Day 7: Completing the CRUD Cycle

Summary Today’s Definition of Done: Shoot owner can edit description and color Shoot owner can destroy a shoot after confirmation Edit and Delete controls visible from dashboard Work Session The first thing I did for Day 7 is start working on the SiteController to add the edit and update methods. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 public function edit(Site $site) { if ($site->user_id !== auth()->id()) { abort(403); } return view('sites.edit', compact('site')); } public function update(Request $request, Site $site) { if ($site->user_id !== auth()->id()) { abort(403); } $validated = $request->validate([ 'name' => 'required|string|max:255', 'description' => 'nullable|string|max:1000', 'theme_color' => 'required|string|in:blue,green,purple', ]); $site->update($validated); return redirect()->route('dashboard')->with('success', 'Shoot updated successfully!'); } Then I added the destroy method just to get everything in place in the controller. ...

January 17, 2026

Day 6: Templating & Dynamic Styling

Summary Today’s Definition of Done: Template Creation Primary colors changed based on theme_color. name and description rendered in HTML Tenant/SiteController returns html instead of json. Work Session In order to handle tenant homepages I created a new view at resources/views/tenant/home.blade.php. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>{{ $site->name }}</title> @vite(['resources/css/app.css', 'resources/js/app.js']) </head> <body class="bg-gray-100 font-sans antialiased"> @php $colors = [ 'blue' => 'bg-blue-600 border-blue-800', 'green' => 'bg-green-600 border-green-800', 'purple' => 'bg-purple-600 border-purple-800', ]; $themeClasses = $colors[$site->theme_color] ?? $colors['blue']; @endphp <div class="min-h-screen flex flex-col items-center justify-center"> <div class="max-w-2xl w-full bg-white shadow-xl rounded-lg overflow-hidden border-t-8 {{ $themeClasses }}"> <div class="p-8"> <h1 class="text-4xl font-extrabold text-gray-900 mb-4"> {{ $site->name }} </h1> <p class="text-lg text-gray-600 leading-relaxed mb-6"> {{ $site->description ?? 'This shoot is just beginning to grow.' }} </p> <div class="pt-6 border-t border-gray-100"> <p class="text-sm text-gray-500 italic"> Sprouted by {{ $site->user->name }} </p> </div> </div> </div> </div> </body> </html> Then I updated Tenant\SiteController to use the new view I just created. ...

January 16, 2026

Day 5: Dynamic Rendering

Summary Before I went to bed yesterday I decided to lean into the Rhizome theme a bit harder and renamed Sites to Shoots. Along that same these instead of creating sites we’ll be sprouting shoots. I did not rename anything in the database, middleware, or controller. I just changed the views to reflect the botanical theme. For Day 5 my goal was to transform shoots from identical placeholders into dynamic pages by allowing users to define a description and a theme color during the “sprouting” process. ...

January 15, 2026

Day 4: Creating a Form

Summary Wednesdays are usually pretty busy for me since I go to church after work and don’t get home until very near the kids bedtime so I decided to break today into 2 sessions. Going into session 1 I had the following goals: Set up the “Landlord” controller Create the route Ensure the Site model works with User relationship Work Session 1 Using php artisan again I created the SiteController controller. Not to be confused with Tenant\SiteController that I created yesterday. ...

January 14, 2026

Day 3: Tenant Aware Routing

Summary Going into today’s session I had the following goals: Middleware correctly pulls sudomain from host string Middleware throws 404 if no slug in database Navigating to mountainlotus.rhizomecms.test displays site name As part of the setup I added some test domains to /etc/hosts so I could work with them and not have to mess with a dns server. 1 2 3 127.0.0.1 rhizomecms.test 127.0.0.1 mountainlotus.rhizomecms.test 127.0.0.1 another-site.rhizomecms.test The Work Session Using php artisan again I created the IdentifyTenant middleware. ...

January 13, 2026

Day 2: Models & Migrations

Summary Going into today’s session I had the following goals: Create a Site model Create a sites table that can be “owned” by a user Create a site belonging to a user I referenced the Laravel migrations doc at laravel.com/docs/12.x/migrations and asked Gemini a few clarifying questions when I ran into issues that I couldn’t quickly find an answer to. I was also aquainted with php artisan today, and it feels very much like working with Ruby on Rails scaffolding. ...

January 12, 2026

Day 1: Scoping a Multi-Tenant CMS

Phase 1: Prep Day (Day 1) 1. Pick your poison Learning Laravel. I haven’t actively used php on purpose for anything since Late php 4/Early php 5. I want to jump back in and refresh my php skills so I plan to do so by learning the Laravel framework. ...

January 10, 2026