Read-only access for AI agents
The course is a resource. The site is its access surface. No auth, no accounts, no write endpoints — just three ways for an agent to read it.
1. llms.txt
The fastest way in. A plain-text index of every lesson, one URL per line. Point an agent at /llms.txt and it can decide what to read.
GET /llms.txt
2. REST API
Search the catalog, fetch lesson markdown, fetch any page as markdown. Three endpoints, all GET, all public.
GET /api/v1/catalog?q=worktree&limit=10
GET /api/v1/resource?path=phases/00-setup-and-tooling/01-dev-environment
GET /api/v1/markdown?path=/catalog
Typed specification: /openapi.json.
3. MCP server
Streamable HTTP at /mcp. Two tools, both read-only:
| Tool | Description |
|---|---|
search_curriculum | Search lessons by query, kind, or phase |
read_resource | Fetch a lesson's markdown by path |
Manifest: /server.json (also served at /.well-known/mcp.json).
Content negotiation
Every page on this site has a markdown twin. Add Accept: text/markdown and the server returns markdown. Example:
curl -H "Accept: text/markdown" http://127.0.0.1:4180/about
# returns the about page as markdown
Limits
- 120 requests/minute/IP per endpoint
- No authentication — public read-only
- No CORS restrictions on the API surface (lessons are public, agents are the audience)
- All routes serve both HTML and markdown
Errors
RFC 9457 problem details with stable code, explanatory detail, and recovery hint. Real 404s, not HTML error pages.
Lessons as files
Every lesson is also a markdown file on disk at the canonical path:
phases/NN-phase-slug/NN-lesson-slug/docs/en.md
You can read lessons directly from the source repo, with no API in the way. The API exists for the cases where you want filtering, search, or a single source of truth.
Running this locally
The site is static and dependency-free. node scripts/serve-site.mjs serves it on 127.0.0.1:4180 and implements every endpoint on this page, so the API above is real rather than aspirational:
node scripts/serve-site.mjs --port 4180
Opening site/index.html from disk is not the same thing — the lesson pages use relative links, and Accept: text/markdown needs a server to read it.