When content is the product, lessons, listings, templates, images, questions, it's not "the writing part" you do at the end. It's an engineering problem wearing a writing costume, and it needs a schema, a validator, and a review process or it collapses under its own weight around item 200.
The concept
A lot of products are mostly content: a course, a template marketplace, a recipe app, a listings directory, a game with hundreds of levels, a knowledge base. For these, the viewer is a few days of work and the content is weeks, and nobody warns you about that ratio.
The failure mode is predictable. You hand-make the first ten items and they're great. You make the next hundred faster and they drift: quality sags, ideas repeat, formatting varies, and you lose track of which are finished. By item 300 you have a pile you can't trust and can't fully re-read.
The fix is to treat content like a dataset: give it a shape, validate it mechanically, produce it in reviewable batches, and record the rules you learn where the next author can't miss them.
Design the schema before item one
Every content item should have a fixed structure. That rigidity is the point:
- The renderer is written once and never special-cases.
- Categorical fields (type, tag, difficulty) make aggregation a
group by, not a heuristic. - A fixed shape means a validator can check every item the same way.
- Missing a field you need later is a feature you can't build; adding one at item 300 is 300 items of retrofitting.
Write five items by hand, extract the common shape, then freeze it. And give every item a stable ID, never address content by array position or display order, because reordering then silently invalidates every reference (Chapter 20).
The gold standard
Hand-craft one item to the exact quality you want. Everything after is produced against it, "match this." Quality is shown, not described. "Engaging," "premium," "cinematic" are unactionable until they're demonstrated or decomposed into criteria a stranger could apply (Chapter 24).
Batch to your review capacity
Produce in units you can actually review, a chapter, a level pack, a category. Not "all of it" in one pass. An unreviewed batch isn't produced content; it's accumulated content, and it's a liability. If you can't read it, you didn't make it, you hoped.
Validate mechanically
Past a few hundred items, human review stops catching systematic problems, a person cannot read 300 items and notice that answer B is correct 98% of the time, or that two items teach the same idea. Machines can. Build a validator that checks, on every batch:
- Syntax / structure, does every item parse and have every field?
- Counts, do you have what you think you have?
- Duplicates, repeated text, repeated ideas (embeddings + cosine similarity finds semantic dupes)
- Cross-references resolve, every link points at a real item
- Distribution / balance, answer positions, difficulty spread, category coverage
- Banned patterns, the rules you learned the hard way, enforced
Record rules in the artifact
Every rule you learn from a mistake goes in the content file itself, at the top, not a wiki, not a commit message. Where the next author (human or AI) cannot miss it before writing item 901. It's the cheapest quality mechanism there is.
Sensitive content needs written overrides
If any section touches health, safety, money, children, or anything where the standard mechanic could cause harm, write the exception into the content file as a rule and check it. Never trust yourself, a contractor, or a model to infer the ethical exception from context (Chapter 14).
📐 Best practice
Freeze the schema before item one, with stable IDs.
Hand-craft a gold standard and produce against it.
Turn "good" into a checklist, not adjectives.
Batch to review capacity, one commit per batch.
Validate mechanically on every batch, structure, counts, duplicates, references, distribution, banned patterns.
Pass an anti-repetition list when generating (the model has no memory of the last call).
Record hard-won rules in the file header.
Write safety overrides for sensitive sections and check them.
Fact-check anything verifiable. A wrong "fact" is a credibility hole.
Verify assets by measurement, not screenshots, caches lie (Chapters 28, 17).
💀 Common mistakes
No schema. Six shapes of the same object in production.
Addressing content by position. Reordering corrupts references silently.
Describing quality instead of showing it. "Make it engaging" produces nothing.
One giant "generate everything" pass. Quality collapses; nobody reviews it.
No anti-repetition context. Item 200 restates item 40, plausibly and invisibly.
No mechanical validation. Systematic bias ships because no human could see it.
Rules kept in your head. The next author repeats the mistake.
No safety overrides. A well-meaning item causes harm in a sensitive section.
Unverifiable "facts." A user fact-checks you and you're wrong.
"Just generate it with AI" and ship. Plausible content is the trap, 450 subtly-repetitive, structurally-identical, average items.
The professional workflow
1. SCHEMA — 5 hand-written examples → extract the shape → freeze it.
Stable IDs on everything.
2. GOLD STANDARD — one item at the real quality bar.
3. CRITERIA — convert "good" into an executable checklist.
4. BATCH — coherent units you can review (a chapter, a pack).
5. VALIDATE every batch
structure · counts · duplicates · references · distribution ·
banned patterns · assets resolve
6. SPOT-REVIEW a random sample. You can't read 900; you can read 20.
7. RECORD the rule learned — in the file header.
8. COMMIT per batch. Reviewable, revertable, visible progress.
Tools, websites & costs
| Need | Tool | Cost |
|---|---|---|
| Authoring at volume | Claude / ChatGPT | ~$20-100/mo |
| Storage | Plain data files in git (.js, .json, MDX) | $0 |
| CMS (if non-technical editors) | Sanity, Contentful, Payload | $0-99/mo |
| Validation | Ad-hoc scripts in your language | $0 |
| Semantic dedup | Embeddings API + cosine similarity | ~cents per 1000 items |
| Fact-checking | Web search + primary sources | $0 |
| Public-domain assets | Met, Rijksmuseum, Unsplash, Wikimedia | $0 |
| Image processing | sharp, ImageMagick, sips | $0 |
| AI image generation | DALL·E, Replicate, Fal | per image |
| Diff review | git diff | $0 |
Structured data files in git beat a CMS for machine-authored content that ships with releases: versioned, diffable, offline, no vendor. Add a CMS when humans other than you edit content.
Alternatives & trade-offs
Data files vs CMS vs database. Files are best for content that changes with releases and is authored by you. A CMS suits non-technical editors and frequent edits. A database suits content that changes at runtime. Most content-heavy products are the first case and reach for the second or third by reflex.
AI-generated vs human-authored vs curated. AI produces volume fast and drifts toward average. Human authoring is high-quality and slow. Curation (public-domain, licensed, user-generated) is cheap and constrains subject matter. Most successful content products blend all three with a human quality gate.
Depth vs breadth. More items or better items? For a differentiated content product, depth is the moat (nobody wants to do the labour), so breadth with a quality floor usually wins, provided the floor holds.
Generate-then-edit vs author-directly. Generating a draft and editing is faster and risks anchoring on mediocre structure. Authoring directly is slower and more original. For volume, generate-then-edit with a strong gold standard and criteria.
Checklist
- The schema is frozen and documented at the top of the file
- Every item has a stable ID, not a position
- I have a hand-crafted gold standard
- "Good" is an executable checklist
- Content is produced in reviewable batches, one commit each
- A validator runs on every batch: structure, counts, duplicates, references, distribution, banned patterns
- Generation passes an anti-repetition list
- Every cross-reference is checked to resolve
- Factual claims are traceable to a source
- Rules learned are in the file header
- Safety overrides exist for sensitive sections and are checked
- I spot-read a random sample, not just the first and last items
📓 Case Study: 1,350 items that stayed coherent
Project: SOLIS, which needed 450 structured lessons and 900 applied questions, well past the point where a human writes or re-reads each one.
The schema was frozen at item one, eight fixed fields per lesson, documented in a comment at the top of the file. That rigidity let the renderer be written once and let a validator check every item identically.
A hand-crafted gold standard anchored quality, the first lesson, written by hand, with every batch generated to "match this exactly." And the criteria were made executable through a process worth remembering: the instruction "dramatize the openings" produced nothing useful across three rounds of "I don't understand," until it was decomposed into a checklist, a scene is a specific moment + a place + a feeling + an action. That is applicable by a stranger. "Dramatize" is not (Chapter 24).
Content was batched by phase, 75 lessons at a time, each reviewed and committed separately, rather than generated in one pass.
⭐ Mechanical validation caught what no human could. A validator ran on every batch checking structure, counts, orphaned references, duplicate text, and answer-position balance. That last check found a defect invisible in any individual item:
The stronger answer sat in the second position in 294 of 300 questions.
A systematic bias, a user who noticed could score 98% by always picking the bottom option, collapsing the whole teaching mechanic. No amount of reading finds that; a distribution check finds it in a second. It was fixed by presenting options in a stable hashed order (three lines of code, zero content rewritten), which then broke every explanation that referenced an option by position, a new bug class created by the fix.
Both findings became authoring rules written into the file header:
AUTHORING RULES (learned the hard way):
- never refer to an option by POSITION — the renderer hashes the order,
so a positional reference can be inverted and made wrong;
- each explanation must stand alone; on a wrong pick the reader sees their
own choice, so one leaning on "the other" dangles. Name the thing.
A safety override lived in the same header. One section dealt with low mood, where "one option is stronger" could cause harm, so the rule was written in: rest, self-compassion and reaching out are never the weaker option there. Without it, a well-meaning question could ship "push through" as the stronger answer to someone struggling.
The image side was the same discipline at larger scale. The product needed 1,350 image slots and had a few dozen source images. Rather than repeat them, an early build showed the same painting up to 31 times, the fix was an assignment engine: source ~900 public-domain images tagged by theme, then assign each slot the least-recently-used image from its theme, never repeating within an item, spacing reuse maximally. Result: 837 distinct images across 1,350 slots, minimum gap ~449 slots between any reuse.
📐 Large-scale assignment is an algorithm problem, not a taste problem. Least-recently-used per theme bucket, in ~100 lines, beat any amount of manual curation.
⚠️ Deviation 1: content had no stable IDs. Lessons were addressed by array position. Reordering would silently invalidate every progress reference and every link between a lesson and its questions. Identified as a gap, never fixed, because by the time it was noticed there was already data keyed on positions (Chapter 20).
⚠️ Deviation 2: the generation prompts were never versioned or evaluated. The validators checked output structure, not output quality, so a prompt change that made the writing worse would have passed every check. For content generated once and human-reviewed, survivable; for a prompt running in production, it would not be (Chapter 24).
Lessons
- Content at scale is a data-engineering problem. Schema, validation, batching, review.
- Freeze the schema before item one, with stable IDs.
- Show quality with a gold standard; convert "good" into a checklist.
- Batch to review capacity. An unreviewed batch is accumulated, not produced.
- ⭐ Mechanical validation finds what humans structurally can't, the 294/300 bias.
- Fix presentation before regenerating where you can. And re-validate: every fix can create a new bug class.
- Record hard-won rules in the file header, where they can't be missed.
- Write safety overrides for sensitive sections and check them.
- Large-scale assignment is an algorithm, not a curation slog.
- Verify assets by measurement, not screenshots. Caches lie.