Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message
Agents
zpmlabs/laravel-package-quick-demo
claude-code
cursor
laravel-packages
artisan-commands
sqlite
migrations
demo-isolation
agent-instructions

Use this file when adding support for zpmlabs/laravel-package-quick-demo to another Laravel package.

Install
php artisan boost:add-skill zpmlabs/laravel-package-quick-demo

Save this content to: AGENTS.md

# Agent Instructions — Laravel Package Quick Demo

Use this file when adding support for `zpmlabs/laravel-package-quick-demo` to another Laravel package.

The package README is good for humans. This file is stricter and is intended for coding agents such as Codex, Copilot Agent, Cursor Agent, Claude Code, or similar tools.

---

## Objective

Add a working, isolated quick demo to a Laravel package.

After implementation, the package user should be able to run:

```bash
php artisan quick-demo:install blog-demo
```

and immediately test the package demo without manually editing `.env`, `config/database.php`, `routes/web.php`, or copying demo files by hand.

---

## Hard rules

Do not violate these rules.

* Do not modify the host application's `.env` file.
* Do not modify the host application's `config/database.php` file.
* Do not modify the host application's `routes/web.php` file.
* Do not create demo tables in the default database connection.
* Do not seed the default database connection.
* Do not register unprefixed demo routes.
* Do not use generic demo keys such as `demo`, `test`, or `example`.
* Do not publish files into generic folders such as `public/demo`, `resources/views/demo`, or `storage/app/demo`.
* Do not overwrite generated files unless the command is run with `--force`.
* Keep all code, class names, method names, comments, and docs in English.

---

## Required package dependency

Add this package to the target package dependencies:

```json
{
  "require": {
    "zpmlabs/laravel-package-quick-demo": "^0.1"
  }
}
```

Use the latest compatible version if the package already exists with a newer release.

---

## Recommended demo structure

Create this structure inside the target package:

```txt
examples/
  database/
    demo.sqlite.stub
  migrations/
    2026_01_01_000001_create_demo_posts_table.php
  routes/
    demo.php
  views/
    index.blade.php
    show.blade.php
  assets/
    demo.css
    demo.js
  storage/
    images/
      demo-cover.jpg
  config/
    demo.php
```

Only create folders that are needed.

For a database-only demo, this is enough:

```txt
examples/
  database/
    demo.sqlite.stub
  migrations/
    2026_01_01_000001_create_demo_records_table.php
```

---

## Demo key naming

Use a package-specific demo key.

Good:

```txt
blog-demo
users-demo
orders-demo
comments-demo
```

Bad:

```txt
demo
test
example
sample
```

The demo key is used for route prefixes, view namespaces, and generated paths, so it must be unique and predictable.

---

## Database naming

Use a package-specific database name.

Good:

```txt
blog_demo
users_demo
orders_demo
```

Bad:

```txt
demo
sqlite
test
example
```

Example:

```php
databaseName: 'blog_demo'
```

This should create:

```txt
database/quick-demos/blog_demo.sqlite
```

and register connection:

```txt
quick_demo_blog_demo
```

---

## Table naming

Use demo-specific table names.

Good:

```txt
demo_posts
demo_users
demo_orders
```

Bad:

```txt
posts
users
orders
```

Do not reuse real application table names unless the demo intentionally targets existing application data, which should be avoided by default.

---

## Service provider registration

Register the demo in the target package service provider `boot()` method.

```php
<?php

namespace Vendor\BlogPackage;

use Illuminate\Support\ServiceProvider;
use ZPMLabs\LaravelPackageQuickDemo\Facades\QuickDemo;
use ZPMLabs\LaravelPackageQuickDemo\Support\DemoDefinition;

class BlogPackageServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        QuickDemo::register(
            DemoDefinition::make(
                key: 'blog-demo',
                name: 'Blog Demo',
                databaseName: 'blog_demo',
                databaseStubPath: __DIR__ . '/../examples/database/demo.sqlite.stub',
                migrationsPath: __DIR__ . '/../examples/migrations',
                seeders: [
                    \Vendor\BlogPackage\Database\Seeders\BlogDemoSeeder::class,
                ],
                routesPath: __DIR__ . '/../examples/routes/demo.php',
                viewsPath: __DIR__ . '/../examples/views',
                assetsPath: __DIR__ . '/../examples/assets',
                storagePath: __DIR__ . '/../examples/storage',
                configPath: __DIR__ . '/../examples/config/demo.php',
            )
        );
    }
}
```

