diff --git a/demo/.ai/guidelines b/demo/.ai/guidelines new file mode 120000 index 000000000..45f9e054c --- /dev/null +++ b/demo/.ai/guidelines @@ -0,0 +1 @@ +../../resources/boost/guidelines \ No newline at end of file diff --git a/demo/.gitignore b/demo/.gitignore index acda100fc..6f85a790f 100644 --- a/demo/.gitignore +++ b/demo/.gitignore @@ -10,3 +10,17 @@ node_modules .DS_Store .phpunit.result.cache .env + +# AI +AGENTS.md +boost.json +.claude +CLAUDE.md +.cursor +.gemini +GEMINI.md +.github +.junie +opencode.json +.mcp.json +.vscode diff --git a/demo/composer.json b/demo/composer.json index ef55e31f4..063132031 100644 --- a/demo/composer.json +++ b/demo/composer.json @@ -24,6 +24,7 @@ "require-dev": { "fakerphp/faker": "^1.9.1", "itsgoingd/clockwork": "^5.1", + "laravel/boost": "^1.8", "laravel/sail": "^1.0.1", "mockery/mockery": "^1.4.4", "nunomaduro/collision": "^8.6", @@ -52,7 +53,8 @@ "post-autoload-dump": [ "Illuminate\\Foundation\\ComposerScripts::postAutoloadDump", "@php artisan package:discover --ansi", - "@php artisan vendor:publish --tag=sharp-assets --force" + "@php artisan vendor:publish --tag=sharp-assets --force", + "@php artisan boost:update --ansi" ], "post-update-cmd": [ "@php artisan vendor:publish --tag=laravel-assets --ansi --force" diff --git a/demo/composer.lock b/demo/composer.lock index 148d524d8..4578bbcfe 100644 --- a/demo/composer.lock +++ b/demo/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "b1313d765c8b8fbe765f35c0e151e138", + "content-hash": "479e7666753599f88fecc36d866c8ae9", "packages": [ { "name": "bacon/bacon-qr-code", @@ -7494,6 +7494,206 @@ ], "time": "2025-09-14T15:34:49+00:00" }, + { + "name": "laravel/boost", + "version": "v1.8.10", + "source": { + "type": "git", + "url": "https://github.com/laravel/boost.git", + "reference": "aad8b2a423b0a886c2ce7ee92abbfde69992ff32" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/boost/zipball/aad8b2a423b0a886c2ce7ee92abbfde69992ff32", + "reference": "aad8b2a423b0a886c2ce7ee92abbfde69992ff32", + "shasum": "" + }, + "require": { + "guzzlehttp/guzzle": "^7.9", + "illuminate/console": "^10.49.0|^11.45.3|^12.41.1", + "illuminate/contracts": "^10.49.0|^11.45.3|^12.41.1", + "illuminate/routing": "^10.49.0|^11.45.3|^12.41.1", + "illuminate/support": "^10.49.0|^11.45.3|^12.41.1", + "laravel/mcp": "^0.5.1", + "laravel/prompts": "0.1.25|^0.3.6", + "laravel/roster": "^0.2.9", + "php": "^8.1" + }, + "require-dev": { + "laravel/pint": "^1.20.0", + "mockery/mockery": "^1.6.12", + "orchestra/testbench": "^8.36.0|^9.15.0|^10.6", + "pestphp/pest": "^2.36.0|^3.8.4|^4.1.5", + "phpstan/phpstan": "^2.1.27", + "rector/rector": "^2.1" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Laravel\\Boost\\BoostServiceProvider" + ] + }, + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Laravel\\Boost\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Laravel Boost accelerates AI-assisted development by providing the essential context and structure that AI needs to generate high-quality, Laravel-specific code.", + "homepage": "https://github.com/laravel/boost", + "keywords": [ + "ai", + "dev", + "laravel" + ], + "support": { + "issues": "https://github.com/laravel/boost/issues", + "source": "https://github.com/laravel/boost" + }, + "time": "2026-01-14T14:51:16+00:00" + }, + { + "name": "laravel/mcp", + "version": "v0.5.3", + "source": { + "type": "git", + "url": "https://github.com/laravel/mcp.git", + "reference": "39b9791b989927642137dd5b55dde0529f1614f9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/mcp/zipball/39b9791b989927642137dd5b55dde0529f1614f9", + "reference": "39b9791b989927642137dd5b55dde0529f1614f9", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-mbstring": "*", + "illuminate/console": "^10.49.0|^11.45.3|^12.41.1", + "illuminate/container": "^10.49.0|^11.45.3|^12.41.1", + "illuminate/contracts": "^10.49.0|^11.45.3|^12.41.1", + "illuminate/http": "^10.49.0|^11.45.3|^12.41.1", + "illuminate/json-schema": "^12.41.1", + "illuminate/routing": "^10.49.0|^11.45.3|^12.41.1", + "illuminate/support": "^10.49.0|^11.45.3|^12.41.1", + "illuminate/validation": "^10.49.0|^11.45.3|^12.41.1", + "php": "^8.1" + }, + "require-dev": { + "laravel/pint": "^1.20", + "orchestra/testbench": "^8.36|^9.15|^10.8", + "pestphp/pest": "^2.36.0|^3.8.4|^4.1.0", + "phpstan/phpstan": "^2.1.27", + "rector/rector": "^2.2.4" + }, + "type": "library", + "extra": { + "laravel": { + "aliases": { + "Mcp": "Laravel\\Mcp\\Server\\Facades\\Mcp" + }, + "providers": [ + "Laravel\\Mcp\\Server\\McpServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Laravel\\Mcp\\": "src/", + "Laravel\\Mcp\\Server\\": "src/Server/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "Rapidly build MCP servers for your Laravel applications.", + "homepage": "https://github.com/laravel/mcp", + "keywords": [ + "laravel", + "mcp" + ], + "support": { + "issues": "https://github.com/laravel/mcp/issues", + "source": "https://github.com/laravel/mcp" + }, + "time": "2026-01-26T10:25:21+00:00" + }, + { + "name": "laravel/roster", + "version": "v0.2.9", + "source": { + "type": "git", + "url": "https://github.com/laravel/roster.git", + "reference": "82bbd0e2de614906811aebdf16b4305956816fa6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/roster/zipball/82bbd0e2de614906811aebdf16b4305956816fa6", + "reference": "82bbd0e2de614906811aebdf16b4305956816fa6", + "shasum": "" + }, + "require": { + "illuminate/console": "^10.0|^11.0|^12.0", + "illuminate/contracts": "^10.0|^11.0|^12.0", + "illuminate/routing": "^10.0|^11.0|^12.0", + "illuminate/support": "^10.0|^11.0|^12.0", + "php": "^8.1|^8.2", + "symfony/yaml": "^6.4|^7.2" + }, + "require-dev": { + "laravel/pint": "^1.14", + "mockery/mockery": "^1.6", + "orchestra/testbench": "^8.22.0|^9.0|^10.0", + "pestphp/pest": "^2.0|^3.0", + "phpstan/phpstan": "^2.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Laravel\\Roster\\RosterServiceProvider" + ] + }, + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Laravel\\Roster\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Detect packages & approaches in use within a Laravel project", + "homepage": "https://github.com/laravel/roster", + "keywords": [ + "dev", + "laravel" + ], + "support": { + "issues": "https://github.com/laravel/roster/issues", + "source": "https://github.com/laravel/roster" + }, + "time": "2025-10-20T09:56:46+00:00" + }, { "name": "laravel/sail", "version": "v1.51.0", diff --git a/resources/boost/guidelines/core.blade.php b/resources/boost/guidelines/core.blade.php new file mode 100644 index 000000000..9dec5e723 --- /dev/null +++ b/resources/boost/guidelines/core.blade.php @@ -0,0 +1,235 @@ +## Sharp +- Sharp is used by this application. Follow existing conventions for how and where it's implemented. +- Sharp is a content management framework for Laravel that allows you to define user interfaces in PHP using structured configuration objects. +- Sharp allows you to build Entity Lists, Forms, Show Pages, and Dashboards. + +### Patterns +Use `make()` static methods to initialize fields, columns, and other components. + +#### Entity Lists +Entity Lists are used to display a list of records. +@verbatim + + +use Code16\Sharp\EntityList\Fields\EntityListField; +use Code16\Sharp\EntityList\Fields\EntityListFieldsContainer; +use Code16\Sharp\EntityList\SharpEntityList; +use Illuminate\Contracts\Support\Arrayable; + +class UserList extends SharpEntityList +{ + protected function buildList(EntityListFieldsContainer $fields): void + { + $fields + ->addField( + EntityListField::make('name') + ->setLabel('Name') + ->setSortable() + ) + ->addField( + EntityListField::make('email') + ->setLabel('Email') + ); + } + + public function buildListConfig(): void + { + $this + ->configureSearchable() + ->configureDefaultSort('name', 'asc'); + } + + public function getListData(): array|Arrayable + { + $users = User::query() + ->when($this->queryParams->hasSearch(), function ($query) { + foreach ($this->queryParams->searchWords() as $word) { + $query->where('name', 'like', $word); + } + }) + ->orderBy( + $this->queryParams->sortedBy() ?: 'name', + $this->queryParams->sortedDir() ?: 'asc' + ); + + return $this->transform($users->paginate(30)); + } +} + +@endverbatim + +#### Forms +Forms are used to create or edit records. +@verbatim + +use Code16\Sharp\Form\Fields\SharpFormTextField; +use Code16\Sharp\Form\Fields\SharpFormTextareaField; +use Code16\Sharp\Form\Layout\FormLayout; +use Code16\Sharp\Form\Layout\FormLayoutColumn; +use Code16\Sharp\Form\SharpForm; +use Code16\Sharp\Utils\Fields\FieldsContainer; + +class UserForm extends SharpForm +{ + public function buildFormFields(FieldsContainer $formFields): void + { + $formFields + ->addField( + SharpFormTextField::make('name') + ->setLabel('Name') + ->setMaxLength(150) + ) + ->addField( + SharpFormTextareaField::make('bio') + ->setLabel('Biography') + ->setMaxLength(500) + ); + } + + public function buildFormLayout(FormLayout $formLayout): void + { + $formLayout + ->addColumn(6, fn (FormLayoutColumn $column) => $column + ->withField('name') + ->withField('bio') + ); + } + + public function find($id): array + { + return $this->transform(User::findOrFail($id)); + } + + public function update($id, array $data) + { + $this->validate($data, [ + 'name' => ['required', 'string', 'max:150'], + ]); + + $user = $id ? User::findOrFail($id) : new User(); + $user->fill($data); + $user->save(); + + return $user->id; + } +} + +@endverbatim + +#### Show Pages +Show Pages are used to display details of a single record. +@verbatim + +use Code16\Sharp\Show\Fields\SharpShowTextField; +use Code16\Sharp\Show\Layout\ShowLayout; +use Code16\Sharp\Show\Layout\ShowLayoutColumn; +use Code16\Sharp\Show\Layout\ShowLayoutSection; +use Code16\Sharp\Show\SharpShow; +use Code16\Sharp\Utils\Fields\FieldsContainer; + +class UserShow extends SharpShow +{ + protected function buildShowFields(FieldsContainer $showFields): void + { + $showFields + ->addField( + SharpShowTextField::make('name') + ->setLabel('Name') + ) + ->addField( + SharpShowTextField::make('email') + ->setLabel('Email') + ) + ->addField( + SharpShowTextField::make('bio') + ->setLabel('Biography') + ); + } + + protected function buildShowLayout(ShowLayout $showLayout): void + { + $showLayout + ->addSection(fn (ShowLayoutSection $section) => $section + ->addColumn(6, fn (ShowLayoutColumn $column) => $column + ->withField('name') + ->withField('email') + ->withField('bio') + ) + ); + } + + public function find(mixed $id): array + { + return $this->transform(User::findOrFail($id)); + } + + public function delete($id): void + { + User::findOrFail($id)->delete(); + } +} + +@endverbatim + +### Transformers +Sharp uses Transformers to map your model data to the format expected by the UI. Use `setCustomTransformer()` to transform field values before displaying them. +@verbatim + +// In Entity Lists, Forms, or Show Pages +public function getListData(): array|Arrayable +{ + $users = User::with('company')->get(); + + return $this + ->setCustomTransformer('name', function($value, $user) { + return strtoupper($value); + }) + ->setCustomTransformer('company:name', function($value, $user) { + return $value ?? 'N/A'; + }) + ->transform($users); +} + +@endverbatim + +### Common Configuration Methods +@verbatim + +// Entity List Configuration +public function buildListConfig(): void +{ + $this + ->configureSearchable() + ->configureDefaultSort('created_at', 'desc') + ->configureDelete(confirmationText: 'Delete this item?') + ->configureCreateButtonLabel('Add new...'); +} + +// Form Configuration +public function buildFormConfig(): void +{ + $this + ->configureDisplayShowPageAfterCreation() + ->configureCreateFormTitle('Create new user') + ->configureEditFormTitle('Edit user'); +} + +// Show Configuration +public function buildShowConfig(): void +{ + $this + ->configureBreadcrumbCustomLabelAttribute('name') + ->configurePageTitle('name'); +} + +@endverbatim + +### Common Classes & Namespaces +- **Entity Lists:** `Code16\Sharp\EntityList\SharpEntityList` +- **Forms:** `Code16\Sharp\Form\SharpForm` +- **Show Pages:** `Code16\Sharp\Show\SharpShow` +- **Dashboards:** `Code16\Sharp\Dashboard\SharpDashboard` +- **Form Fields:** `Code16\Sharp\Form\Fields\...` +- **Show Fields:** `Code16\Sharp\Show\Fields\...` +- **Entity List Fields:** `Code16\Sharp\EntityList\Fields\...` +- **Eloquent Updater:** `Code16\Sharp\Form\Eloquent\WithSharpFormEloquentUpdater`