Skip to content

docs: ADR for Sanity CMS removal#1584

Open
zacjones93 wants to merge 1 commit intomainfrom
zac/sanity-removal
Open

docs: ADR for Sanity CMS removal#1584
zacjones93 wants to merge 1 commit intomainfrom
zac/sanity-removal

Conversation

@zacjones93
Copy link
Copy Markdown
Contributor

@zacjones93 zacjones93 commented Mar 17, 2026

Adds ADR-0004 capturing the decision to remove Sanity CMS entirely and replace it with Course Builder (MySQL) and egghead-rails (Postgres/GraphQL).

What's in this PR

  • Bootstraps docs/decisions/ ADR directory with index
  • 0004-remove-sanity-cms-and-replace-with-course-builder-and-egghead-rails.md — full MADR-style decision record

The decision

Sanity currently serves six roles in the app: lesson metadata overlay, course metadata, video resource storage, the Tips feature, 15 editorial content pages, and the instructor creation workflow. This ADR documents the decision to remove it entirely.

The ADR covers:

  • Why Option A (full removal) over keeping Sanity read-only or editorial-only — the operational cost (API keys, webhooks, Redis allowlist, Studio deployment) doesn't shrink meaningfully with partial removal
  • 8-phase implementation plan ordered by risk — Phase 1 (lesson overlay removal) is zero-risk and can ship immediately; Tips and the video upload pipeline are later phases gated on Course Builder having a write API
  • 13 verification checkboxes including rg commands, build checks, and operational steps (Sanity webhook deregistration, Redis key cleanup, env var removal)

The SANITY_REMOVAL_PLAN.md in the repo root is the research artifact that fed this ADR.

Summary by CodeRabbit

Release Notes

  • Documentation
    • Added architectural decision documentation outlining a multi-phase content infrastructure migration strategy, detailing the transition plan with specific implementation phases and verification steps.

@vercel
Copy link
Copy Markdown

vercel bot commented Mar 17, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
egghead-io-nextjs Ready Ready Preview, Comment Mar 17, 2026 3:01pm

Request Review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 17, 2026

📝 Walkthrough

Walkthrough

A new Architecture Decision Record (ADR) documenting the strategic removal of Sanity CMS and its replacement with Course Builder and egghead-rails. The document outlines an eight-phase decommission plan with specific technical actions, migration patterns, and verification steps across the content pipeline.

Changes

Cohort / File(s) Summary
Architecture Decision Records
docs/decisions/0004-remove-sanity-cms-and-replace-with-course-builder-and-egghead-rails.md
New ADR documenting comprehensive plan to remove Sanity CMS dependencies, migrate content ownership to Course Builder as source of truth, and decommission Sanity infrastructure across 8 phases including lesson metadata, course metadata, video resources, instructor workflows, tips content, editorial pages, curated overlays, and remaining utilities.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~15 minutes

Poem

🐰 A CMS farewell, phased out with care,
Course Builder and Rails shall fill the air,
Eight phases ahead, a strategic quest,
From Sanity's grasp to systems that rest,
New truth, new paths—a cleaner affair! 📚✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'docs: ADR for Sanity CMS removal' directly and accurately describes the main change: addition of an architectural decision record documenting the removal of Sanity CMS.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch zac/sanity-removal
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Tip

You can validate your CodeRabbit configuration file in your editor.

If your editor has YAML language server, you can enable auto-completion and validation by adding # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json at the top of your CodeRabbit configuration file.

@zacjones93
Copy link
Copy Markdown
Contributor Author

Sanity vs Course Builder — Live Data Audit

Ran a live cross-reference against Sanity project sb1i5dlc (production) and the Course Builder PlanetScale DB to validate the ADR assumptions. Full report in reports/SANITY_REMOVAL_AUDIT.md + rerunnable script at investigation/sanity-vs-cb-audit.ts in the migrate-egghead repo.


Numbers

Metric Count
Sanity course+resource docs 729
Sanity lesson docs 540
Course Builder courses 440
Course Builder lesson slugs 6,772
Sanity docs also in CB 412 ✅
Sanity docs not in CB 317 ⚠️
Real courses with lessons only in Sanity ~2 🚨
Published tips (no CB equivalent) 37 🚨
Blog posts (Sanity-only) 57 ⚠️
Guides (Sanity-only) 9 ⚠️
Case studies (Sanity-only) 17 ⚠️
Sanity lessons not yet in CB (exact-slug match) 220 ⚠️

The 729 "course" count is misleading

704 of those are _type = 'resource' — curated landing pages, topic pages, instructor pages. They break into:

