Authoring kit
This site is two things. It's Workshop 01, "Agent-ready". It's also the prototype for how Factory Academy builds every workshop after it. This section is the second thing: the principles, the file structure, the data files and the steps to start the next workshop from this one.
If you're writing a lab, read these in order:
- This page, for the principles and the structure
- The lab template, which you copy
- The component reference, for what each block does and its props
- The voice guide, for how the prose should sound
- The publishing checklist, before anything ships
The principles
Five rules shape every page. Each exists because the alternative produces a workshop people finish and forget.
One idea per lab
Every lab teaches exactly one new idea, stated in one sentence in src/data/labs.ts and shown at the top of the lab by <LabMeta>. If you can't write the sentence, the lab isn't ready. If you need two sentences, it's two labs.
Lab 5's idea is "a hook runs your code on every tool call it matches". Everything in the lab serves it: the gap it closes, the hook, the hole in the hook, the fix, the check on the outcome. Things that don't serve it become extensions.
A scenario with stakes
Every lab exists because a story needs it. Larkspur's story is a rounding change that reached 11,400 customers, and a head of Model Risk who won't sign without controls. Each lab's "Why this matters" names a person from the scenario and a real consequence.
A good scenario has an incident that the whole workshop prevents, three to five people with conflicting needs, and a measurable goal. It is fictional, and says so, but its shape is one the reader recognizes from their own job.
Measure first
Lab 0 sets up a scoreboard before anything changes, and every lab ends by re-running it. Some labs move the number. Some shouldn't, and saying so is part of the lesson. A workshop about making something better needs a way to show it got better, and a way to catch when a change made something worse. Lab 5's T3 regression is the most valuable number on the board.
Break it on purpose
Every lab has one step where the learner breaks the control they just built. The first hook gets bypassed by sed. The first permission rule has a typo that makes it skip quietly. A learner who has watched their own control fail understands it in a way no explanation achieves, and they'll test the next one without being asked.
Every number labeled
Scoreboard figures, transcripts and receipts are illustrative until the workshop is piloted, and every one carries a badge that says so. Every product fact comes from one checked fact sheet with a date on it. A workshop that teaches engineers to be honest about what their controls guarantee can't overclaim its own evidence.
How the site is organized
docusaurus.config.ts# customFields.academy: everything that differs per workshopsidebars.ts# the lab ids, in orderreference/factory-facts.md# the only source for product facts, datedWRITING-BRIEF.md# what every writer reads firstdocs/intro.mdx, scenario.mdx, setup.mdx, concept-map.mdxlabs/# one file per lab, same anatomysolutions/# finished state per labguides/# standalone practical guidesauthoring/# this kitinstructor-guide.mdx, run-of-show.mdx, facilitator-keys.mdxsrc/data/# labs, scoreboard, people, glossary: the content components readcomponents/# the MDX componentscomponents/playground/# interactive tools, embeddable and full-pagetheme/MDXComponents.tsx# registers every component for every .mdx filepages/# home, start, playground, mission, assessment, plan, talk, academylib/# shared hooks and the permission-rule simulatorscripts/check-mdx.mjs# compiles MDX and checks components and linkscompanion/# git-ignored: clone the companion repo here to authorlarkspur-payments/# github.com/mrlynn/larkspur-payments, with harness-reference/
The data files
Content that appears in more than one place lives in src/data/, written once. Change it there and every page that reads it changes.
| File | What it holds | Read by |
|---|---|---|
labs.ts | Every lab: number, slug, title, minutes, phase, the one idea, the tag, what it builds on, and whether it moves the scoreboard | <LabMeta>, <LabTrack>, the home page, the study plan, the run of show |
scoreboard.ts | The tasks, their checks, and a snapshot of passes after each lab that moves the number | <Scoreboard>, <ScoreboardDelta> |
people.ts | The scenario's people: name, role, initials and what they need | <Persona> |
glossary.ts | Every term, its plain-English definition, the home lab and related terms | <GlossaryList>, <Term> |
agentsMd.ts | The before-and-after AGENTS.md for Lab 2 | Lab 2, its solution, the AGENTS.md scorer |
Two rules. A lab title in labs.ts must match the lab's frontmatter title exactly. And every number in scoreboard.ts is illustrative until the pilot replaces it with a measured run.
Authoring rules that keep the build green
- Validate every file with
node scripts/check-mdx.mjs <files>. It compiles the MDX with the same version Docusaurus uses, and checks that every component is registered and every relative link resolves. Run it with no arguments to check all ofdocs/. - Curly braces and
<in prose go inside inline code or code fences. MDX reads them as JSX otherwise, and the build fails. - Link docs with relative file paths (
./labs/lab-2-agents-md.mdx) and site pages with absolute paths (/playground/hooks). - Every product fact comes from
reference/factory-facts.md. If it isn't there, leave it out or say "check the docs" and link to them.
Starting workshop 02
Copy this repository. Then work through three places, in this order.
1. customFields.academy in docusaurus.config.ts
One block holds everything that differs between workshops at the site level:
const academy = {
track: 'Platform track',
workshopNumber: '01',
workshopTitle: 'Agent-ready',
companionRepo: 'https://github.com/mrlynn/larkspur-payments',
companionDir: 'larkspur-payments',
discussionsUrl: 'https://github.com/mrlynn/larkspur-payments/discussions',
feedbackIssueUrl: 'https://github.com/mrlynn/larkspur-payments/issues/new',
factoryDocs: 'https://docs.factory.ai',
docsCheckedOn: '2026-09-29',
numbersAreIllustrative: true,
};
Change every field. Set docsCheckedOn to the date you rebuild the fact sheet, and leave numbersAreIllustrative as true until the pilot. Then update title, tagline and url in the same file.
2. src/data/*
Rewrite all five files for the new workshop. Start with labs.ts, because writing one sentence per lab is how you find out whether the sequence works. Then people.ts and the scenario, then scoreboard.ts with the new tasks. Write glossary.ts last, from the terms the labs actually use. Delete agentsMd.ts if no lab needs it.
Update the lab ids in sidebars.ts to match the new slugs.
3. docs/
- Write
scenario.mdxfirst. Every lab traces back to it. - Rebuild
reference/factory-facts.mdfrom the current docs, with the date. Write a newWRITING-BRIEF.mdfrom this one. - Copy the lab template once per lab.
- Keep
docs/authoring/as it is, and improve it where the new workshop taught you something.
What to keep, and what still carries Workshop 01
The components, the page frames, check-mdx.mjs and the authoring kit carry over unchanged. Workshop content lives in src/data/, and a few pieces still hold Workshop 01 content in code, so check both:
| File | What is specific to Workshop 01 |
|---|---|
src/data/layers.ts | The seven harness layers (ConceptCards, LabTrack) |
src/data/scoreboard.ts | The tasks, snapshots and the scoreboard title |
src/components/playground/* | Every tool is about the Droid harness and Larkspur's rules |
src/lib/permissionRules.ts | Larkspur's starting rule set |
src/pages/index.tsx, start.tsx, talk.tsx, mission.tsx, assessment.tsx | Page copy, the three doors, the hero session |
The playgrounds are the most expensive part to rebuild, and the most worth it. Budget for one or two new ones per workshop rather than seven.
Where the Academy fits
The Academy blueprint describes the tracks, the workshop anatomy across all of them, and how a workshop moves from draft to pilot to published. This kit is the practical half of that page.