Repo size audit (16.10.2026)
Owner 16.10.2026 (SRC-1422): bring nemo12-www down to about 5 MB and nemo12.com to about 10 MB, audit first. Measured on the state right after the repo split (16.10.2026): nemo12-www with its open PRs #1-#4, nemo12.com on session/repo-split (www and Pearl already removed, otherwise equal to main).
Verdict. nemo12-www can reach about 5.5 MB, and 5 MB once the CMS (phase 2 of the split) owns www content. nemo12.com reaches about 36 MB by taking media, SQL, migrations and content out of git (and landing the removals already in flight); about 17 MB once docs.nemo12.com has its own repo and the eleven extra apps are out or retired; about 12-14 MB with generated E2E fixtures and archived one-off scripts. What remains is code and tests, which should stay: exactly 10 MB would mean cutting code itself.
Two sizes, two different fixes
| Checkout (tracked files at HEAD) | Clone (git history, packed) | |
|---|---|---|
| nemo12-www | 34.7 MB, 1,433 files | 12.3 MB |
| nemo12.com | 161.9 MB, 5,623 files (190 MB, 6,482 files before the split) | 147.7 MB |
Removing files shrinks the checkout at once. The clone keeps every old version until history is rewritten (section "Git history"). node_modules (707 MB and about 810 MB) is not in git and is not counted.
nemo12-www: 34.7 MB to about 5 MB
Every tracked file sits in exactly one bucket:
| Bucket | MB | What | Fix |
|---|---|---|---|
| Generated seed SQL | 15.46 | scripts/seed-seo-pages.sql 6.05, four seed-articles-*.sql 8.17, seed-illustrations.sql 1.26 | Stop committing: the seed-data workflow builds them from source right before loading |
| Content | 8.85 | 400 article Markdown files 3.93, SEO pages 0.96, docs/curriculum 1.91, illustration registry + alts 1.42, books content 0.88 | CMS phase 2: content lives in D1 nemo12-cms, edited in cms.nemo12.com |
| Code | 3.73 | apps, worker, scripts, packages | Keep |
| Images | 2.70 | social covers 2.15 (cover-youtube.png 0.81 ...), article photos 0.55 | R2 (nemo12-content), served from the media route |
| Contract snapshots | 2.34 | openapi.snapshot.json 1.22, seed-videos.sql 0.74 | Keep only what tests read: the path list (about 30 KB) and the video rows (about 50 KB) |
| Other | 1.44 | package-lock.json 0.52, config, SVG | Keep |
| Tests | 0.21 | Keep |
| Step | Saves | Size after | Risk |
|---|---|---|---|
| 1. Generated seeds out of git | 15.5 | 19.3 | Low: one workflow change; the --check gates move into it |
| 2. Slim contract snapshots | 1.9 | 17.4 | Low |
| 3. Images to R2 | 2.7 | 14.7 | Low: URLs change, the SEO gate checks them |
| 4. CMS phase 2 (content to D1) | 8.9 | about 5.8 | Medium: the planned phase 2 itself |
5. Large copy files in src/site (subjectCopy.ts, students.ts ...) to CMS | about 0.8 | about 5.0 | Medium |
nemo12.com: 161.9 MB to about 10-12 MB
| Bucket | MB | What | Fix |
|---|---|---|---|
| Media | 52.1 | 455 MP3 in apps/learn/public/audio 38.6, JPG 13.1 (apps/learn/public/img 10.2, compass 2.9), PNG 0.4 (learn's are in R2 since 17.10.2026) | R2 nemo12-content, served like the videos already are |
| Seed and archive SQL | 21.5 | 66 scripts/*.sql 19.4 (seed-b21 3.0, seed-parent-bodies-* 7.1, seed-parent-gates-* 4.4, seed-grammar 1.3 ...), the AI Teen scripts folder 1.3 (removed by SRC-1419), scripts/archive 0.8 | Generated ones: build at seed time. Already-loaded one-offs: archive to R2 with their run date |
| Migrations | 20.2 | 358 files; the big ones load content (0294 1.75, 0280 1.72, 0265 1.10 ...) | Squash into one baseline schema: 374 tables = 252 KB. Content goes to seeds; tests get small fixtures |
| Content data | 15.6 | scripts/course-content 6.9, apps/learn/src/**/*.json 4.9, content/ 3.7, scripts/b21 1.2 ... | D1 (it is already the source of truth for IELTS content), edited in Dolphin (SDD-056) |
| In-flight removals | 14.5 | math (the learn math folder, course content), AI Teen, b21 (math and AI Teen removed by SRC-1419) | Already claimed by other sessions (toan12-split, english-only-cleanup, b21-redirect) |
| Apps not in the owner's list | 8.8 | marlins 6.9 (5.8 of it parent lessons and ebook chapters as .ts, the same text again in seed-parent-*.sql), compass, ui, coral, gull, mm, partners, tutors, reef, ielts, playbooks | Owner decision: own repo(s), or retire |
| Docs | 9.9 | docs.nemo12.com | Own repo (nemo12-docs), like www |
| Code | 11.1 | learn, api, admin, dolphin, docs app, packages, scripts | Keep; one-off scripts can be archived |
| Tests and E2E fixtures | 4.5 | api tests 1.9, learn E2E 2.3 (content.fixture.json 0.9) | Keep; generate the big fixtures |
| Other | 1.4 | lock, config | Keep |
| Content as code TS | 2.2 | explore/configs.tsx 0.24, shared/prompts.ts 0.15 ... | D1 |
| Step | Saves | Size after | Risk |
|---|---|---|---|
| 1. Media to R2 | 52.1 | 109.8 | Low-medium: a media route, URL rewrite, e2e of audio pages |
| 2. Seed and archive SQL out of git | 21.5 | 88.3 | Low |
| 3. Squash migrations (baseline + test fixture; the baseline runs once on production as a no-op) | 20.0 | 68.3 | Medium: migrate:check and api tests move to the baseline |
| 4. Land the in-flight removals (math, AI Teen, b21) | 14.5 | 53.8 | Owned by other sessions |
| 5. Content data and content-as-code to D1 | 17.8 | 36.0 | Medium-high: content editing moves to Dolphin |
| 6. Docs to their own repo | 9.9 | 26.1 | Medium, same recipe as the www split |
| 7. The eleven extra apps out or retired | 8.8 | about 17.3 | Owner decision per app |
| 8. Generate big E2E fixtures, archive one-off scripts | about 3-5 | about 12-14 | Low |
Exactly 10 MB would mean cutting code itself. The audit recommends stopping at about 12-14 MB.
Git history
| Today | After rewriting history to drop media and SQL blobs | |
|---|---|---|
| nemo12-www | 12.3 MB (SQL 2.6, PNG 2.4, MD 2.6) | about 5 MB |
| nemo12.com | 147.7 MB (MP3 34.5, JPG 22.5, SQL 15.5, PNG 14.9, MD 11.7, TS 11.2) | about 30-40 MB |
A rewrite force-pushes main and invalidates every open branch, ready/* branch and worktree (10 ready/* branches and 8 claimed tasks today). Plan:
- nemo12-www: rewrite now, before anyone else depends on it: its only branches are the split's own.
- nemo12.com: rewrite once, last, at a quiet moment: after steps 1-3, with every session stopped and every open branch merged or rebased.
Order and guardrails
- nemo12-www steps 1-3, plus its history rewrite.
- nemo12.com steps 1-3 (media, SQL, migrations): 94 MB out at low risk.
- CMS phase 2 (nemo12-www step 4) and nemo12.com step 5 (content to D1 via Dolphin).
- Owner decisions: docs repo, extra apps.
- nemo12.com history rewrite.
A gate stops regrowth in both repos: no new tracked media file (.mp3, .m4a, .jpg, .png, .webp), no new generated scripts/seed-*.sql, and no tracked file over 500 KB without an allow-list line with a reason.
Progress
| Date | Step | Result |
|---|---|---|
| 17.10.2026 | nemo12-www steps 1-3 | 34.7 to 16.5 MB (nemo12-www PRs #5, #6) |
| 17.10.2026 | Unused D1 data archived to R2 and dropped | migration 0359, PR #714 (see data-audit) |
| 17.10.2026 | nemo12.com step 2, seeds without test readers | 7.5 MB out, PR #715 |
| 17.10.2026 | nemo12.com step 1, NEMO WALK media to R2 | 48.8 MB out: 549 files verified by sha256 from production, served by GET /v1/public/media/walk/... (PR #716 and the learn PR) |
| 17.10.2026 | nemo12.com step 3, migrations to a baseline | 359 files (20.2 MB) became 0000_baseline.sql (483 KB) plus workers/api/test/reference-rows.sql (848 KB of test rows): 18.9 MB out, checkout 124.6 to 105.7 MB. On the bare baseline 102 of 3,250 api tests failed, all for missing reference rows; the fixture brings them back. Production schema read 17.10.2026: all 732 baseline objects already exist there, so the baseline's one run is a no-op |
| 17.10.2026 | Bank-wide IELTS content checks back, on production data | The squash left the api tests a six-skill slice. Nightly job ielts-bank-check (see below) now checks the whole bank |
Checks on content that lives only in production
After step 3, production D1 is the only copy of the IELTS micro-skill bank (51 skills, about 5,000 items), edited through seed-data or Dolphin. The api tests that used to check the whole bank now see the slice in workers/api/test/reference-rows.sql. The nightly workflow .github/workflows/ielts-bank-check.yml (22:30 UTC, also workflow_dispatch) covers the rest:
- It exports
ielts_task_types,ielts_micro_skills,ielts_micro_exercisesandielts_micro_skill_itemswithwrangler d1 export(read-only) into SQLite. scripts/check-ielts-bank.mjs --db <file>runs the rules the tests enforced up to SRC-1422: 51 skills per area, at least 5,008 items, every answer index within distinct options, every warm-up set showing 3 items, four stages per skill and their languages, at least 4 items per skill with exercises, at least 3 exercises per level for Listening, Speaking and Writing, plus reference and task-type checks.scripts/audit-content.mjs --db <file>scores completeness; it now fails when the D1 part cannot be read.
A red run means production content broke a rule: fix the rows through seed-data or Dolphin. Adding a skill or retiring items on purpose means editing the floor in check-ielts-bank.mjs.
How to measure again
git ls-files -z | xargs -0 stat -f '%z' | awk '{s+=$1} END {printf "%.1f MB\n", s/1048576}'
git count-objects -vH | grep size-pack