Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
524 changes: 0 additions & 524 deletions .agents/skills/inertia-react-development/SKILL.md

This file was deleted.

524 changes: 0 additions & 524 deletions .claude/skills/inertia-react-development/SKILL.md

This file was deleted.

9 changes: 1 addition & 8 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ The Laravel Boost guidelines are specifically curated by Laravel maintainers for

This application is a Laravel application and its main Laravel ecosystems package & versions are below. You are an expert with them all. Ensure you abide by these specific packages & versions.

- php - 8.4
- php - 8.3
- inertiajs/inertia-laravel (INERTIA_LARAVEL) - v3
- laravel/fortify (FORTIFY) - v1
- laravel/framework (LARAVEL) - v13
Expand Down Expand Up @@ -118,13 +118,6 @@ This project has domain-specific skills available in `**/skills/**`. You MUST ac

- Laravel can be deployed using [Laravel Cloud](https://cloud.laravel.com/), which is the fastest way to deploy and scale production Laravel applications.

=== herd rules ===

# Laravel Herd

- The application is served by Laravel Herd at `https?://[kebab-case-project-dir].test`. Use the `get-absolute-url` tool to generate valid URLs. Never run commands to serve the site. It is always available.
- Use the `herd` CLI to manage services, PHP versions, and sites (e.g. `herd sites`, `herd services:start <service>`, `herd php:list`). Run `herd list` to discover all available commands.

=== tests rules ===

# Test Enforcement
Expand Down
9 changes: 1 addition & 8 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ The Laravel Boost guidelines are specifically curated by Laravel maintainers for

This application is a Laravel application and its main Laravel ecosystems package & versions are below. You are an expert with them all. Ensure you abide by these specific packages & versions.

- php - 8.4
- php - 8.3
- inertiajs/inertia-laravel (INERTIA_LARAVEL) - v3
- laravel/fortify (FORTIFY) - v1
- laravel/framework (LARAVEL) - v13
Expand Down Expand Up @@ -118,13 +118,6 @@ This project has domain-specific skills available in `**/skills/**`. You MUST ac

- Laravel can be deployed using [Laravel Cloud](https://cloud.laravel.com/), which is the fastest way to deploy and scale production Laravel applications.

=== herd rules ===

# Laravel Herd

- The application is served by Laravel Herd at `https?://[kebab-case-project-dir].test`. Use the `get-absolute-url` tool to generate valid URLs. Never run commands to serve the site. It is always available.
- Use the `herd` CLI to manage services, PHP versions, and sites (e.g. `herd sites`, `herd services:start <service>`, `herd php:list`). Run `herd list` to discover all available commands.

=== tests rules ===

# Test Enforcement
Expand Down
9 changes: 1 addition & 8 deletions GEMINI.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ The Laravel Boost guidelines are specifically curated by Laravel maintainers for

This application is a Laravel application and its main Laravel ecosystems package & versions are below. You are an expert with them all. Ensure you abide by these specific packages & versions.

- php - 8.4
- php - 8.3
- inertiajs/inertia-laravel (INERTIA_LARAVEL) - v3
- laravel/fortify (FORTIFY) - v1
- laravel/framework (LARAVEL) - v13
Expand Down Expand Up @@ -118,13 +118,6 @@ This project has domain-specific skills available in `**/skills/**`. You MUST ac

- Laravel can be deployed using [Laravel Cloud](https://cloud.laravel.com/), which is the fastest way to deploy and scale production Laravel applications.

=== herd rules ===

# Laravel Herd

- The application is served by Laravel Herd at `https?://[kebab-case-project-dir].test`. Use the `get-absolute-url` tool to generate valid URLs. Never run commands to serve the site. It is always available.
- Use the `herd` CLI to manage services, PHP versions, and sites (e.g. `herd sites`, `herd services:start <service>`, `herd php:list`). Run `herd list` to discover all available commands.

=== tests rules ===

# Test Enforcement
Expand Down
76 changes: 61 additions & 15 deletions app/Http/Controllers/ThemesController.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace App\Http\Controllers;

use App\Models\Theme;
use App\Services\AiService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
Expand All @@ -13,24 +14,42 @@

class ThemesController extends Controller
{
public function create()
public function create(Request $request)
{
return Inertia::render('themes/create');
$baseTheme = null;
if ($fork = $request->query('fork')) {
$baseTheme = Theme::where('name', $fork)->first();
if ($baseTheme) {
$baseTheme->load('tags');
$tags = $baseTheme->tags->pluck('name')->toArray();
$baseTheme = $baseTheme->toArray();
$baseTheme['tags'] = $tags;
}
}

return Inertia::render('themes/create', [
'baseTheme' => $baseTheme,
]);
}

public function store(Request $request)
{
$request->validate([
'url' => ['required', 'url'],
'url' => ['required_without:theme_data', 'nullable', 'url'],
'theme_data' => ['required_without:url', 'nullable', 'array'],
]);

$response = Http::get($request->url);
if ($request->url) {
$response = Http::get($request->url);

if ($response->failed()) {
return back()->withErrors(['url' => 'Could not fetch registry from the provided URL.']);
}
if ($response->failed()) {
return back()->withErrors(['url' => 'Could not fetch registry from the provided URL.']);
}

$data = $response->json();
$data = $response->json();
} else {
$data = $request->theme_data;
}

if (empty($data) || ! is_array($data)) {
return back()->withErrors(['url' => 'Invalid registry JSON format.']);
Expand All @@ -56,6 +75,12 @@ public function store(Request $request)
$errors[] = '"cssVars.dark" must be an object.';
}
}
} elseif (isset($data['vars_light']) && isset($data['vars_dark'])) {
// Support direct vars_light/vars_dark for manual/AI creation
$data['cssVars'] = [
'light' => $data['vars_light'],
'dark' => $data['vars_dark'],
];
}

if (isset($data['files'])) {
Expand Down Expand Up @@ -100,22 +125,28 @@ public function store(Request $request)
}

if (! empty($errors)) {
return back()->withErrors(['url' => implode(' ', $errors)]);
$errorKey = $request->url ? 'url' : 'theme_data';

return back()->withErrors([$errorKey => implode(' ', $errors)]);
}

$data['name'] = Str::kebab($data['name']);
$data['type'] = 'registry:theme';

if (! ($data['author'] ?? null)) {
$host = Str::of(parse_url($request->url, PHP_URL_HOST))
->replaceFirst('www.', '')
->before('.')
->toString();
$data['author'] = $host;
if ($request->url) {
$host = Str::of(parse_url($request->url, PHP_URL_HOST))
->replaceFirst('www.', '')
->before('.')
->toString();
$data['author'] = $host;
} else {
$data['author'] = auth()->user()->name;
}
}

if (Theme::where('name', $data['name'])->exists()) {
return back()->withErrors(['url' => "A theme named [{$data['name']}] already exists."]);
$data['name'] = $data['name'].'-'.Str::random(4);
}

$theme = Theme::fromRegistry($data);
Expand All @@ -133,6 +164,21 @@ public function store(Request $request)
->with('success', 'Theme created successfully.');
}

public function generate(Request $request, AiService $aiService)
{
$request->validate([
'prompt' => ['required', 'string', 'max:500'],
]);

$themeData = $aiService->generateFullTheme($request->prompt);

if (empty($themeData)) {
return response()->json(['error' => 'Failed to generate theme.'], 500);
}

return response()->json($themeData);
}

public function index()
{
$availableTags = Cache::remember('themes:available_tags', 3600, function () {
Expand Down
3 changes: 2 additions & 1 deletion app/Models/Theme.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use App\Observers\ThemeObserver;
use Illuminate\Database\Eloquent\Attributes\Fillable;
use Illuminate\Database\Eloquent\Attributes\ObservedBy;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\SoftDeletes;
Expand All @@ -27,7 +28,7 @@
#[ObservedBy(ThemeObserver::class)]
class Theme extends Model
{
use HasTags, HasTheme, SoftDeletes;
use HasFactory, HasTags, HasTheme, SoftDeletes;

protected $table = 'themes';

Expand Down
1 change: 0 additions & 1 deletion boost.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
"socialite-development",
"wayfinder-development",
"pest-testing",
"inertia-react-development",
"tailwindcss-development"
]
}
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
"laravel/tinker": "^3.0",
"laravel/wayfinder": "^0.1.14",
"spatie/laravel-permission": "^7.4",
"spatie/laravel-tags": "^4.11"
"spatie/laravel-tags": "^4.11",
"symfony/var-dumper": "7.4.*"
},
"require-dev": {
"fakerphp/faker": "^1.24",
Expand Down
32 changes: 16 additions & 16 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

40 changes: 40 additions & 0 deletions database/factories/ThemeFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

namespace Database\Factories;

use App\Models\Theme;
use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;

/**
* @extends Factory<Theme>
*/
class ThemeFactory extends Factory
{
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition(): array
{
$name = $this->faker->unique()->slug();

return [
'user_id' => User::factory(),
'name' => $name,
'title' => $this->faker->words(3, true),
'description' => $this->faker->sentence(),
'vars_light' => [
'background' => '0 0% 100%',
'foreground' => '240 10% 3.9%',
'primary' => '240 5.9% 10%',
],
'vars_dark' => [
'background' => '240 10% 3.9%',
'foreground' => '0 0% 98%',
'primary' => '0 0% 98%',
],
];
}
}
5 changes: 5 additions & 0 deletions npm_dev.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@

> dev
> vite

sh: 1: vite: not found
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading