Blog

Thoughts & Builds

Code, AI, real-world projects, and the occasional rant. No fluff — just what I'm learning and building.

laravel ux design-systems theming multi-tenancy sql

Day one of the visual walkthrough: I hard-coded a colour that already had a setting

Twelve commits of 'make this page look right' — and the most useful thing all day was being told the thing I'd just hard-coded was already a choice on the Appearance screen.

Read more
laravel multi-tenancy migrations security

Short session: three questions a guard asked, answered

A lookup that takes the first matching row in any tenant is fine until there are two tenants. And a unique index can quietly prevent the second one from ever configuring anything.

Read more
laravel security csp middleware testing css

45 security findings, one missing CSS class, and the middleware order that undid every scope in the platform

Route model binding ran before the business-unit context was set, so every module route resolved records from anywhere. One line in a priority list.

Read more
security testing laravel static-analysis api

Evening session: tests that read every package, so the module I write next month is already checked

Every finding from the security review had a regression test. Those protect code that exists. These read the source of every package and fail on a shape — and found four more gaps on their first run.

Read more
laravel performance sql audit testing security

I wrote down why the audit screen was slow, fixed it, measured it, and was wrong

192ms before, 199ms after. The predicate I'd blamed in a decision record wasn't the thing. The COUNT beside the rows was costing five times what the rows cost.

Read more
laravel security architecture notifications tokens

Two modules rolled their own share links, and they'd already drifted apart

One could be revoked and one couldn't. Nobody decided that — it's just what building the same thing twice produces.

Read more
laravel reporting dashboards javascript testing debugging git-worktree

A date filter, three hex codes, and a test suite that hung for 30 minutes

I asked for a date toggle and some colour tweaks on a dashboard, and ended up rethinking where derived data lives and chasing a phantom test failure caused by a symlinked vendor folder.

Read more
architecture laravel ux technical-debt dashboards

Five things that said they did something, and didn't

An empty state promising a feature that was never built. A dropdown offering a default that stored nothing. A heading saying 'in order' with no way to change the order. And a comment of mine that was the bug.

Read more
css tailwind design-systems laravel accessibility theming

A theme is data, markup is code, and a menu bar has three rows not two

Built a whitelabelling layer where the only free value is a colour — and then got the colour model wrong twice in a row because I'd misread my own layout.

Read more
porting laravel testing ci architecture

I spent an evening porting from the wrong repository

Two products share an ancestor: same folder layout, same file names, recognisably the same code. I read one and built against it all evening. The drift check caught it by refusing to run.

Read more
laravel blade architecture pdf api billing

Three modules in a day, and a Blade directive that silently refused to compile

Quotes, contracts and billing. The best bug was one character of whitespace, and the best feature was a prompt that writes itself.

Read more
laravel reporting sql architecture charts pdf

Evening session: porting 17,000 lines of query builder that had never been tested

Built a whole reporting engine — filter trees, two computed-field languages, widgets, scheduling. Every decision felt right. I was reading the wrong repository the entire time.

Read more
php rclone s3 backups devops nginx totp debugging

I built a backup tool in a day, and almost every bug was a near-miss

Scheduled database and file backups, shipped to production in one session — where the interesting part wasn't the feature, it was the four separate bugs that would have silently destroyed data.

Read more
laravel email api ci static-analysis architecture fortify

CI ran out of minutes mid-build, and nobody invited could ever set a password

Eleven hours: an email module with three real transports, a support desk, a token API, and the discovery that the invitation flow had never once worked end to end.

Read more
laravel testing css eloquent php ux

Twelve gaps in one walkthrough, and every one was a finished feature with no door on it

A parity row said 'Ported'. The code was built, routed and tested. No view rendered any of it. That happened twelve times in one afternoon.

Read more
porting triage architecture technical-debt

Ten gaps became three, and the best one was a finished feature no route could reach

Re-read a week-old backlog against the actual code instead of against my own notes. Two of the items were already done and nobody had noticed.

Read more
laravel architecture eloquent porting testing

For once I applied the rule before making the mistake

Built the last big area of the phase, then audited one more and decided not to build it at all — which is the first time on this project I've caught that before writing the code rather than after.

Read more
laravel notifications testing routing dark-mode seeders architecture

The notification row was written, the count stayed zero, and eight tests passed the whole time

Route parameters that bind positionally, a test that asserted a link instead of a page, a migrate:fresh that ate my deployment state twice, and a notification system delivering to a class nothing queries.

Read more
laravel file-storage transactions soft-deletes validation

Evening session: a file area, and a delete you can undo

Ported a file area and found the source's download route would stream any file to anyone who could reach it. Then a second caller broke the settings mechanism I'd shipped that afternoon.

Read more
laravel permissions ci github-actions migrations architecture testing

A whole sidebar group vanished, and it took a permission cascade that never fired to explain it

Two modules installed, enabled, migrated, routed — and invisible to every user including the superuser, with no error anywhere. Plus three packages that had never once run in CI.

Read more
porting process documentation architecture

