PHPackages                             rmh/laravel-openui - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. rmh/laravel-openui

ActiveLibrary

rmh/laravel-openui
==================

OpenUI Generative UI integration for the Laravel AI SDK - inject OpenUI Lang system prompts, define component libraries, and stream structured UI responses.

0.1.1(1w ago)10MITPHPPHP ^8.3CI passing

Since Mar 13Pushed 1w agoCompare

[ Source](https://github.com/RanaMoizHaider/laravel-openui)[ Packagist](https://packagist.org/packages/rmh/laravel-openui)[ RSS](/packages/rmh-laravel-openui/feed)WikiDiscussions main Synced today

READMEChangelog (2)Dependencies (5)Versions (3)Used By (0)

laravel-openui
==============

[](#laravel-openui)

[![Latest Version on Packagist](https://camo.githubusercontent.com/7844c7fe54e645553369bdcfe5a8179d96eff98dd0877cb61a8dab8b51ad6967/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f726d682f6c61726176656c2d6f70656e75692e737667)](https://packagist.org/packages/rmh/laravel-openui)[![Tests](https://camo.githubusercontent.com/46d9ec67eaf2efefa49e5908a3467dddc0a041cf3a66789f2032f59659f490ed/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f72616e616d6f697a6861696465722f6c61726176656c2d6f70656e75692f74657374732e796d6c3f6c6162656c3d7465737473)](https://github.com/ranamoizhaider/laravel-openui/actions)[![License](https://camo.githubusercontent.com/30679cbee3ba6bdd9c2aa31952fdf28905772b53b4708619ff3b4588c70270d9/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f72616e616d6f697a6861696465722f6c61726176656c2d6f70656e7569)](LICENSE.md)

**OpenUI Generative UI integration for the Laravel AI SDK.**

This package connects [OpenUI](https://openui.com) — the open standard for Generative UI — with the [Laravel AI SDK](https://laravel.com/docs/12.x/ai-sdk). It handles system prompt injection, component library management, caching, and streaming, so your agents can respond with structured, interactive UI instead of plain text.

---

How It Works
------------

[](#how-it-works)

OpenUI works in four steps:

```
Component Library → System Prompt → LLM → OpenUI Lang → Frontend Renderer

```

1. You define which React components the LLM is allowed to generate.
2. This package injects a system prompt into your agent's instructions describing those components and the OpenUI Lang syntax.
3. The LLM responds in OpenUI Lang (a compact, streaming-native format).
4. Your frontend's `` from `@openuidev/react-lang` parses and renders it live.

---

Installation
------------

[](#installation)

```
composer require rmh/laravel-openui
```

Publish the config file:

```
php artisan vendor:publish --tag=openui
```

---

Quick Start
-----------

[](#quick-start)

### Option 1: Global Middleware (zero-touch, all agents)

[](#option-1-global-middleware-zero-touch-all-agents)

Register the middleware once in your `AppServiceProvider` and every agent will automatically receive the OpenUI system prompt:

```
// app/Providers/AppServiceProvider.php

use RMH\OpenUI\Middleware\InjectOpenUIPrompt;
use Laravel\Ai\Facades\Ai;

public function boot(): void
{
    Ai::middleware([InjectOpenUIPrompt::class]);
}
```

Your agents need no changes. Stream the response back to your OpenUI frontend:

```
Route::post('/chat', function (Request $request) {
    return MyAgent::make()
        ->stream($request->input('message'))
        ->usingVercelDataProtocol();
});
```

---

### Option 2: `GeneratesUI` Trait (explicit opt-in per agent)

[](#option-2-generatesui-trait-explicit-opt-in-per-agent)

Add the trait to agents that should produce UI. Rename `instructions()` to `agentInstructions()`:

```
use RMH\OpenUI\Concerns\GeneratesUI;
use Laravel\Ai\Contracts\Agent;
use Laravel\Ai\Promptable;

class HotelSearchAgent implements Agent
{
    use Promptable, GeneratesUI;

    protected function agentInstructions(): string
    {
        return 'You are a helpful hotel search assistant.';
    }
}
```

Toggle UI per call:

```
// UI enabled (default)
HotelSearchAgent::make()->prompt('Find hotels in Paris');

// UI disabled for this call
HotelSearchAgent::make()->withoutUI()->prompt('Find hotels in Paris');
```

---

### Option 3: Per-agent Middleware

[](#option-3-per-agent-middleware)

Add the middleware only to specific agents:

```
use RMH\OpenUI\Middleware\InjectOpenUIPrompt;
use Laravel\Ai\Contracts\Agent;
use Laravel\Ai\Contracts\HasMiddleware;
use Laravel\Ai\Promptable;

class HotelSearchAgent implements Agent, HasMiddleware
{
    use Promptable;

    public function instructions(): string
    {
        return 'You are a helpful hotel search assistant.';
    }

    public function middleware(): array
    {
        return [new InjectOpenUIPrompt];
    }
}
```

---

### Option 4: Anonymous Agents / Inline Calls

[](#option-4-anonymous-agents--inline-calls)

```
use RMH\OpenUI\Facades\OpenUI;
use function Laravel\Ai\{agent};

$response = agent(
    instructions: 'You are a travel assistant.' . "\n\n" . OpenUI::systemPrompt(),
)->prompt('Find hotels in Paris');
```

---

Defining Your Component Library
-------------------------------

[](#defining-your-component-library)

### In `config/openui.php`

[](#in-configopenuiphp)

```
'components' => [
    'Card' => [
        'title'       => 'string',
        'description' => 'string?',   // ? = optional
        'imageUrl'    => 'string?',
        'ctaLabel'    => 'string?',
    ],
    'Carousel' => [
        'cards' => 'Card[]',           // nested component reference
    ],
    'Table' => [
        'columns' => 'array',
        'rows'    => 'array',
    ],
    'Alert' => [
        'type'    => 'enum:info|success|warning|error',
        'title'   => 'string',
        'message' => 'string?',
    ],
],
```

Supported prop types: `string`, `int`, `float`, `bool`, `array`, `ComponentName[]`, `enum:a|b|c`. Append `?` to mark any type as optional.

---

### Via the Facade (programmatic / runtime)

[](#via-the-facade-programmatic--runtime)

```
use RMH\OpenUI\Facades\OpenUI;

// Register one component
OpenUI::component('PriceTag', [
    'amount'   => 'string',
    'currency' => 'string?',
]);

// Register many at once
OpenUI::library([
    'Chart'     => ['type' => 'enum:bar|line|pie', 'data' => 'array'],
    'MapPin'    => ['lat' => 'float', 'lng' => 'float', 'label' => 'string?'],
]);
```

The cache is automatically invalidated when you add components via the facade.

---

### Via the Artisan Command

[](#via-the-artisan-command)

Scaffold a typed component definition class:

```
php artisan openui:component Card --props="title:string,description:string?,imageUrl:string?"
```

This generates `app/Ai/OpenUI/Components/CardComponent.php`. Register it in your service provider:

```
use RMH\OpenUI\Facades\OpenUI;
use App\Ai\OpenUI\Components\CardComponent;

OpenUI::component((new CardComponent)->name(), (new CardComponent)->props());
```

---

### Export for Frontend

[](#export-for-frontend)

Export your component definitions to TypeScript/Zod for your frontend:

```
php artisan openui:export
```

This generates `resources/js/openui.ts` with Zod schemas:

```
// Auto-generated by laravel-openui
import { z } from 'zod';

export const CardSchema = z.object({
  title: z.string(),
  description: z.string().optional(),
  imageUrl: z.string().optional(),
});

export const openUISchema = z.object({
  Card: CardSchema,
});
```

**Export options:**

OptionDescription`--path=...`Custom output path (default: `resources/js/openui.ts`)`--format=zod|ts|json`Output format (default: `zod`)`--types`TypeScript types only (shorthand for `--format=ts`)`--force`Overwrite existing file**Examples:**

```
# Export to custom path
php artisan openui:export --path=frontend/src/openui.ts

# Export TypeScript types only (no Zod)
php artisan openui:export --types

# Export as JSON
php artisan openui:export --format=json --path=schema.json

# Force overwrite
php artisan openui:export --force
```

---

Configuration Reference
-----------------------

[](#configuration-reference)

```
// config/openui.php

'enabled'                => env('OPENUI_ENABLED', true),
'design_system'          => env('OPENUI_DESIGN_SYSTEM', 'shadcn'),
'stream_protocol'        => env('OPENUI_STREAM_PROTOCOL', 'vercel'),
'system_prompt_placement'=> 'append',  // 'append' | 'prepend'
'custom_system_prompt'   => null,      // override the entire generated prompt

'components' => [...],

'allowed_agents' => [],               // empty = all agents; list FQCN to restrict

'cache' => [
    'enabled' => env('OPENUI_CACHE_ENABLED', true),
    'store'   => env('OPENUI_CACHE_STORE', null),
    'ttl'     => env('OPENUI_CACHE_TTL', 3600),
],
```

---

Frontend Integration
--------------------

[](#frontend-integration)

### Option 1: Use Exported Schema (Recommended)

[](#option-1-use-exported-schema-recommended)

Export your component definitions and import them directly:

```
php artisan openui:export
```

Then in your frontend:

```
import { Renderer, createLibrary, defineComponent } from '@openuidev/react-lang';
import { CardSchema, CarouselSchema } from './openui';
import { Card, Carousel } from './components';

const components = [
  defineComponent({
    name: 'Card',
    props: CardSchema,
    component: ({ props }) => ,
  }),
  defineComponent({
    name: 'Carousel',
    props: CarouselSchema,
    component: ({ props }) => ,
  }),
];

export const library = createLibrary({ root: 'Card', components });

```

### Option 2: Manual Schema Definition

[](#option-2-manual-schema-definition)

Define schemas manually on the frontend:

```
import { Renderer, createLibrary, defineComponent } from '@openuidev/react-lang';
import { z } from 'zod';

const Card = defineComponent({
    name: 'Card',
    props: z.object({
        title: z.string(),
        description: z.string().optional(),
        imageUrl: z.string().optional(),
        ctaLabel: z.string().optional(),
    }),
    component: ({ props }) => ,
});

export const library = createLibrary({ root: 'Card', components: [Card] });

```

---

Inspecting the Generated System Prompt
--------------------------------------

[](#inspecting-the-generated-system-prompt)

```
use RMH\OpenUI\Facades\OpenUI;

// View what's being injected
dd(OpenUI::systemPrompt());

// Flush and regenerate
OpenUI::flushCache();
```

---

Testing
-------

[](#testing)

When writing tests for agents that use OpenUI, you can temporarily disable injection:

```
config(['openui.enabled' => false]);
```

Or assert on the generated prompt:

```
use RMH\OpenUI\Facades\OpenUI;

$this->assertStringContainsString('Card', OpenUI::systemPrompt());
```

---

Changelog
---------

[](#changelog)

Please see [CHANGELOG.md](CHANGELOG.md).

License
-------

[](#license)

MIT — see [LICENSE.md](LICENSE.md).

###  Health Score

38

—

LowBetter than 86% of packages

Maintenance98

Actively maintained with recent releases

Popularity2

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity39

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

2

Last Release

9d ago

PHP version history (2 changes)0.1.0PHP ^8.2

0.1.1PHP ^8.3

### Community

Maintainers

![](https://www.gravatar.com/avatar/892294ff938f797c91632aa8225eb83b27483ae1dc666185685fb06ae048784b?d=identicon)[rmh](/maintainers/rmh)

---

Top Contributors

[![RanaMoizHaider](https://avatars.githubusercontent.com/u/58527494?v=4)](https://github.com/RanaMoizHaider "RanaMoizHaider (5 commits)")

---

Tags

laravelaistreamingAgentlaravel-aiopenuigenerative-ui

###  Code Quality

TestsPHPUnit

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/rmh-laravel-openui/health.svg)

```
[![Health](https://phpackages.com/badges/rmh-laravel-openui/health.svg)](https://phpackages.com/packages/rmh-laravel-openui)
```

###  Alternatives

[joshcirre/instruckt-laravel

Visual feedback for AI coding agents — Laravel MCP package

1412.8k](/packages/joshcirre-instruckt-laravel)[sbsaga/toon

🧠 TOON for Laravel — a compact, human-readable, and token-efficient data format for AI prompts &amp; LLM contexts. Perfect for ChatGPT, Gemini, Claude, Mistral, and OpenAI integrations (JSON ⇄ TOON).

589.9k](/packages/sbsaga-toon)[vectorifyai/vectorify-laravel

Vectorify package for Laravel. The fastest way to ask AI about your data.

196.1k](/packages/vectorifyai-vectorify-laravel)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