Category Count Migration needed?
Curated topic pages (react, javascript, typescript…) ~40 No — remove loadSanityTag() code, base GraphQL data survives
Instructor landing pages (Filip Hric, Kadi Kraman…) ~10 No — remove per-instructor GROQ files, base GraphQL data survives
Promotional/collection resources ~240 No — archive (404 or redirect)
Real courses with lessons only in Sanity ~2 Yes 🚨

The 2 actual blockers (real courses, lessons in Sanity only)

  • fast-monorepos-with-pnpm-workspaces-and-nx17 lessons in Sanity, not found in CB
  • build-a-modern-cms-driven-web-applications-using-strapi-and-next-js-93cc097213 lessons in Sanity, not found in CB

These need to either be confirmed as retired/unpublished, or migrated to Course Builder before the Sanity overlay is removed.


The 220 "missing" lessons are probably fine

All first-20 samples have ~ tilde suffix slugs (CB-native courses). The exact-slug match misses them because CB stores them under hash-based IDs. A follow-up pass using the same hash-matching logic as getCourseBuilderLesson() should reduce this to near-zero.


Outstanding decisions

  1. 37 published tips — pure Sanity, no CB equivalent, no video attached. The ADR calls this out correctly. Retire or migrate?
  2. Topics content blocks (37 courses have them) — structured "What you'll learn" blocks in Sanity with no CB equivalent. These disappear when the overlay is removed unless CB gets a fields.topics field.
  3. Editorial export — 57 posts, 9 guides, 17 case studies need a sanity dataset export snapshot before the project is decommissioned.

ADR validation