Only include paths that actually exist.

If there are no routes, omit `routesPath`.

If there are no views, omit `viewsPath`.

If there are no assets, omit `assetsPath`.

If there are no storage files, omit `storagePath`.

If there is no config file, omit `configPath`.

---

## SQLite stub

Create:

```txt
examples/database/demo.sqlite.stub
```

An empty file is acceptable:

```bash
mkdir -p examples/database
touch examples/database/demo.sqlite.stub
```

Prefer an empty SQLite stub plus migrations and seeders over a prebuilt SQLite database.

---

## Migration pattern

Every demo migration must explicitly use the quick-demo connection.

```php
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
use ZPMLabs\LaravelPackageQuickDemo\Facades\QuickDemo;

return new class extends Migration
{
    public function getConnection(): string
    {
        return QuickDemo::connectionName('blog-demo');
    }

    public function up(): void
    {
        Schema::connection($this->getConnection())->create('demo_posts', function (Blueprint $table): void {
            $table->id();
            $table->string('title');
            $table->text('body')->nullable();
            $table->boolean('is_published')->default(true);
            $table->timestamps();
        });
    }

public function down(): void
    {
        Schema::connection($this->getConnection())->dropIfExists('demo_posts');
    }
};
```

Do not use:

```php
Schema::create('posts', function (Blueprint $table): void {
    // Wrong for demo package tables.
});
```

---

## Seeder pattern

Every demo seeder must write to the quick-demo connection.

```php
<?php

namespace Vendor\BlogPackage\Database\Seeders;

use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use ZPMLabs\LaravelPackageQuickDemo\Facades\QuickDemo;

class BlogDemoSeeder extends Seeder
{
    public function run(): void
    {
        DB::connection(QuickDemo::connectionName('blog-demo'))
            ->table('demo_posts')
            ->insert([
                [
                    'title' => 'First demo post',
                    'body' => 'This post belongs to the isolated quick demo database.',
                    'is_published' => true,
                    'created_at' => now(),
                    'updated_at' => now(),
                ],
            ]);
    }
}
```

Do not use the default connection:

```php
DB::table('posts')->insert([...]);
```

---

## Model pattern

Every demo model must use the quick-demo connection.

```php
<?php

namespace Vendor\BlogPackage\Models;

use Illuminate\Database\Eloquent\Model;
use ZPMLabs\LaravelPackageQuickDemo\Facades\QuickDemo;

class DemoPost extends Model
{
    protected $table = 'demo_posts';

    protected $guarded = [];

    public function getConnectionName(): string
    {
        return QuickDemo::connectionName('blog-demo');
    }
}
```

Use demo-specific model names when possible:

```txt
DemoPost
DemoUser
DemoOrder
```

---

## Route pattern

Create:

```txt
examples/routes/demo.php
```

Example:

```php
<?php

use Illuminate\Support\Facades\Route;
use Vendor\BlogPackage\Http\Controllers\BlogDemoController;

Route::get('/', [BlogDemoController::class, 'index'])->name('index');
Route::get('/posts/{post}', [BlogDemoController::class, 'show'])->name('show');
```

The quick-demo package mounts these routes under:

```txt
/quick-demo/blog-demo
```

and names them under:

```txt
quick-demo.blog_demo.
```

Do not manually add routes to the host application's `routes/web.php`.

---

## Controller pattern

Use demo models and demo views.

