Skip to content

Course Map Schema Publishing

What ships today

  • TS source of truth: packages/course-map-shared/src/types.ts (CourseMap).
  • Generated JSON Schema: packages/course-map-shared/schema/course-map.v1.json β€” checked in, draft 2020-12, additionalProperties: false everywhere.
  • Generator: npm run schema:generate -w @course-map/shared (uses ts-json-schema-generator, reads JSDoc tags).
  • Drift check: npm run schema:check -w @course-map/shared β€” runs in CI when course-map types or the schema file change.
  • Version constants: COURSE_MAP_SCHEMA_VERSION (1.0.0) and COURSE_MAP_SCHEMA_URL exported from @course-map/shared.
  • JSON exports: GET /api/course-maps/:id/export.json stamps every download with $schema + schemaVersion as the first two keys, so ajv and IDEs bind validators automatically.

What hasn’t shipped yet

  • Hosting: The canonical $id is https://schema.theaccessible.org/course-map/v1.json, but the domain does not resolve yet. Downloaded JSON files reference it; following the URL 404s today.

Hosting plan

When ready to publish:

  1. Stand up a small Cloudflare Pages project at schema.theaccessible.org.
  2. Serve the generated course-map.v1.json at /course-map/v1.json, with Cache-Control: public, max-age=300, must-revalidate and CORS * (it’s a public spec).
  3. Set up a GitHub Action that re-publishes the file on every push to main that touches packages/course-map-shared/schema/.
  4. After publication, smoke-test with ajv -s <url> -d <export.json>.

Versioning

  • MAJOR bumps change the URL (/course-map/v2.json). Add the new schema file alongside the old one; keep v1 available indefinitely.
  • MINOR/PATCH bumps stay at the same URL but increment COURSE_MAP_SCHEMA_VERSION. Only backwards-compatible additions are allowed.
  • A change is breaking if it: removes a property, narrows a string format/pattern, removes an enum value, or makes an optional property required. Anything else is non-breaking.

How to evolve the schema

  1. Edit packages/course-map-shared/src/types.ts (add fields, refine JSDoc).
  2. Bump COURSE_MAP_SCHEMA_VERSION accordingly.
  3. Run npm run schema:generate -w @course-map/shared and commit both files in the same PR.
  4. CI drift check will fail otherwise.

Why the schema doesn’t validate catalogUrlTemplate as a URI

The template contains {code} / {subject} / {number} placeholders, which are not valid in RFC 3986 URIs. The schema uses a pattern regex to require a http(s)://... prefix and at least one placeholder; full URI validation happens after substitution at use sites (substituteCatalogUrl).