Back to Blog
4 min read

How I Automated Portal Feature Generation in HomeForged Using Modular Pipelines

The Generator That Broke More Than It Built

Early in HomeForged’s development, I leaned hard on code generation to scaffold out portal features—resources, pages, forms, the works. It made sense at the time: Laravel’s Artisan commands gave me a clean entry point, and with Filament PHP powering my admin interface, I could spin up CRUD interfaces in seconds. But my first-gen generator was a monolith—a single, tangled command that tried to do everything at once: parse config, generate models, wire up Filament resources, and scaffold UI components. It worked… until it didn’t.

I hit the wall when I added Phase 5 portal features. Suddenly, 72+ tests started failing—mostly around schema mismatches, incorrect relation handling, and inconsistent policy bindings. Debugging meant stepping through hundreds of lines of procedural logic. Worse, every new feature required fragile string-based templating overrides. I weren’t shipping faster—I was breaking faster.

The kicker? I was generating less over time because the cost of maintaining the generator outweighed the time saved. That’s when I decided to rebuild from the ground up—not just fix it, but reframe it.

Enter the Pipeline: Small Stages, Big Wins

I scrapped the monolith and rebuilt the generator as a modular pipeline. Instead of one command doing everything, I broke the process into discrete, testable stages:

  • Parse Schema
  • Generate Models & Migrations
  • Build Filament Resources
  • Scaffold Pages & Forms
  • Wire Up Policies & Tests

Each stage is a lightweight, reusable class that accepts a context object and returns an updated one. I leaned into Laravel’s pipeline pattern—yes, the same one used in middleware—but applied it to code generation. Now, when I add a new portal feature, I don’t touch the core logic. I just plug in a new stage or tweak an existing one.

The impact was immediate. I reran my test suite and watched 72+ failures drop to zero. Why? Because each stage could be tested in isolation. I could mock input, assert output, and verify side effects—something impossible with the old monolith. I even added snapshot testing for generated files using Pest, so I’d catch unintended changes early.

But the real win was flexibility. One team needed enum-based status fields auto-injected into forms. Another wanted soft deletes toggled via config. With the pipeline, these weren’t special cases—they were just new transforms. I added a HandleEnums stage and a ApplySoftDeletes stage, and suddenly, customization became trivial.

Auto-Generated Portals, Zero Manual UI

The end goal wasn’t just stable generation—it was full automation. And with the pipeline in place, I got there.

Today, when I define a new portal feature in config (think: portal: { resource: 'ClientProject', with: ['team', 'budget', 'status'] }), the generator runs through the pipeline and spits out:

  • A fully-structured Eloquent model
  • A database migration with relationships
  • A Filament Resource with List, View, and Edit pages
  • Pre-wired form components (including enums, file uploads, and relation managers)
  • Policy-based authorization hooks
  • A starter test suite with CRUD coverage

All of it generated. All of it consistent. And all of it editable—because I’m not locking devs in. If someone needs a custom form layout or a computed field, they can safely override just that part. The rest stays in sync.

I’m now using this to spin up entire portal modules in under five minutes. No copy-pasting, no missed migrations, no forgotten policies. It’s not magic—it’s just well-structured code doing what code should: automating the boring stuff so I can focus on the hard problems.

If you’re building internal tools with Laravel and Filament, don’t write a monolithic generator. Build a pipeline. Break it down. Test each piece. Let the machine do the typing. You’ll ship faster, break less, and actually enjoy maintaining your tooling.

Newer post

Building a Schema-Driven Mobile UI: How I Made HomeForged Configurable Without Code

Older post

How I Replaced Legacy Automations with a Scalable Workflow Engine in HomeForged