Skip to main content
info@drupalodyssey.com
Friday, May 8, 2026
Contact

Main navigation

  • Home
  • Services
  • Case Studies
  • Blog
  • Resources
  • About
Search
Riterly is open for beta. Come see your voice.
Now Live
Development

Eight Cents a Post: How a Symfony CLI Tool Became a SaaS

May 08, 2026

In a previous post, I detailed how I created a CLI tool to help me write about what I know. Then that accidentally became a product.

The Blank Cursor Problem

Running a consulting practice, a full time Drupal architect job, and maintaining a technical blog are not compatible activities unless you're ruthlessly efficient about one of them. The Drupal Odyssey isn't a side project I dash off in twenty minutes — each post is a genuine technical artifact that takes real time to research, structure, and write with enough depth to be worth reading. Some nights I had the ideas and the notes but zero capacity to turn them into a coherent 1,000-word post that didn't read like a tired developer talking to himself.

The blank cursor was the symptom. The actual problem was the friction between "I know what I want to say" and "I have a publishable post." Every minute I spent fighting structure and phrasing was a minute not spent on the content that actually mattered — the architectural decisions, the tradeoffs, the things you only learn by doing.

I didn't want a ghostwriter. I wanted to reduce the latency between an idea and a post, without sacrificing the voice or the technical standards that make the blog worth anything.

Blueprints, Build, and a branding.md File

The solution is a two-pass PHP/Symfony CLI agent. The pipeline has two named stages: Blueprints and Build.

Pass 1 — Blueprints takes a topic, a set of reference materials, and the voice profile, then generates a structured outline and context notes. No draft. Just the architecture of the post — the sections, the angle, the key technical specifics that need to appear, written as an editorial brief.

Then it stops.

That's not a bug. The approval gate between Blueprints and Build is mandatory and explicit. You review the outline, adjust the angle, add specifics the agent missed, remove anything that's off. Only when you sign off does Pass 2 — Build fire, turning the approved brief into a full draft.

"Nobody pushes straight to production" is a phrase I use with clients. The same logic applies here. The outline review isn't ceremony — it's the point where your judgment as the lead architect enters the pipeline. The agent doesn't get to skip it.

Intermediate artifacts — outlines, context notes, research summaries — live in a cache/ directory. Think of it as a local RAG layer: structured, reviewable, and there if you need to rerun a pass without re-burning API tokens.

The agent's brain is branding.md. Not a prompt — a governance layer. It contains tone rules, banned phrases, audience definitions, structural constraints, phrase patterns, and CTA templates. When the agent generates output, branding.md is the spec it works against. If a phrase appears on the banned list, it doesn't appear in the draft. The voice isn't a vibe; it's a config file.

End-to-end cost: $0.04–$0.08 per post. At a weekly publishing cadence, for me, that's $4.16 per year. The API bill is genuinely the smallest problem in the room.

Why PHP, and Why It Matters

I built this in PHP/Symfony deliberately. Not because PHP is the only choice — it's not — but because the architectural patterns felt immediately native.

Service containers. Config-as-code. Structured pipeline components. If you've spent time building custom Drupal modules or wiring up services in services.yml, the Symfony CLI patterns are not foreign territory. The agent's structure maps directly to how a Drupal developer already thinks about dependency injection and configuration management. I wasn't learning new abstractions; I was applying familiar ones to a new problem.

To be clear: this is not a Drupal tool. There's no Drupal installation involved, no hook system, no entity API. But it speaks the same structural language — and for me, that mattered. A tool you understand architecturally is a tool you'll actually maintain and extend rather than abandon when it gets complicated.

The Drupal parallel turned out to be more than coincidence, but we'll get to that.

From One branding.md to Multi-Tenant

The moment the tool started working reliably, I asked myself if it, "Could work for my other blog too?"

That question changed everything. A personal CLI tool is held together by the author's own judgment. A tool used by strangers has to encode that judgment in the architecture itself — and be portable enough to hold multiple, completely distinct editorial voices at the same time.

The agent already supported multiple branding.md profiles. One agent instance, separate voice profiles per publication, completely isolated context. The Drupal Odyssey profile and, say, a DIY maker blog profile could coexist without bleed. That's the product seed: the governance architecture is portable, not personal.

The shift to SaaS-grade infrastructure meant adding Symfony Messenger for async AI generation — queuing generation jobs rather than running them synchronously in a CLI session. The pipeline stayed identical; the plumbing just got more robust.

The meta proof of the whole approach: Riterly now uses itself to write its own marketing copy. Also, feature specification files were fed to it to write it's own documentation. It held up.

That's also how the original "I Built a PHP Agent" post came to exist — the agent read its own source code as reference material and produced the draft. If that's not a working demo, I don't know what is.

Here's where the Drupal parallel stops being coincidence. DrupalCon Chicago 2026 Driesnote keynote announced the Context Control Center. The architectural mapping is direct:

CLI Tool Drupal CCC
branding.md AI Context config entities
cache/ directory RAG pipeline retrieval layer
Banned Phrases list AI Guardrails (AI module 1.3.0)
Two-pass approval gate Human-in-the-loop review workflow

The branding.md feature in the CLI tool was complete two months before the Driesnote. Same DNA, different packaging. When Dries walked through the CCC architecture, I recognized every component — not because I'd read the roadmap, but because I'd already built a portable version of it out of necessity.

That's either a great sign for the architecture or confirmation that the blank-cursor problem is universal enough that multiple people arrived at the same solution independently.

What It Is Right Now

Riterly is in private beta testing now. The pipeline works. The multi-profile capability works. The cost model is absurdly favorable. But a beta is not a finished product, and I'm not going to oversell it.

The one thing I want to be explicit about: the human gate is load-bearing. The AI Guardrails in the architecture — the global banned phrases, the structural constraints — catch known failure modes. They don't catch novel hallucinations that are technically within tone rules but factually wrong. A well-behaved confabulation still passes the filter.

Removing the approval gate between Blueprints and Build to "streamline" the workflow removes the load-bearing wall. The tool doesn't pretend otherwise. Full automation is a trap, and the pipeline is engineered to make that impossible to ignore: you cannot produce a draft without signing off on an outline first.

The mindset shift that made this work for me wasn't about AI — it was about stepping back from being the writer and becoming the editorial director of my own content. The agent is the compiler. The blueprints are mine. The judgment call at the gate is mine. The published post is mine.

That's the architecture. And now other people can use it too.

If the two-pass pipeline, the governance layer, or the multi-profile capability sounds like a problem you've already been solving in a messier way — that's the point. Come take a look.

Author

Ron Ferguson

 

Next Blog

0 Comments

Login or Register to post comments.

Ad - Header (728*90 AD)

Ad - Sidebar (300 x 600 AD)

Ad - Sidebar (300 x 250 AD)

Newsletter

Subscribe my Newsletter for new blog and tips.

Menu

  • Home
  • Services
  • Case Studies
  • Blog
  • Resources
  • About

Legal

  • Privacy Policy
  • Terms & Conditions
  • Disclaimer
  • Cookies

I specialize in custom development, performance tuning, and reliable maintenance, delivering clean code and strategic solutions that scale with your business. Ready to discuss your project?

E: info@drupalodyssey.com
Fort Worth, TX

© 2026 All Rights Reserved.

Proud supporter of active military, veterans and first responders.