Course Sites Want Versioned Providers, Not One More Core

repopatterntypescriptarchitecturegremlincontent-providercourse-sitesdesign-systems

Maps Gremlin/custom course sites to versioned provider packages instead of shared-core coupling.

The interesting bit in CodeTV isn’t a page or a component. It’s the split under packages/: @badass-courses/content-provider-course-builder and @badass-courses/content-provider-sanity.

Both packages do the same shape of work: query a backing source like PlanetScale or Sanity Content Lake, validate the data with Zod, and transform it into a StructuredContentGraph from @badass-courses/gremlin-sdk. The site gets getCourseGraph, listCourseSlugs, and listCourses instead of learning how every old content system stores its weird shit.

That is the clever part. Gremlin doesn’t need one overloaded core package that slowly becomes a junk drawer. It needs versioned provider boundaries: content provider, database adapter, commerce provider, marketing email provider, transactional email provider, and a shadcn registry for the design system.

This maps cleanly to the thing Joel called out in Slack: standalone repos for CodeTV, Kent C. Dodds, Code with Antonio, and whatever comes next, each depending on specific versions of shared packages. More painful up front. Less cursed six months later.

Key Ideas

  • content-provider-course-builder wraps the CourseBuilder data shape and exposes a tiny provider API: getCourseGraph, listCourseSlugs, and listCourses.
  • content-provider-sanity wraps Sanity episodes into the same graph shape, including video metadata like Mux playback IDs and YouTube IDs.
  • StructuredContentGraph is the contract. Source-specific code stays behind the provider boundary instead of leaking through the site.
  • core is overloaded language here. Naming smaller provider packages makes ownership and versioning clearer.
  • A shadcn registry fits the same pattern for shared UI: sites pull explicit design-system resources instead of inheriting an implicit app-shaped dependency.