How I Built an AI Content Engine That Writes My Blog

I got tired of AI blog generators producing unpublishable slop, so I built a content engine with guardrails: structured output, a controlled SEO vocabulary, and free auto-generated images.
The problem with “AI blog generators”
Most AI writing tools have the same failure mode: you give them a topic, and they hand back something that looks like a blog post but can’t actually be published. The meta description is the wrong length, so Google truncates it. The tags are hallucinated keywords nobody searches for. There’s no image. The slug has spaces in it. Half the time the “article” is 300 words of filler.
So you spend forty minutes editing what the AI promised would save you forty minutes.
I wanted something different. A system where a single input produces a post that is publishable as-is, with correct metadata, on-brand keywords, an illustration, and a body with actual substance. Not “AI-assisted.” Automated, with guardrails strong enough that the AI physically cannot hand me garbage.
This post is the result. It was generated, validated, and illustrated by the exact pipeline it describes.
Guardrail #1: structured output, not freeform text
The core mistake people make is asking a model for prose and hoping it remembers all the constraints. It won’t. The fix is to stop asking for prose and start asking for a validated data structure.
My draft generator calls a large language model (currently GLM-4.7, served on Cerebras for speed) in strict JSON mode, then runs the response through a schema before it’s allowed anywhere near the blog. The schema isn’t a suggestion. It’s a hard contract:
- Title must be 10 to 80 characters.
- Slug must be valid kebab-case (
like-this, neverLike This). - SEO description must be 140 to 160 characters, exactly the window Google shows in search results, so it never gets truncated or padded.
- Tags: between 3 and 8.
- Body: at least 800 characters of real content.
- Hero image prompt and alt text: required, with their own length bounds.
If the model returns a title that’s too long, or a slug with a space, or a meta description that’s 200 characters, validation rejects the whole draft. There’s no “mostly correct” output sneaking through. Either it meets the contract or it doesn’t exist. That single design decision is the difference between a toy and something I trust to publish.
Guardrail #2: a controlled SEO vocabulary
Left to its own devices, a language model will invent keywords. Ask it for tags about automation and you’ll get “synergistic AI paradigms” and other phrases real humans never type into a search bar.
So I took the choice away from it. The engine loads a curated keyword vocabulary I maintain, split into primary terms (the things I actually want to rank for), secondary terms, and long-tail templates. The model can only tag a post using words from that list. It can’t drift off-brand, it can’t chase keywords irrelevant to my work, and it can’t hallucinate. The SEO strategy stays in my hands. The model just fills in the writing.
This is the pattern I reach for constantly in automation work: let the AI do the open-ended part, but constrain every decision that has a right answer.
Guardrail #3: free illustration, dogfooded
A post without an image looks unfinished, and stock photos are expensive and generic. So the engine generates its own hero image.
The draft schema already forces the model to produce an image prompt alongside the text. That prompt gets sent to Pollinations.ai, which returns a 1024x576 image, the right aspect ratio for a blog hero, with no API key and no cost. The image at the top of this very post was generated that way, from a prompt the model wrote about its own article. The whole thing illustrates itself.
Guardrail #4: it can’t be abused
Anything that calls a paid model and writes files needs a lock on the door. The generation endpoints sit behind two things: an in-memory per-IP rate limiter, so nobody can hammer the API in a loop, and admin-only gating, so the generation routes aren’t open to the public internet. Cheap to build, and it means the engine is safe to leave running.
The publishing layer
Once a draft passes validation, publishing is deliberately boring, which is the point. Posts are plain markdown files with frontmatter. A small library reads the frontmatter (title, tags, dates), renders the markdown to HTML, and calculates the reading time automatically. Next.js serves everything with incremental static regeneration, so pages are static-fast but still update when content changes. No database, no CMS, no monthly bill. The content is the source of truth, version-controlled in the repo like everything else.
The result
Here’s the full path: I pick a topic, the engine generates a schema-valid draft with on-brand tags and a perfectly-sized meta description, illustrates it with a free generated image, and drops a publishable markdown file into the blog. What used to be an afternoon of writing and formatting is now a single run, and nothing reaches the page unless it satisfies every rule I care about.
The deeper point isn’t “AI can write blog posts.” It’s that the value is in the guardrails, not the model. The model is interchangeable. I upgraded it once already without changing anything else. What makes the system trustworthy is the schema that rejects bad output, the vocabulary that keeps it on-brand, and the safety rails around the whole thing.
That’s the same thing I build for the businesses I work with. Not “we added AI,” but a system where the AI is boxed in tightly enough that you can actually rely on what comes out the other end.
Want results like this for your business?
Let's talk about automating your busywork. Book a free 15-minute call.