The table before the code

One commit all day: a parity table written before a single line of the feature. Yesterday's audit cost me a day, so today I paid it up front.

Read more
laravel porting refactoring testing eloquent sqlite

I'd been porting the schema and calling it the feature

Built a plan, then re-read the source controllers and found six behaviours I'd never carried across — plus a cycle check I'd written backwards that happily saved a cycle.

Read more
docker laravel ci github-actions testing security maps

A green suite, six broken journeys, and a drift log that was empty because nothing was writing to it

Moved local dev off the shared stack into Docker, built a CI check that verifies my own paperwork, then demoed the thing and found six features that were fully tested and completely unusable.

Read more
ci github-actions composer monorepo testing laravel

CI on a clean checkout found four things my machine never could

Including that I'd been claiming PHP 8.3 support for a dependency set that needs 8.4, and that a split workflow was one merge away from force-pushing a package over the monorepo.

Read more
laravel settings caching seeders eloquent

One commit, two bugs I wasn't looking for

Made status vocabularies client-editable. Found a stale-cache bug and a seeder that was silently skipping the hook that assigns record identifiers.

Read more
laravel architecture monorepo packages multi-tenant testing

Day one: stock Laravel install to a working modular platform in fourteen hours

Started with a blank Laravel app and a brief. Ended with a module registry, a record-type framework and two bugs that only showed up because I clicked things instead of running tests.

Read more
personal family process rest

Nothing shipped in July

There's a hole in this blog between the end of May and now — eleven weeks of it. It wasn't burnout, and it isn't a productivity story with a lesson bolted on the end. It was summer — and I have a countable number of those left with a teenager in the house.

Read more
laravel saas mentorship work-experience rebrand iteration

21 commits in a week: building a SaaS with my daughter as the product owner

It started as a school work-experience placement. By the end of week one we'd shipped a real SaaS — twice. Two rebrands, two pricing models, and a non-developer product owner who knew exactly what she wanted.

Read more
laravel blade vite ux databases debugging

Rebuilding a reporting page one step at a time

Five layout changes, a backend bug I didn't plant, and the time I mistook 'combined' for 'either/or'.

Read more
laravel outlook office-js sanctum microsoft-graph webhooks modular-architecture

Building an Outlook Ribbon Add-in on Top of a Laravel Monolith (and Everything That Went Sideways)

I needed a 'Create Case' button in Outlook that talked to an existing Laravel case management system. What I got was a crash course in Sanctum quirks, encrypted credential archaeology, and the question nobody asked: what even is a service account in Sanctum?

Read more
laravel reporting gridstack apexcharts nwidart-modules vanilla-js debugging

Building a Power BI Lite in a Day (and Renaming Everything Twice)

Shipped a full self-service reporting module from nothing to 44 routes in a day. Then the client asked to rename it. Then asked to restructure the whole thing. Here's the real story, including the route rename that took the whole module offline.

Read more
laravel debugging sessions nginx caching imports

Session Overflow and the Art of Not Storing Everything

I added a description column, broke production with a session overflow, ripped the feature out, and rebuilt it with cache-backed AJAX — all in one afternoon.

Read more
laravel php carbon date-logic debugging billing

Off by One Month: The Date Bug That Looked Simple

A billing viewer was showing the wrong periods — the fix turned out to be two bugs hiding behind one symptom.

Read more
documentation security api-integration microsoft-graph audit

Your Security Doc Is Lying (And You Probably Don't Know It)

I audited a client-facing security document against the actual codebase and found it was promising things that weren't true — and missing things that were.

Read more
laravel phpspreadsheet dhtmlx gantt export html2canvas

Exporting a Gantt chart is harder than it should be

A spreadsheet API that changed its method names and a Gantt chart that only exports what's visible — two problems, two lessons.

Read more
laravel blade permissions onboarding debugging

Three features, one Blade bug, and a backfill command

I shipped three features in one session and broke the whole page with a single capital letter.

Read more
laravel blade cherry-pick multi-repo debugging ai-assisted-development

Cherry-picking across repos and the three bugs that came with it

I shipped a parent-child account feature and squashed three bugs — but only after toArray silently turned my models into mush and a Blade directive mismatch swallowed all my JavaScript.

Read more
laravel ai-assisted-development claude-code cherry-pick debugging

Cherry-Picks, Null Crashes, and Wrong API Codes — One Session, Three Layers of Broken

3,000 lines of code, a cherry-pick that brought routes without controllers, a JavaScript crash caused by a form field that didn't exist, and picking the wrong API transaction type three times.

Read more
laravel tailwind ai meta blog

Building zerofocus.dev From Scratch in One Session

Started with a blank Laravel install, ended with a full site, blog system, and a skill that documents what I build. Along the way, config caching bit me twice and Symfony YAML wasn't where I expected it.

Read more
intro personal

Hello World — Welcome to Zero Focus Dev

First post. No polished intro, no grand plan — just a guy with coffee, code, and too many browser tabs open. Here's what this is all about.

Read more