diff --git a/database/seeders/BlogDatabaseSeeder.php b/database/seeders/BlogDatabaseSeeder.php index ee579b2..0365798 100644 --- a/database/seeders/BlogDatabaseSeeder.php +++ b/database/seeders/BlogDatabaseSeeder.php @@ -28,7 +28,7 @@ public function run(): void 'published_at' => now()->subMonths(5), 'category_id' => $gettingStarted->id, 'author_id' => $author?->id, - ], public_path('images/blog/what-is-saucebase.jpg')); + ], public_path('modules/blog/images/what-is-saucebase.jpg')); $this->createPost([ 'title' => 'Stop Rebuilding the Same Boilerplate Every Project', @@ -48,7 +48,7 @@ public function run(): void 'published_at' => now()->subMonths(3), 'category_id' => $devExperience->id, 'author_id' => $author?->id, - ], public_path('images/blog/tech-stack.jpg')); + ], public_path('modules/blog/images/tech-stack.jpg')); $this->createPost([ 'title' => 'Your First Module: Scaffold and Ship in Under 10 Minutes', @@ -58,7 +58,7 @@ public function run(): void 'published_at' => now()->subMonths(2), 'category_id' => $featuresModules->id, 'author_id' => $author?->id, - ], public_path('images/blog/add-your-saucebase.jpg')); + ], public_path('modules/blog/images/add-your-saucebase.jpg')); $this->createPost([ 'title' => 'Auth, Billing, and Privacy: The Three Modules Every SaaS Needs', @@ -68,7 +68,7 @@ public function run(): void 'published_at' => now()->subMonth(), 'category_id' => $featuresModules->id, 'author_id' => $author?->id, - ], public_path('images/blog/cookies-or-privacy.jpg')); + ], public_path('modules/blog/images/cookies-or-privacy.jpg')); $this->createPost([ 'title' => 'Copy-and-Own: The Philosophy Behind Saucebase Modules', @@ -78,7 +78,17 @@ public function run(): void 'published_at' => now()->subWeeks(2), 'category_id' => $devExperience->id, 'author_id' => $author?->id, - ], public_path('images/blog/your-recipes.jpg')); + ], public_path('modules/blog/images/your-recipes.jpg')); + + $this->createPost([ + 'title' => 'Vue or React? What about both!', + 'excerpt' => 'Choosing a frontend framework used to mean committing to a stack for the life of your project. Saucebase 2.0 changes that — ship with Vue 3 or React 19, and every module works either way.', + 'content' => $content('post-7-vue-and-react.html'), + 'status' => PostStatus::Published, + 'published_at' => now()->subDays(3), + 'category_id' => $devExperience->id, + 'author_id' => $author?->id, + ], public_path('modules/blog/images/vue-and-react.jpg')); } private function createPost(array $data, string $coverImage = ''): Post diff --git a/database/seeders/content/post-7-vue-and-react.html b/database/seeders/content/post-7-vue-and-react.html new file mode 100644 index 0000000..0f32a43 --- /dev/null +++ b/database/seeders/content/post-7-vue-and-react.html @@ -0,0 +1,30 @@ +
Choosing a frontend framework used to mean committing to a stack for the life of your project. Pick Vue, and every module you install needs to be Vue. Pick React, and you're locked into that ecosystem. For a starter kit that ships with authentication, billing, settings, and a blog out of the box, that's a real constraint.
+ +Saucebase 2.0 removes it.
+ +Every Saucebase module ships with both a Vue 3 and a React 19 implementation. When you set up a new project, you choose your framework — and every module you install just works with it. No adapters, no workarounds, no "Vue only" footnotes in the docs.
+ +Under the hood, each module keeps its framework implementations in resources/js/vue/ and resources/js/react/. The module installer reads your project's frontend.json and copies the right files into place automatically.
For contributors and teams evaluating the framework decision, Saucebase ships a command that makes switching non-destructive:
+ +php artisan saucebase:stack vue --dev
+php artisan saucebase:stack react --dev
+
+In --dev mode, both framework directories are kept on disk. Entry points are thin passthroughs. You can flip between them without losing any work.
Framework-specific code only lives where it has to. Routing, backend logic, Filament admin panels, database migrations, API endpoints — all of that is shared. The only thing that differs between the Vue and React versions of a module is the frontend layer.
+ +This means a bug fix in a controller, a new field on a model, or a Filament resource change is written once and works for everyone regardless of their chosen framework.
+ +A starter kit's job is to get out of your way. Locking you into a framework decision on day one — before you've written a single line of product code — is the opposite of that. Saucebase 2.0 lets you start building and figure out the rest later. Or never figure it out at all, because both options keep working.
+ +Pick the framework your team knows. Saucebase handles the rest.
diff --git a/resources/assets/images/add-your-saucebase.jpg b/resources/assets/images/add-your-saucebase.jpg new file mode 100644 index 0000000..397bf4e Binary files /dev/null and b/resources/assets/images/add-your-saucebase.jpg differ diff --git a/resources/assets/images/cookies-or-privacy.jpg b/resources/assets/images/cookies-or-privacy.jpg new file mode 100644 index 0000000..416a4e4 Binary files /dev/null and b/resources/assets/images/cookies-or-privacy.jpg differ diff --git a/resources/assets/images/tech-stack.jpg b/resources/assets/images/tech-stack.jpg new file mode 100644 index 0000000..d4e10ea Binary files /dev/null and b/resources/assets/images/tech-stack.jpg differ diff --git a/resources/assets/images/vue-and-react.jpg b/resources/assets/images/vue-and-react.jpg new file mode 100644 index 0000000..316f025 Binary files /dev/null and b/resources/assets/images/vue-and-react.jpg differ diff --git a/resources/assets/images/what-is-saucebase.jpg b/resources/assets/images/what-is-saucebase.jpg new file mode 100644 index 0000000..3583bbc Binary files /dev/null and b/resources/assets/images/what-is-saucebase.jpg differ diff --git a/resources/assets/images/your-recipes.jpg b/resources/assets/images/your-recipes.jpg new file mode 100644 index 0000000..6cff52f Binary files /dev/null and b/resources/assets/images/your-recipes.jpg differ diff --git a/src/Http/Controllers/BlogController.php b/src/Http/Controllers/BlogController.php index 680d814..3cd3103 100644 --- a/src/Http/Controllers/BlogController.php +++ b/src/Http/Controllers/BlogController.php @@ -30,7 +30,7 @@ public function show(string $categoryOrSlug, ?string $slug = null): Response $category = Category::where('slug', $categoryOrSlug)->firstOrFail(); $post = $query->where('category_id', $category->id)->where('slug', $slug)->firstOrFail(); } else { - $post = $query->where('slug', $categoryOrSlug)->whereNull('category_id')->firstOrFail(); + $post = $query->where('slug', $categoryOrSlug)->firstOrFail(); } $related = Post::published()