```php
<?php

namespace Vendor\BlogPackage\Http\Controllers;

use Vendor\BlogPackage\Models\DemoPost;

class BlogDemoController
{
    public function index()
    {
        return view('quick-demo-blog-demo::index', [
            'posts' => DemoPost::query()->latest()->get(),
        ]);
    }

    public function show(DemoPost $post)
    {
        return view('quick-demo-blog-demo::show', [
            'post' => $post,
        ]);
    }
}
```

---

## View pattern

Put views in:

```txt
examples/views
```

Use the generated namespace:

```txt
quick-demo-blog-demo
```

Example:

```php
return view('quick-demo-blog-demo::index');
```

Do not use generic view namespaces like:

```txt
demo::index
example::index
```

---

## Asset pattern

Put assets in:

```txt
examples/assets
```

They will be published to:

```txt
public/vendor/quick-demos/blog-demo
```

Use them in Blade:

```blade
<link rel="stylesheet" href="{{ asset('vendor/quick-demos/blog-demo/demo.css') }}">
<script src="{{ asset('vendor/quick-demos/blog-demo/demo.js') }}" defer></script>
```

Do not publish demo assets directly to `public/` root.

---

## Storage pattern

Put demo storage files in:

```txt
examples/storage
```

They will be copied to:

```txt
storage/app/quick-demos/blog-demo
```

Use:

```php
storage_path('app/quick-demos/blog-demo/images/demo-cover.jpg')
```

Do not copy files to generic storage folders.

---

## Config pattern

Put optional demo config in:

```txt
examples/config/demo.php
```

It will be copied to:

```txt
config/quick-demos/blog-demo.php
```

Do not modify existing application config files.

---

## Hook pattern

Use hooks only when normal migrations, seeders, routes, views, assets, storage, and config are not enough.

Example registration:

```php
DemoDefinition::make(
    key: 'blog-demo',
    name: 'Blog Demo',
    databaseName: 'blog_demo',
    afterInstall: \Vendor\BlogPackage\Demo\AfterInstallBlogDemo::class,
)
```

Hook class:

```php
<?php

namespace Vendor\BlogPackage\Demo;

use ZPMLabs\LaravelPackageQuickDemo\Support\QuickDemoContext;

class AfterInstallBlogDemo
{
    public function handle(QuickDemoContext $context): void
    {
        // Custom demo setup logic.
    }
}
```

Available context fields:

```php
$context->definition;
$context->databasePath;
$context->connectionName;
$context->routePrefix;
$context->routeNamePrefix;
$context->viewNamespace;
$context->assetsDestination;
$context->storageDestination;
$context->configDestination;
$context->options;
```

---

## Validation checklist

After implementing the demo, run these commands in a Laravel test app:

```bash
composer dump-autoload
php artisan quick-demo:list
php artisan quick-demo:show blog-demo
php artisan quick-demo:install blog-demo --fresh --force
php artisan route:list
```

Confirm all of the following:

* The demo appears in `quick-demo:list`.
* `quick-demo:show blog-demo` displays correct paths.
* The SQLite database exists in `database/quick-demos`.
* The generated connection name is package-specific.
* Demo migrations ran on the quick-demo connection.
* Demo seeders inserted data into the quick-demo database.
* No demo tables were created in the default database.
* Demo routes are mounted under `/quick-demo/{demo-key}`.
* Demo route names are prefixed.
* Demo views render correctly.
* Demo assets load correctly.
* Demo storage files are copied if configured.
* Demo config is copied if configured.
* `.env` was not changed.
* `config/database.php` was not changed.
* `routes/web.php` was not changed.

---

## Common mistakes to avoid

Do not do this:

```php
Schema::create('posts', function (Blueprint $table): void {
    // Wrong connection and wrong table name for demo isolation.
});
```

Do this instead:

```php
Schema::connection(QuickDemo::connectionName('blog-demo'))->create('demo_posts', function (Blueprint $table): void {
    // Correct.
});
```

Do not do this:

```php
DB::table('posts')->insert([...]);
```

Do this instead:

```php
DB::connection(QuickDemo::connectionName('blog-demo'))->table('demo_posts')->insert([...]);
```

Do not do this:

```php
Route::get('/demo', DemoController::class);
```

Do this instead:

```php
// examples/routes/demo.php
Route::get('/', [BlogDemoController::class, 'index'])->name('index');
```

The quick-demo package will add the route prefix.

---

## Expected final result

A user should be able to do this:

```bash
composer require vendor/blog-package
php artisan quick-demo:list
php artisan quick-demo:install blog-demo
php artisan serve
```

Then open:

```txt
http://localhost:8000/quick-demo/blog-demo
```

No manual setup should be required.

Agent Instructions — Laravel Package Quick Demo

Use this file when adding support for zpmlabs/laravel-package-quick-demo to another Laravel package.

The package README is good for humans. This file is stricter and is intended for coding agents such as Codex, Copilot Agent, Cursor Agent, Claude Code, or similar tools.


Objective

Add a working, isolated quick demo to a Laravel package.

After implementation, the package user should be able to run:

php artisan quick-demo:install blog-demo

and immediately test the package demo without manually editing .env, config/database.php, routes/web.php, or copying demo files by hand.


Hard rules

Do not violate these rules.

  • Do not modify the host application's .env file.
  • Do not modify the host application's config/database.php file.
  • Do not modify the host application's routes/web.php file.
  • Do not create demo tables in the default database connection.
  • Do not seed the default database connection.
  • Do not register unprefixed demo routes.
  • Do not use generic demo keys such as demo, test, or example.
  • Do not publish files into generic folders such as public/demo, resources/views/demo, or storage/app/demo.
  • Do not overwrite generated files unless the command is run with --force.
  • Keep all code, class names, method names, comments, and docs in English.

Required package dependency

Add this package to the target package dependencies:

{
  "require": {
    "zpmlabs/laravel-package-quick-demo": "^0.1"
  }
}

Use the latest compatible version if the package already exists with a newer release.


Recommended demo structure

Create this structure inside the target package:

examples/
  database/
    demo.sqlite.stub
  migrations/
    2026_01_01_000001_create_demo_posts_table.php
  routes/
    demo.php
  views/
    index.blade.php
    show.blade.php
  assets/
    demo.css
    demo.js
  storage/
    images/
      demo-cover.jpg
  config/
    demo.php

Only create folders that are needed.

For a database-only demo, this is enough:

examples/
  database/
    demo.sqlite.stub
  migrations/
    2026_01_01_000001_create_demo_records_table.php

Demo key naming

Use a package-specific demo key.

Good:

blog-demo
users-demo
orders-demo
comments-demo

Bad:

demo
test
example
sample

The demo key is used for route prefixes, view namespaces, and generated paths, so it must be unique and predictable.


Database naming

Use a package-specific database name.

Good:

blog_demo
users_demo
orders_demo

Bad:

demo
sqlite
test
example

Example:

databaseName: 'blog_demo'

This should create:

database/quick-demos/blog_demo.sqlite

and register connection:

quick_demo_blog_demo

Table naming

Use demo-specific table names.

Good:

demo_posts
demo_users
demo_orders

Bad:

posts
users
orders

Do not reuse real application table names unless the demo intentionally targets existing application data, which should be avoided by default.


Service provider registration

Register the demo in the target package service provider boot() method.

<?php

namespace Vendor\BlogPackage;

use Illuminate\Support\ServiceProvider;
use ZPMLabs\LaravelPackageQuickDemo\Facades\QuickDemo;
use ZPMLabs\LaravelPackageQuickDemo\Support\DemoDefinition;

class BlogPackageServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        QuickDemo::register(
            DemoDefinition::make(
                key: 'blog-demo',
                name: 'Blog Demo',
                databaseName: 'blog_demo',
                databaseStubPath: __DIR__ . '/../examples/database/demo.sqlite.stub',
                migrationsPath: __DIR__ . '/../examples/migrations',
                seeders: [
                    \Vendor\BlogPackage\Database\Seeders\BlogDemoSeeder::class,
                ],
                routesPath: __DIR__ . '/../examples/routes/demo.php',
                viewsPath: __DIR__ . '/../examples/views',
                assetsPath: __DIR__ . '/../examples/assets',
                storagePath: __DIR__ . '/../examples/storage',
                configPath: __DIR__ . '/../examples/config/demo.php',
            )
        );
    }
}

Only include paths that actually exist.

If there are no routes, omit routesPath.

If there are no views, omit viewsPath.

If there are no assets, omit assetsPath.

If there are no storage files, omit storagePath.

If there is no config file, omit configPath.


SQLite stub

Create:

examples/database/demo.sqlite.stub

An empty file is acceptable:

mkdir -p examples/database
touch examples/database/demo.sqlite.stub

Prefer an empty SQLite stub plus migrations and seeders over a prebuilt SQLite database.


Migration pattern

Every demo migration must explicitly use the quick-demo connection.

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
use ZPMLabs\LaravelPackageQuickDemo\Facades\QuickDemo;

return new class extends Migration
{
    public function getConnection(): string
    {
        return QuickDemo::connectionName('blog-demo');
    }

    public function up(): void
    {
        Schema::connection($this->getConnection())->create('demo_posts', function (Blueprint $table): void {
            $table->id();
            $table->string('title');
            $table->text('body')->nullable();
            $table->boolean('is_published')->default(true);
            $table->timestamps();
        });
    }

public function down(): void
    {
        Schema::connection($this->getConnection())->dropIfExists('demo_posts');
    }
};

Do not use:

Schema::create('posts', function (Blueprint $table): void {
    // Wrong for demo package tables.
});

Seeder pattern

Every demo seeder must write to the quick-demo connection.

<?php

namespace Vendor\BlogPackage\Database\Seeders;

use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use ZPMLabs\LaravelPackageQuickDemo\Facades\QuickDemo;

class BlogDemoSeeder extends Seeder
{
    public function run(): void
    {
        DB::connection(QuickDemo::connectionName('blog-demo'))
            ->table('demo_posts')
            ->insert([
                [
                    'title' => 'First demo post',
                    'body' => 'This post belongs to the isolated quick demo database.',
                    'is_published' => true,
                    'created_at' => now(),
                    'updated_at' => now(),
                ],
            ]);
    }
}

Do not use the default connection:

DB::table('posts')->insert([...]);

Model pattern

Every demo model must use the quick-demo connection.

<?php

namespace Vendor\BlogPackage\Models;

use Illuminate\Database\Eloquent\Model;
use ZPMLabs\LaravelPackageQuickDemo\Facades\QuickDemo;

class DemoPost extends Model
{
    protected $table = 'demo_posts';

    protected $guarded = [];

    public function getConnectionName(): string
    {
        return QuickDemo::connectionName('blog-demo');
    }
}

Use demo-specific model names when possible:

DemoPost
DemoUser
DemoOrder

Route pattern

Create:

examples/routes/demo.php

Example:

<?php

use Illuminate\Support\Facades\Route;
use Vendor\BlogPackage\Http\Controllers\BlogDemoController;

Route::get('/', [BlogDemoController::class, 'index'])->name('index');
Route::get('/posts/{post}', [BlogDemoController::class, 'show'])->name('show');

The quick-demo package mounts these routes under:

/quick-demo/blog-demo

and names them under:

quick-demo.blog_demo.

Do not manually add routes to the host application's routes/web.php.


Controller pattern

Use demo models and demo views.

<?php

namespace Vendor\BlogPackage\Http\Controllers;

use Vendor\BlogPackage\Models\DemoPost;

class BlogDemoController
{
    public function index()
    {
        return view('quick-demo-blog-demo::index', [
            'posts' => DemoPost::query()->latest()->get(),
        ]);
    }

