DEVELOPER / API

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:

ToolDescription
search_curriculumSearch lessons by query, kind, or phase
read_resourceFetch 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

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.