Course Content Authoring
Schema authority: all primitive field names (unit / concept / prompt / task / material / quiz / faq / illustration) come from
_shared/domain-primitives.md
. When this skill mentions a field, that file is the source of truth.
Filename convention (English-first): all generated files and directories use English names. The mapping from legacy Chinese names is in
_shared/domain-primitives.md
§0.
This skill produces the
teaching substance of a course: the things a learner reads, copies, listens to, or works through. It anchors every artifact to the outline IDs from
, so the next stage (SPA conversion) can wire them up mechanically.
Deliverables (Standard Layout)
course-package/ (your project's content root)
├── day{n}/
│ ├── outline.md ← from outline stage (do NOT edit here)
│ └── content.md ← THIS skill writes: lecture script, prompts, exercises, references
├── shared-scenario.md ← from outline stage
├── supporting-docs.md ← THIS skill writes: FAQ, environment setup, pre-reading
└── materials/ ← THIS skill writes: standalone learner artifacts
├── README.md ← index of materials
└── *.md, *.csv, *.yaml ← samples, templates, datasets
Material Types (Pick What Fits Your Course)
The example workshop uses these — they're examples, not requirements. Decide per course what makes sense:
| Type | Format | When to use |
|---|
| Lecture script | | Per-day teaching narrative, embedded in |
| Sample document | | A "before" artifact learners will improve (e.g. an FAQ, a policy doc) |
| Tabular dataset | (UTF-8 BOM!) | Practice data for AI processing exercises |
| Structured config | | When the exercise involves declarative configuration |
| PDF reference | | Official documents (laws, regulations) — usually external sources |
| Prompt template | block | Domain-specific reusable prompts (this course uses RTFC framework, others may not — adapt to your course's pedagogy) |
| Quiz items | inline in or separate | Pre-test, post-test, comprehension checks |
| Worksheets | | Fill-in templates learners complete |
About prompt templates: This skill is agnostic to which prompt framework you use. RTFC (Role / Task / Format / Context) was used in the original workshop, but if your course teaches a different framework (e.g. CRISPE, COSTAR, plain examples), use that. Don't force RTFC into a course where it doesn't fit. The framework is part of the course content, not a property of this skill.
CSV Trap (Easy to Miss)
When generating CSV files that will be opened in Excel by non-developer learners,
prepend a UTF-8 BOM (
):
js
const content = '' + headerRow + '\n' + dataRows.join('\n');
Without it, Excel on Windows mis-detects encoding and shows mojibake. Learners will think the file is broken. This bug was found late in the example workshop — bake it in from the start.
Anchor Everything to Outline IDs
Every artifact you produce must trace to a unit ID. Use this header pattern in lecture notes:
markdown
## u-3: {Unit title from outline.md}
**對應任務**: d2-u3-t1, d2-u3-t2
**對應素材**: 客訴處理SOP.md, FAQ官方版.md
**圖片需求 (illustrations)**:
- `day2-u3-hero.png` — hero / 主視覺:{學員角色} 在 {情境} 操作的場景圖(AI 生圖)
- `day2-u3-flow.svg` — 概念流程:{步驟 A → B → C}(手繪 SVG,含中文標籤)
- `day2-u3-example.png` — 結果範例截圖(選填)
{lecture content here}
Why: the SPA conversion stage will read these markers to auto-link tasks, materials, content,
and visual asset slots. If you skip them, the SPA author has to re-read everything to figure out the wiring, and Stage 5 (
) has no spec to generate against — you end up with a site that has only a cover image.
Task IDs Are Forever
When writing task descriptions inside
, assign each task a stable ID (e.g.
). These IDs will become
localStorage keys in the deployed website. Three rules:
- Never rename a published task ID. Students' progress is keyed to it.
- Never reuse a deleted task ID. If you remove a task, the ID retires permanently.
- Two formats coexist in practice ( and ). Pick one for new content; don't mix.
Quiz Item Discipline
If the course has a quiz, write items numbered sequentially (
,
, ...). Be aware these numbers will leak into multiple places once on the SPA:
- The quiz array itself
- A -style helper that maps each item to its source chapter (so wrong answers can link back)
- Hardcoded strings in the SPA: , score display , passing threshold
Renumber-safe authoring: think of the quiz as
append-only. If you delete
, leave the slot empty in your draft and renumber only at the very last stable moment, with a checklist of all the places to update.
Hidden Materials Pattern
Some materials are
for instructors only (answer keys, pre/post-test scoring) or
conditional (only shown if a feature flag is on). Mark them explicitly in
:
markdown
|---|---|---|
| 員工差勤辦法.md | 學員 | Day 2 公開素材 |
| 結訓測驗解答.md | 講師 | 不要納入 SPA materials[],僅講師端使用 |
The SPA conversion stage will read this column and exclude instructor-only items.
Anti-Patterns
- Writing content before outline is locked — every back-edit cascades to multiple files.
- Embedding prompt frameworks the course doesn't actually teach — if your course doesn't use RTFC, don't force-fit it just because the example template has it.
- Quiz items without source-chapter mapping — when a learner gets one wrong, they need to know where to review. Tag every quiz item with the unit it came from.
- Long flat material list with no instructor / learner distinction — by Day 4 the instructor doesn't know which file is what.
- Forgetting CSV BOM — see above.
Completion Gate (Hard Rule — must pass before hand-off)
Before declaring "content draft complete" and suggesting
, every item below must have a
written artefact in the corresponding
file (not just a verbal "yes"). Walk the user through them; if an artefact is thin or missing, ask one clarifying question and finish it before moving on.
- Per-day exists for every Day declared in table. A Day file with only the title heading fails — it must contain unit sections.
- Every outline unit ID has a matching section in its day's . Run a quick diff: list of unit IDs in must be a subset of headings in . Missing sections fail the gate.
- Every unit section has substance — at least one of: lecture script ≥ ~10 lines, listing real task IDs, listing real material filenames. A unit that only has a heading + placeholder fails.
- Every unit section declares with 1–3 entries. Each entry must specify (a) filename stem (e.g. ), (b) image kind ( / / / ), (c) one-line spec for the visual asset author. Units that genuinely need no image must declare a single waiver line:
- waived: {reason, e.g. 5-min admin slot}
. Silence does not pass.
- Quiz items (if applicable) tagged with — every item points to a real unit ID so wrong answers can route students back to the source chapter. Untagged items fail.
- exists with the material index, distinguishing 學員 vs 講師 columns (see Hidden Materials Pattern above).
If the user pushes "可以了,先轉成網頁" before all items have written artefacts, refuse politely:
「Stage 2 還有 N 個單元沒寫實質內容(或沒設圖片需求)。直接進 Stage 3 會生出薄殼網頁,學員看到只有標題 + 沒插圖。先把第 X 項補上,大概 Y 分鐘,比之後重做網頁省好幾倍。」
If the user explicitly demands a thin demo (與
Stage 2 Override Policy 相同條件):依照 orchestrator 文件的三步驟(標 stub 註解、設
、明確告知學員顯示效果)才放行,不要在 Stage 2 內部偷偷放水。
Hand-off
When this stage finishes (Completion Gate passed), you should have:
- Per-day filled in, every outline unit ID covered by a section
- Each unit section: lecture script + tasks + materials refs + 1–3 entries
- All material files in with an index README distinguishing 學員 / 講師 items
- Quiz draft (if applicable) numbered with source-chapter tags
- Every artifact traceable to an outline unit ID
Tell the user: "content draft complete. Next stage (
) will convert this into
+
, including an
array per unit derived from your
blocks. After Stage 3/4,
will fulfil those slots — your spec lines become its prompt input. Don't change unit IDs or task IDs from this point — they'll become localStorage keys."