    public function show(DemoPost $post)
    {
        return view('quick-demo-blog-demo::show', [
            'post' => $post,
        ]);
    }
}

View pattern

Put views in:

examples/views

Use the generated namespace:

quick-demo-blog-demo

Example:

return view('quick-demo-blog-demo::index');

Do not use generic view namespaces like:

demo::index
example::index

Asset pattern

Put assets in:

examples/assets

They will be published to:

public/vendor/quick-demos/blog-demo

Use them in Blade:

<link rel="stylesheet" href="{{ asset('vendor/quick-demos/blog-demo/demo.css') }}">
<script src="{{ asset('vendor/quick-demos/blog-demo/demo.js') }}" defer></script>

Do not publish demo assets directly to public/ root.


Storage pattern

Put demo storage files in:

examples/storage

They will be copied to:

storage/app/quick-demos/blog-demo

Use:

storage_path('app/quick-demos/blog-demo/images/demo-cover.jpg')

Do not copy files to generic storage folders.


Config pattern

Put optional demo config in:

examples/config/demo.php

It will be copied to:

config/quick-demos/blog-demo.php

Do not modify existing application config files.


Hook pattern

Use hooks only when normal migrations, seeders, routes, views, assets, storage, and config are not enough.

Example registration:

DemoDefinition::make(
    key: 'blog-demo',
    name: 'Blog Demo',
    databaseName: 'blog_demo',
    afterInstall: \Vendor\BlogPackage\Demo\AfterInstallBlogDemo::class,
)

Hook class:

<?php

namespace Vendor\BlogPackage\Demo;

use ZPMLabs\LaravelPackageQuickDemo\Support\QuickDemoContext;

class AfterInstallBlogDemo
{
    public function handle(QuickDemoContext $context): void
    {
        // Custom demo setup logic.
    }
}

Available context fields:

$context->definition;
$context->databasePath;
$context->connectionName;
$context->routePrefix;
$context->routeNamePrefix;
$context->viewNamespace;
$context->assetsDestination;
$context->storageDestination;
$context->configDestination;
$context->options;

Validation checklist

After implementing the demo, run these commands in a Laravel test app:

composer dump-autoload
php artisan quick-demo:list
php artisan quick-demo:show blog-demo
php artisan quick-demo:install blog-demo --fresh --force
php artisan route:list

Confirm all of the following:

  • The demo appears in quick-demo:list.
  • quick-demo:show blog-demo displays correct paths.
  • The SQLite database exists in database/quick-demos.
  • The generated connection name is package-specific.
  • Demo migrations ran on the quick-demo connection.
  • Demo seeders inserted data into the quick-demo database.
  • No demo tables were created in the default database.
  • Demo routes are mounted under /quick-demo/{demo-key}.
  • Demo route names are prefixed.
  • Demo views render correctly.
  • Demo assets load correctly.
  • Demo storage files are copied if configured.
  • Demo config is copied if configured.
  • .env was not changed.
  • config/database.php was not changed.
  • routes/web.php was not changed.

Common mistakes to avoid

Do not do this:

Schema::create('posts', function (Blueprint $table): void {
    // Wrong connection and wrong table name for demo isolation.
});

Do this instead:

Schema::connection(QuickDemo::connectionName('blog-demo'))->create('demo_posts', function (Blueprint $table): void {
    // Correct.
});

Do not do this:

DB::table('posts')->insert([...]);

Do this instead:

DB::connection(QuickDemo::connectionName('blog-demo'))->table('demo_posts')->insert([...]);

Do not do this:

Route::get('/demo', DemoController::class);

Do this instead:

// examples/routes/demo.php
Route::get('/', [BlogDemoController::class, 'index'])->name('index');

The quick-demo package will add the route prefix.


Expected final result

A user should be able to do this:

composer require vendor/blog-package
php artisan quick-demo:list
php artisan quick-demo:install blog-demo
php artisan serve

Then open:

http://localhost:8000/quick-demo/blog-demo

No manual setup should be required.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console