Building and generating courses
Every course of your own starts from one button, Courses → Create a
course (/courses). Your courses are private until you share them (below).
On the course list each of yours has Open (to learn from it) and
Edit files (this page).
It makes a starter course called Untitled course, with one example lesson, and opens its page with the Generate the course dialog open. Fill it in to have AI write the course, or close it to write the course yourself.
Build one by hand
- Close the Generate dialog. Click the title at the top of the page to rename the course.
- The course page (
/courses/<id>) shows its lessons as a table. The first row is the course settings (course.json).- + on a unit adds a lesson there; name it on the spot.
- Click a name to rename it; drag a row by its grip (or focus it and use ↑ / ↓) to reorder it; ✕ deletes it.
- ⧉ duplicates a lesson: the copy, called “
(copy)”, lands right below it with new ids, ready to edit. - ▸ opens a row’s JSON in place. On a new lesson, paste a whole lesson file there. With the JSON switch (top right of the table) off, the same file opens as a form instead.
- Paste a word list (language courses) turns a list you already have,
one
word — meaningper line (or a comma,=or tab between them), into a new lesson with those words. It shows what it read first, and the lines it couldn’t, before you add it. No AI key needed.
- There is no Save button: every change is saved as you make it (typing, three seconds after the last keystroke). The circle by the course title is green ✓ when everything is saved, yellow while saving, and a red ! with the reason under the title when something is not. The whole course is checked on each save; if it would not load, nothing changes.
The Undo and Redo icons under the table take back the last stretch of editing (or the last AI change) and put it back, up to ten steps. Download all files, at the bottom of the page, exports the course as one JSON file.
The format: How a course is built, and every field in the course format.
Write lessons with an LLM you already use
Paste the course format (raw Markdown) into the chat, then ask for one lesson at a time:
Here is the course.json of my course (paste it). Write the lesson file for “Ordering coffee” in unit “1”, group “phrases”, following the format exactly. Reply with JSON only.
On the course page: + on the unit, name the lesson, ▸, paste the
reply. It saves itself. If it does not validate, paste the error back to the
model. An LLM that can fetch pages can start from /llms.txt
instead.
Scripts can send up to 100 files at once while signed in:
POST /api/courses/<id>/files with {"files": [{"path": "lessons/coffee.json", "content": "…"}]}. The reply lists what was saved and the course’s
validation error, if any.
Generate one with AI
The Generate the course dialog opens on a new course, and stays on offer (under Use AI) while you have only changed names (the title, lesson titles and lessons added by name). The AI keeps those names and plans the named lessons first. It needs an API key (Claude, OpenAI or Gemini) saved on your profile; without one the dialog is greyed out with a link to the profile.
- Say what you want to learn in a sentence or two.
- Optionally add your material: notes, homework, a syllabus (pasted, or text files dropped in; up to 60 000 characters). The course teaches exactly that.
- Pick the kind of course (or let the AI decide).
- Pick how much to write: the Full course (the AI decides how many lessons, up to 15), a Preview (one unit with one full lesson), or an Outline (every unit and lesson, each a bulleted list of what it will teach plus one example question). The (i) beside the choice explains them.
A progress modal shows the phase and a progress bar, with Cancel. On the course list the course is greyed out as generating, with a Watch link. The model writes an outline, then one lesson at a time; the app validates each one and, if it is wrong, sends it back with the error, up to twice. When it is ready the modal goes and the course’s lessons are there.
- A run that stops (error, cancel, restart) keeps what was written. Its card on the course list has a red ! that opens why. Resume writes only the missing lessons (or Retry when not even the outline was saved).
- To start a generated course over, delete it and create a new one.
Change a course with AI
Use AI, under the lesson table, uses the first API key saved on your profile (it names the provider only when you have two or more). The switch Allow changes to existing content picks the mode. A second switch, Outline only, makes the lessons it writes outlines instead of full lessons.
- Off, Only add: one new lesson, written and placed by the AI. Nothing else in the course may change, or nothing is saved.
- On, Allow overall changes (any course of yours that loads): say what should change (“more word problems”, “drop the history lesson”). The course keeps working as it was until the whole new version validates.
When the job ends, Review AI changes opens: every file the AI added, changed or removed, with a side-by-side diff. Review AI changes under Use AI opens it again later. Undo under the table brings the old version back.
With Do Not Show Me AI Features on in your profile, none of this is shown.
Share a course
Share on the course page: type e-mail addresses, Send invitations. Each person gets a link; the course then sits on their list (under Shared with you until opened). They learn from it with their own progress; only you can change it, and your edits reach them at once. The dialog lists every address with invited or opened; Remove stops sharing with one.
Fixing validation errors
Every error names the file and the field, for example:
lessons/coffee.json: unit 'B' is not in the manifest (units: A1, A2)
- On the lesson table, the save is refused and the red ! by the title says why; fix the JSON in the row (▸) and it is saved again.
- A course that does not load shows its files instead of the table, with the error on top: open the file named, fix it, Save and validate.
- Common causes: a
unitnot listed incourse.json, aquestion_idused twice in the course, a multiple-choicecorrect_answerthat is not one of itsoptions, aslugwith capitals or spaces.
The rules behind each error are in the course format.