PHPackages                             baconfy/prompt - 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. [Templating &amp; Views](/categories/templating)
4. /
5. baconfy/prompt

ActiveLibrary[Templating &amp; Views](/categories/templating)

baconfy/prompt
==============

Manage AI prompts in Laravel with Markdown + YAML front matter, multiple drivers (file/database), and Blade rendering.

v1.1.1(3w ago)2316↑121.9%AGPL-3.0-or-laterPHPPHP ^8.3CI passing

Since May 8Pushed 1w agoCompare

[ Source](https://github.com/baconfy/prompt)[ Packagist](https://packagist.org/packages/baconfy/prompt)[ RSS](/packages/baconfy-prompt/feed)WikiDiscussions main Synced 1w ago

READMEChangelogDependencies (12)Versions (10)Used By (0)

 [![Prompt](https://raw.githubusercontent.com/baconfy/prompt/main/docs/presentation.jpg)](https://raw.githubusercontent.com/baconfy/prompt/main/docs/presentation.jpg)

[![Tests](https://github.com/baconfy/prompt/actions/workflows/tests.yml/badge.svg)](https://github.com/baconfy/prompt/actions/workflows/tests.yml)[![Latest Version](https://camo.githubusercontent.com/b79e3a804a237f5f7c02e562e44c2c5689fc19e0f3807773accb40a4edaf55ac/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6261636f6e66792f70726f6d70742e737667)](https://packagist.org/packages/baconfy/prompt)[![License](https://camo.githubusercontent.com/2f180ae9326bb5ee216ece24fd89073ac87bedf0991384812624530606dc61e2/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f6261636f6e66792f70726f6d70742e737667)](https://packagist.org/packages/baconfy/prompt)[![Total Downloads](https://camo.githubusercontent.com/a44e42c4541442a5d54453ccbefd048c94381a9ec2398b8326921b3b4a9918a6/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6261636f6e66792f70726f6d70742e737667)](https://packagist.org/packages/baconfy/prompt)[![PHP Version](https://camo.githubusercontent.com/7e658c33acbf86c2d65a43df4e4cd176e75573abb88ab1e0fd8016943d32acc1/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f7068702d762f6261636f6e66792f70726f6d70742e737667)](https://packagist.org/packages/baconfy/prompt)

Manage AI prompts in Laravel as Markdown files (with optional YAML front matter) or database records, rendered through Blade.

Why
---

[](#why)

LLM prompts are configuration. They drift across the codebase, get duplicated, and end up hardcoded as long strings inside services. This package treats prompts as first-class assets:

- One file or DB record per prompt
- YAML front matter for model/temperature/required variables
- Blade rendering for variable interpolation
- Drivers for file and database storage
- Strict validation of required variables

Requirements
------------

[](#requirements)

- PHP 8.3+
- Laravel 12+

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

[](#installation)

```
composer require baconfy/prompt
```

The service provider auto-registers. Publish what you need:

```
php artisan vendor:publish --tag=prompt-config
php artisan vendor:publish --tag=prompt-migrations    # only if you plan to use the database driver
php artisan migrate
```

Quick start
-----------

[](#quick-start)

Create a prompt at `resources/prompts/welcome.md`:

```
---
model: claude-opus-4-5
temperature: 0.7
required: [name]
---
You are a helpful assistant. Greet {{ $name }} warmly and ask how you can help today.
```

Render it:

```
$prompt = prompt('welcome', ['name' => 'John']);

$prompt->content;           // rendered string
$prompt->metadata['model']; // 'claude-opus-4-5'
(string) $prompt;           // same as ->content (implements Stringable)
```

Use the metadata to drive your LLM call:

```
$prompt = prompt('welcome', ['name' => 'John']);

$response = $anthropic->messages()->create([
    'model'       => $prompt->metadata['model'],
    'temperature' => $prompt->metadata['temperature'],
    'messages'    => [['role' => 'user', 'content' => (string) $prompt]],
]);
```

Front matter
------------

[](#front-matter)

Front matter is an optional YAML block at the top of the prompt:

```
---
model: claude-opus-4-5
temperature: 0.7
required: [user_name, context]
description: Onboarding greeting
tags: [onboarding, greeting]
---
Hello {{ $user_name }}! Considering {{ $context }}, welcome aboard.
```

Behavior:

- If the file does **not** start with `---`, it is treated as plain content (no metadata, no validation, just Blade).
- `required: [...]` is enforced. Missing variables throw `MissingRequiredVariablesException`.
- Anything else is metadata. The package does not interpret it; read it via `$prompt->metadata['anything']`.

Drivers
-------

[](#drivers)

### File driver

[](#file-driver)

Default. Reads from `resources/prompts/*.md`. Dot notation maps to subfolders:

```
prompt('auth.login');               // resources/prompts/auth/login.md
prompt('emails.welcome.subject');   // resources/prompts/emails/welcome/subject.md
```

### Database driver

[](#database-driver)

Stores prompts in a `prompts` table with `name` and `content` columns. The content column holds raw markdown — exactly the same format as the file driver. Front matter, when present, sits inline at the top of `content`.

```
use Baconfy\Prompt\Models\Prompt;

Prompt::create([
    'name'    => 'welcome',
    'content' =>  'John']);   // works the same way
```

Migrating prompts between file and database drivers is a copy/paste — the storage format is identical.

Switch the default driver in `.env`:

```
PROMPTS_DRIVER=database
PROMPTS_CONNECTION=mysql       # optional, falls back to DB_CONNECTION
PROMPTS_TABLE=prompts          # optional
```

Or use both side by side:

```
// config/prompt.php
'drivers' => [
    'system' => [
        'driver' => 'file',
        'folder' => resource_path('prompts/system'),
    ],
    'user' => [
        'driver' => 'database',
        'table'  => 'user_prompts',
    ],
],
```

```
Prompt::driver('system')->find('welcome');
Prompt::driver('user')->find('welcome');
```

API
---

[](#api)

### Helper

[](#helper)

```
prompt(string $name, array $data = []): RenderedPrompt
```

### Facade

[](#facade)

```
use Baconfy\Prompt\Facades\Prompt;

Prompt::get('welcome', ['name' => 'John']);   // RenderedPrompt
Prompt::source('welcome');                     // ParsedFrontMatter|null
Prompt::driver('database');                    // Driver instance (defaults to active)
```

### `RenderedPrompt`

[](#renderedprompt)

```
$prompt->content;    // rendered string
$prompt->metadata;   // array
(string) $prompt;    // same as ->content
```

### `ParsedFrontMatter`

[](#parsedfrontmatter)

What `Prompt::source()` returns — pre-render. Useful when you want metadata without rendering Blade:

```
$source = Prompt::source('welcome');
$source->metadata['model'];   // 'claude-opus-4-5'
$source->content;             // raw template, with Blade tags untouched
```

### `Prompt` model

[](#prompt-model)

Eloquent model on the `prompts` table. Use it to seed, update, or otherwise manage DB-backed prompts:

```
use Baconfy\Prompt\Models\Prompt as PromptModel;

PromptModel::create([
    'name'    => 'welcome',
    'content' => update(['content' => 'Hi {{ $name }}!']);
```

The driver itself does not depend on this model — it reads via Query Builder. The model is a convenience for your CRUD layer.

CLI
---

[](#cli)

Three Artisan commands ship with the package:

```
php artisan prompt:list                              # list prompts across all configured drivers
php artisan prompt:list database                     # list prompts for a specific driver
php artisan prompt:show welcome                      # show metadata and raw content for a single prompt
php artisan prompt:show welcome --driver=database    # target a specific driver
php artisan prompt:make welcome                      # scaffold resources/prompts/welcome.md
```

`prompt:list` accepts an optional driver argument (the name of any driver defined in `config/prompt.php`); omitting it iterates all drivers. `prompt:show` accepts a `--driver=` option to target a specific named driver instead of the active default. `prompt:make` is file-driver only — database prompts are created directly via the `prompts` table.

`prompt:show` is your debug companion: confirm what `Prompt::source('welcome')` will return before rendering anywhere.

Testing
-------

[](#testing)

### Faking prompts

[](#faking-prompts)

In your application's tests, replace the real driver with a stub so prompts don't hit the filesystem or database:

```
use Baconfy\Prompt\Facades\Prompt;
use Baconfy\Prompt\RenderedPrompt;

Prompt::fake([
    'welcome' => 'Hello stub!',
    'auth.login' => new RenderedPrompt('Stub login.', ['model' => 'gpt-4']),
]);

// code under test
prompt('welcome', ['name' => 'whatever']);

Prompt::assertCalled('welcome');
Prompt::assertNotCalled('checkout');
```

A plain string stub is wrapped in a `RenderedPrompt` with empty metadata; pass a `RenderedPrompt` instance when your code reads `$prompt->metadata`.

### Factories

[](#factories)

The `Prompt` model ships with an Eloquent factory for seeding test data when you use the database driver:

```
use Baconfy\Prompt\Models\Prompt;

Prompt::factory()->create();
Prompt::factory()->count(5)->create();
Prompt::factory()->create(['name' => 'welcome', 'content' => 'Hi!']);
```

Configuration
-------------

[](#configuration)

`config/prompt.php`:

```
return [
    'default' => env('PROMPTS_DRIVER', 'file'),

    'drivers' => [
        'file' => [
            'driver' => 'file',
            'folder' => env('PROMPTS_FOLDER', resource_path('prompts')),
        ],
        'database' => [
            'driver'     => 'database',
            'connection' => env('PROMPTS_CONNECTION'),
            'table'      => env('PROMPTS_TABLE', 'prompts'),
        ],
    ],
];
```

The `drivers` array supports any number of named entries. Each one has a `driver` field (`file` or `database`) plus the keys that driver needs. The same type can appear under multiple names (e.g. two file folders for system vs. user prompts).

Exceptions
----------

[](#exceptions)

```
use Baconfy\Prompt\Exceptions\PromptNotFoundException;
use Baconfy\Prompt\Exceptions\MissingRequiredVariablesException;
```

- `PromptNotFoundException` — thrown by `Prompt::get()` when the name is not found by the active driver. Exposes `->name`.
- `MissingRequiredVariablesException` — thrown when the prompt declares `required` in its metadata and any variable is missing from `$data`. Exposes `->variables` (the list of missing names).

Admin Panel
-----------

[](#admin-panel)

 [![Prompt](https://raw.githubusercontent.com/baconfy/prompt/main/docs/prompts.png)](https://raw.githubusercontent.com/baconfy/prompt/main/docs/prompts.png)

Optional admin panel for managing prompts stored in the `database` driver. The `file` driver remains read-only and is meant to be managed via Git.

The panel ships as plain Blade views styled with **Tailwind via CDN** — no front-end build step, no JavaScript framework, no extra dependencies. Routes are mounted at `/_prompts` by default whenever `prompt.panel.enabled` is true.

### Authorization

[](#authorization)

Two equivalent options (the callback wins if both are present):

```
// AppServiceProvider::boot() — closure style (like Horizon::auth)
use Baconfy\Prompt\Panel;

Panel::auth(fn ($user = null) => $user?->email === 'you@example.com');
```

```
// or via a regular Gate
use Illuminate\Support\Facades\Gate;

Gate::define('viewPrompts', fn ($user = null) => $user?->isAdmin());
```

If neither is defined, the panel responds **403**.

### Features

[](#features)

- **Index** at `/_prompts` — paginated list of every prompt name (latest version per name) with a `vN` badge and live search.
- **Editor** at `/_prompts/create` and `/_prompts/{prompt}/edit` — form with live preview that renders the prompt through Blade using JSON variables. Refuses to save if the content is identical to the current latest version.
- **Versions** at `/_prompts/{prompt}/versions` — accordion of every revision with a unified diff against the current version. Each older row can be **Restored** (creates a new version on top with the chosen content) or **Deleted**.

### Versioning model

[](#versioning-model)

Every save inserts a new row in the `prompts` table; existing rows are never updated. Rows sharing a `name` form a version chain:

- First save → new row with `root_id = null` (the root, v1).
- Subsequent saves → new row with `root_id` pointing to the v1 row.
- `Prompt::get('welcome')` always resolves to the latest version (`MAX(id)` per `name`).

### Configuration

[](#configuration-1)

```
// config/prompt.php
'panel' => [
    'enabled'    => env('PROMPTS_PANEL_ENABLED', true),
    'path'       => env('PROMPTS_PANEL_PATH', '_prompts'),
    'gate'       => 'viewPrompts',
    'middleware' => ['web'],
],
```

Publish the views to customize them:

```
php artisan vendor:publish --tag=prompt-views
```

Security
--------

[](#security)

Blade compiles prompt content. **Do not load prompt content from untrusted sources.** A prompt containing `{{ system('rm -rf /') }}` would execute that PHP if rendered. Treat prompts as code, not user input.

The panel is gated by `Panel::auth()` / Gate and ships behind the `web` middleware group by default — it is **not** safe to expose publicly without authorization.

Development
-----------

[](#development)

Run the package test suite:

```
composer test            # pest
composer test:coverage   # 100% required
composer test:types      # phpstan
composer format          # pint
```

Boot a local dev environment (Orchestra Testbench workbench + SQLite):

```
composer dev             # builds the workbench DB and serves at http://127.0.0.1:8000
```

The workbench wires `Panel::auth()` to always allow, so `/` redirects to `/_prompts` ready to use.

Credits
-------

[](#credits)

- [Renato Dehnhardt](https://github.com/rdehnhardt)
- [All contributors](https://github.com/baconfy/prompt/graphs/contributors)

License
-------

[](#license)

See [LICENSE](LICENSE) for details.

###  Health Score

47

—

FairBetter than 93% of packages

Maintenance96

Actively maintained with recent releases

Popularity20

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity54

Maturing project, gaining track record

 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 ~1 days

Total

8

Last Release

25d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/7077461?v=4)[Renato Dehnhardt](/maintainers/rdehnhardt)[@rdehnhardt](https://github.com/rdehnhardt)

---

Top Contributors

[![rdehnhardt](https://avatars.githubusercontent.com/u/7077461?v=4)](https://github.com/rdehnhardt "rdehnhardt (31 commits)")

---

Tags

laravellaravel-ailaravel-ai-sdklaravel-frameworklaravelaiblademarkdownllmpromptfront matter

###  Code Quality

TestsPest

Static AnalysisPHPStan

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/baconfy-prompt/health.svg)

```
[![Health](https://phpackages.com/badges/baconfy-prompt/health.svg)](https://phpackages.com/packages/baconfy-prompt)
```

###  Alternatives

[laravel/ai

The official AI SDK for Laravel.

9782.1M153](/packages/laravel-ai)[psalm/plugin-laravel

Psalm plugin for Laravel

3325.1M337](/packages/psalm-plugin-laravel)[moonshine/moonshine

Laravel administration panel

1.3k239.9k72](/packages/moonshine-moonshine)[roots/acorn

Framework for Roots WordPress projects built with Laravel components.

9732.3M121](/packages/roots-acorn)[tightenco/jigsaw

Simple static sites with Laravel's Blade.

2.2k449.3k30](/packages/tightenco-jigsaw)[tallstackui/tallstackui

TallStackUI is a powerful suite of Blade components that elevate your workflow of Livewire applications.

719160.4k12](/packages/tallstackui-tallstackui)

PHPackages © 2026

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