The 8-phase order in the ADR holds up against the data:

  • Phase 1 (lesson overlay) — safe to ship now, CB already covers 412/412 matched courses
  • Phase 2 (course metadata) — safe after confirming the 2 Strapi/monorepo courses are retired
  • Phase 5 (tips) — still needs the decision
  • Phase 6 (editorial) — needs the export snapshot first

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@docs/decisions/0004-remove-sanity-cms-and-replace-with-course-builder-and-egghead-rails.md`:
- Around line 237-243: The markdown contains unlabeled fenced code blocks in
docs/decisions/0004-remove-sanity-cms-and-replace-with-course-builder-and-egghead-rails.md
(around the block listing src/utils/... at lines ~237-243 and the env var block
around ~258-272) which triggers markdownlint MD040; fix by adding a language
identifier (use "text") to the opening backticks of those fenced blocks so they
become ```text, ensuring both blocks (the file list and the environment variable
list) are updated; no other changes required.
- Line 233: Replace the mistaken recursive/replace ripgrep flags by changing
each occurrence of rg -r "sanity" src/ --type ts --type tsx to a plain search
(e.g., rg "sanity" src/ --type ts --type tsx or rg -n "sanity" src/ --type ts
--type tsx) so the verification step only searches and does not attempt
replacement, and add language identifiers (use txt) to the missing fenced code
blocks that list files and environment variables (the triple-backtick blocks
shown around the src/... list and the NEXT_PUBLIC_SANITY_PROJECT_ID list) so
they become ```txt.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 2dafcf15-953d-4506-932d-546e20c83bc4

📥 Commits

Reviewing files that changed from the base of the PR and between 4d1a782 and ce50a0f.

📒 Files selected for processing (1)
  • docs/decisions/0004-remove-sanity-cms-and-replace-with-course-builder-and-egghead-rails.md


**Phase 8 — Delete utility files and packages**

Run only after `rg -r "sanity" src/ --type ts --type tsx` returns no results.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Verify ripgrep flag semantics:"
rg --help | rg -n -- '-r, --replace'

echo "Quick behavioral check:"
tmp_file="$(mktemp)"
printf 'sanity\ngroq\n' > "$tmp_file"

echo "Correct search form should match:"
rg -n 'sanity|groq' "$tmp_file"

echo "Replace mode (-r) is different behavior and not intended for existence checks."
rm -f "$tmp_file"

Repository: skillrecordings/egghead-next

Length of output: 309


🏁 Script executed:

cat -n docs/decisions/0004-remove-sanity-cms-and-replace-with-course-builder-and-egghead-rails.md | sed -n '230,280p'

Repository: skillrecordings/egghead-next

Length of output: 2108


🏁 Script executed:

grep -n "rg -r" docs/decisions/0004-remove-sanity-cms-and-replace-with-course-builder-and-egghead-rails.md

Repository: skillrecordings/egghead-next

Length of output: 349


Fix ripgrep command syntax in verification steps and add language tags to code blocks.

The file contains three instances of rg -r (replace mode) where plain search is needed for verification. Additionally, two fenced code blocks are missing language identifiers.

Suggested fixes

Line 233:

-Run only after `rg -r "sanity" src/ --type ts --type tsx` returns no results.
+Run only after `rg "sanity" src/ --type ts --type tsx` returns no results.

Lines 237–243 and 258–272:

-- **Files to delete**:
+- **Files to delete**:

-  ```
+  ```txt
   src/utils/sanity-client.ts
   src/utils/sanity-server.ts
   src/utils/sanity.fetch.only.server.ts
   src/lib/sanity-allowlist.ts          (deleted in Phase 1)
   studio/                              (entire directory)
-  ```
+  ```

-- **Environment variables to remove** from all `.env.*` files and Vercel project settings:
-  ```
+- **Environment variables to remove** from all `.env.*` files and Vercel project settings:
+  ```txt
   NEXT_PUBLIC_SANITY_PROJECT_ID
   ...
-  ```
+  ```

Lines 276–277:

-- [ ] `rg -r "sanity" src/ --type-add 'tsx:*.tsx' -t ts -t tsx --iglob '!*.test.*'` returns zero results
-- [ ] `rg -r "groq" src/ --type-add 'tsx:*.tsx' -t ts -t tsx` returns zero results
+- [ ] `rg "sanity" src/ --type-add 'tsx:*.tsx' -t ts -t tsx --iglob '!*.test.*'` returns zero results
+- [ ] `rg "groq" src/ --type-add 'tsx:*.tsx' -t ts -t tsx` returns zero results
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@docs/decisions/0004-remove-sanity-cms-and-replace-with-course-builder-and-egghead-rails.md`
at line 233, Replace the mistaken recursive/replace ripgrep flags by changing
each occurrence of rg -r "sanity" src/ --type ts --type tsx to a plain search
(e.g., rg "sanity" src/ --type ts --type tsx or rg -n "sanity" src/ --type ts
--type tsx) so the verification step only searches and does not attempt
replacement, and add language identifiers (use txt) to the missing fenced code
blocks that list files and environment variables (the triple-backtick blocks
shown around the src/... list and the NEXT_PUBLIC_SANITY_PROJECT_ID list) so
they become ```txt.

Comment on lines +237 to +243
```
src/utils/sanity-client.ts
src/utils/sanity-server.ts
src/utils/sanity.fetch.only.server.ts
src/lib/sanity-allowlist.ts (deleted in Phase 1)
studio/ (entire directory)
```
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add language identifiers to fenced code blocks.

These two fenced blocks are unlabeled and trigger markdownlint MD040.

Suggested doc fix
-  ```
+  ```text
   src/utils/sanity-client.ts
   src/utils/sanity-server.ts
   src/utils/sanity.fetch.only.server.ts
   src/lib/sanity-allowlist.ts          (deleted in Phase 1)
   studio/                              (entire directory)

...

  • NEXT_PUBLIC_SANITY_PROJECT_ID
    NEXT_PUBLIC_SANITY_DATASET
    NEXT_PUBLIC_SANITY_API_VERSION
    NEXT_PUBLIC_SANITY_PUBLIC_KEY
    SANITY_EDITOR_TOKEN
    SANITY_WEBHOOK_SIGNATURE_SECRET
    SANITY_WEBHOOK_CREATED_SECRET
    SANITY_WEBHOOK_SECRET
    SANITY_API_TOKEN
    SANITY_STUDIO_PROJECT_ID
    SANITY_STUDIO_API_VERSION
    SANITY_STUDIO_DATASET
    SANITY_ALLOWLIST_MAX_AGE_SECONDS
    
</details>




Also applies to: 258-272

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 markdownlint-cli2 (0.21.0)</summary>

[warning] 237-237: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

</details>

</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In
@docs/decisions/0004-remove-sanity-cms-and-replace-with-course-builder-and-egghead-rails.md
around lines 237 - 243, The markdown contains unlabeled fenced code blocks in
docs/decisions/0004-remove-sanity-cms-and-replace-with-course-builder-and-egghead-rails.md
(around the block listing src/utils/... at lines ~237-243 and the env var block
around ~258-272) which triggers markdownlint MD040; fix by adding a language
identifier (use "text") to the opening backticks of those fenced blocks so they
become ```text, ensuring both blocks (the file list and the environment variable
list) are updated; no other changes required.


</details>

<!-- fingerprinting:phantom:triton:hawk -->

<!-- This is an auto-generated comment by CodeRabbit -->

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant