Content spec
This page summarizes SPEC.md - the contract between content and app.
Content is plain markdown/YAML with zero references to the runtime, so
everything ports unchanged to any future implementation.
Track layout
Section titled “Track layout”tracks/<track-id>/├── track.yaml # title, description, optional provenance, ordered lesson list├── <lesson-id>/│ ├── lesson.md # frontmatter (title) + GFM body│ └── sandbox/ # optional - Dockerfile presence enables the terminal│ ├── Dockerfile│ └── … # seed data, scripts├── interview-prep.md # recommended└── resources.md # recommendedLesson conventions
Section titled “Lesson conventions”Inside lesson.md bodies:
> **Tip:** …blockquotes render as highlighted callouts.- Conceptual sections end with “Explain it” verbal-articulation prompts.
- Tool mentions: when a lesson uses a tool it doesn’t teach, it gives
a one-line survival hint at first mention (e.g. “
nano- Ctrl+O saves, Ctrl+X exits”) rather than assuming familiarity. External links are reserved for concept-sized topics, point only at official references (man pages, the tool’s own docs - never blogs or tutorial sites), appear at first mention only, and are calibrated to the track’s level. A lesson needing more than two or three such links is assuming too much for its level - the fix is teaching the tool or changing the level, not more links.
Quiz blocks
Section titled “Quiz blocks”A fenced code block with language quiz containing valid JSON:
```quiz{ "questions": [ { "q": "What does WHERE filter?", "options": ["Rows before grouping", "Groups after aggregation"], "answer": 0, "explain": "WHERE filters rows; HAVING filters groups." }] }```answer is the zero-based index of the correct option.
Sandboxes
Section titled “Sandboxes”The runner builds the lesson’s sandbox/ directory, runs it with 512 MB / 1
CPU limits, and attaches the terminal via bash -l. Images must include
bash, create /work, and provide an executable check on PATH.
Terminal working directory
Section titled “Terminal working directory”The terminal opens in /work by default. When the exercise’s files live
elsewhere, the image declares it so the learner lands where the work is:
LABEL supercharger.workdir="/var/www/site"Keep the /work default only when starting away from the files is the point
(e.g. filesystem navigation is the skill) - and then the lesson must say
where the files are. Every command shown in a lesson body must work verbatim
from the directory the terminal opens in, and lessons must warn where a
correct command legitimately prints nothing (grep with no match), so silence
isn’t mistaken for a broken environment.
The check contract
Section titled “The check contract”check prints JSON to stdout:
{ "checkpoints": [ { "name": "Table orders_clean exists", "pass": true }, { "name": "Query saved to /work/answer.sql", "pass": false, "hint": "Save your final query in /work/answer.sql." }] }All validation logic runs inside the container; the lesson auto-completes when every checkpoint passes.
preps/<prep-id>/├── job-posting.md # written by the app├── resume.md # optional, written by the app├── analysis.md # requirements → skills; inferred items flagged├── plan.md # ordered study plan linking tracks/lessons├── interview-prep.md # role-specific questions and talking points├── curriculum.json # optional ordered curriculum for the prep UI├── onboarding-requests.json # optional product-doc onboarding requests├── onboarding/<id>/source.md # optional pasted docs/excerpts└── track-requests.json # optional requested tracks for agent handoffAny .md files in a prep render as tabs in the app. curriculum.json renders
as the Curriculum tab when present.
Curriculum
Section titled “Curriculum”curriculum.json defines the best study order across existing tracks and
requested gap tracks:
[ { "id": "sql-fundamentals", "kind": "existing", "level": "beginner", "order": 1, "modificationHints": "Posting emphasizes log investigation - consider a log-table query scenario." }, { "id": "readme-product-onboarding", "kind": "docs-onboarding", "level": "beginner", "order": 2 }, { "id": "api-debugging-ai-support", "kind": "requested", "level": "intermediate", "order": 3 }]modificationHints is an optional per-item string written during prep
generation: a job-posting-specific suggestion for how an existing track could
be tuned for this role. The app surfaces it as a one-tap suggestion when the
learner opens the Modify form. Agents should only write it where the posting
genuinely suggests a tuning - never generic advice.
The app treats tracks/<id>/track.yaml as the source of truth for whether a
track is ready. If the folder exists, the Curriculum tab shows Start and
lesson progress. If it does not, the item remains a request.
The app can reorder curriculum.json when the learner moves tracks in the
Curriculum tab. Agents should preserve intentional ordering unless asked to
optimize the sequence.
Product docs onboarding
Section titled “Product docs onboarding”onboarding-requests.json stores approved docs sources for product-specific
practice:
[ { "id": "readme-product-onboarding", "title": "ReadMe Product Onboarding", "kind": "docs-onboarding", "goal": "support-product", "level": "beginner", "docsUrl": "https://docs.example.com", "sourcePath": "onboarding/readme-product-onboarding/source.md", "notes": "Focus on API references, auth setup, and common support issues.", "status": "suggested", "createdBy": "User" }]Docs onboarding should create operational fluency, not a summary. Expected outputs include product map, glossary, relevant workflows, common failure modes, mock support tickets, customer reply practice, escalation-writing practice, final readiness assessment, and suggested tracks only for remaining gaps.
Agents must use only approved source docs and flag assumptions when they infer behavior not directly supported by those sources.
Track requests
Section titled “Track requests”track-requests.json gives agents and the GUI a machine-readable creation
queue:
[ { "id": "api-debugging-ai-support", "title": "API Debugging for AI Product Support", "level": "intermediate", "depth": "standard", "priority": "high", "reason": "The role emphasizes customer API debugging and command-line reproduction.", "status": "suggested", "createdBy": "Codex" }]Requests live in two places with the same entry format: per prep at
preps/<prep-id>/track-requests.json, and - for standalone tracks not tied
to any prep - a track-requests.json at the repo root, written by the
home screen’s Add track button. Standalone tracks omit sourcePrep from
their track.yaml.
The app may update status to creating or modify-requested. An external
agent reads that state, creates or revises the track, sets status back to
created when done, and records provenance in the track’s track.yaml, for
example:
title: API Debugging for AI Product Supportdescription: Reproduce customer API issues with curl, request IDs, auth headers, and escalation notes.level: intermediatedepth: standardicon: worldcreatedBy: CodexsourcePrep: product-support-specialistmodifiedFor: [acme-tse] # preps this track was later tuned formodifiedBy: Claude Code # tool that applied the latest modificationlessons: - 01-reading-api-docs - 02-auth-header-mistakesModification requests
Section titled “Modification requests”A modify-requested entry carries modificationNotes (what to change), an
optional target level, and a mode:
mode: "in-place"- revise the track where it is, and add the prep’s id tomodifiedFor(plusmodifiedBy) in itstrack.yaml. The app rendersmodifiedForas a tuned for tag - green in the prep it was tuned for, a warning in any other prep using the same track.mode: "fork"- leave the original untouched. The request includes aforkToid (<track>-<prep>); the agent copies the track there, applies the changes to the copy withparentTrack,sourcePrep, andmodifiedForset, and repoints the prep’scurriculum.jsonat the fork.
Agents should keep lesson directory ids stable during in-place modifications
when the learner has progress on them, because progress.json keys by
<track>/<lesson>.
icon is optional and picks the duotone icon shown on the track card (e.g.
disk for SQL, world for APIs, bug for debugging, chip for CLI tools).
The repo’s SPEC.md lists all allowed names; without it the app guesses from
keywords in the title and description.
Learner level and depth
Section titled “Learner level and depth”Tracks and requests should set level:
| Level | Use when |
|---|---|
beginner | The learner has job context but does not yet know the tool, acronyms, or workflow. Define jargon before using it. |
intermediate | The learner knows the basics and needs realistic support-ticket practice. |
advanced | The learner is ready for edge cases, tradeoffs, and harder closed-book screens. |
Use depth to set the bar:
| Depth | Typical shape |
|---|---|
primer | 4-6 lessons for a compact foundation. |
standard | 6-8 lessons for most job-ready tracks. |
deep-dive | 8-10 lessons for advanced or broad topics. |
Six lessons is a reference pattern, not a rule. Do not pad a narrow topic, and do not compress a broad beginner topic so much that it starts using unexplained jargon.
Progress
Section titled “Progress”progress.json at the repo root holds lesson completion and quiz state. It
is personal data: content generation and app updates must never modify it.