Spec — Repo restructure
2026-refresh › repo-restructure · chore · created 2026-08-05 · spec · plan.html
One repo — the course-production studio — restructured so Asim can always answer "what is this file and is
it checked in?" at a glance: reusable platform code in packages/, each course self-contained under
courses/<slug>/ including its media as symlinks, Claude's working artefacts confined to an
ignored scratch/, and heavy files living externally, reachable only through the symlinks.
Problem
P1The repo reads as random files and random folders — Asim's words; a month of spikes and outputs accreted with no structure.
Spike leftovers, rendered mp4s, contact-sheet PNGs, pipeline scripts and curriculum docs are
interleaved. Working out what anything is requires archaeology.
P2There is no checked-in policy — what belongs in git vs Dropbox vs nowhere is folklore, not structure.
The gitignore accreted entry by entry (
*.mp4, spikes/, masters/…).
Nothing states the rule, so every new artefact re-poses the question.P3Platform and course content are tangled — blocking the reuse this repo now exists for.
The Remotion templates and ffmpeg pipeline are future-course assets; the dossiers and scripts are
adv-js content. They currently share folders, so nothing is liftable.
Solution at a glance
J0Three buckets, one rule each — and everything about a course under its own roof.
| Bucket | Rule | Where |
|---|---|---|
| Checked in | If it's text or code, it's in git. | packages/ · courses/* (except media) · DESIGN.md |
| In-repo, ignored | Disposable working artefacts — visible, deletable, never committed. | scratch/ |
| External | Anything heavy. In the repo only as a symlink. | courses/*/media/ → Dropbox/Drive |
course-studio/ ✓ = tracked ✗ = ignored/symlink ├── DESIGN.md ✓ (lands with design-system) ├── README.md ✓ the map — buckets, rules, layout ├── packages/ ✓ reusable platform │ ├── remotion/ card template · slide kit · overlay kit │ └── scripts/ normalise · concat · trim · conform · beats · audits ├── courses/ │ └── adv-js/ the whole course under one roof │ ├── curriculum/ ✓ dossiers · triage · production sheet · verification │ ├── scripts/ ✓ recording scripts (briefings) │ ├── workshop/ ✓ the lecture .md files students get │ ├── transcripts/ ✓ Scribe JSON · caption VTTs │ └── media/ ✗ symlinks only │ ├── source/ masters 2016 · 2019 · async · takes inbox │ └── out/ rendered cards · assembled lectures ├── scratch/ ✗ Claude's working artefacts — screenshots, probes, test clips └── .work/ ✗ journal (central home, already ignored)
Job stories
J1 · When I look at the repo
J1.1ls reads as a table of contents — every top-level name answers "what is this" without opening it P1Random files and foldersarchaeology required
Top level is exactly: DESIGN.md, README, packages, courses, scratch, media-free. Nothing else.
J1.2Everything about one course is under its folder — media included — courses/adv-js/ holds curriculum, scripts, workshop, transcripts, media links P1Random files and folderscourse content scattered
Asim's explicit call: media symlinks live under each course, not at repo root — so "what's what" for a
course is one folder listing. A future course is a new
courses/<slug>/ with the same five entries.J1.3git status is always readable — only text/code is ever tracked; heavy files are structurally unreachable P2No checked-in policygitignore folklore
The ignore rules protect the buckets (
scratch/, courses/*/media/), and README
states the three rules so no future artefact re-poses the question.J2 · When Claude works
J2.1Working artefacts are confined and visible — screenshots, probe frames, test clips all land in scratch/, never anywhere else P1Random files and folderswork junk mixed with deliverables P2No checked-in policyjunk risked being committed
Asim can inspect what Claude's doing (it's in-repo, not hidden in /tmp) and delete scratch/ at any time
with zero loss — nothing durable may live there.
J3 · When a future course starts
J3.1The platform lifts without surgery — packages/ has no course-specific paths baked in P3Platform and content tanglednothing liftable today
Pipeline scripts take paths as arguments; Remotion components take props. Course specifics live in the
course folder.
Constraints
- Nothing is deleted — moves and archives only; the Dropbox masters and their folder layout are untouched (symlink targets only).
- The pipeline keeps working after the move — script paths updated in the same change.
- The
.workjournal and its story history are untouched. - Spike material (runner, vscode-drive, old spikes) archives into
scratch/archive/— recoverable, out of the way; findings docs already live in the journal. - Renaming the repo folder itself is Asim's action (it breaks open sessions/paths) — coordinated, not automated.
Deferred to plan
Exact external media home per subfolder
Why it must wait: needs a look at Dropbox free space and folder layout. Lean: Dropbox for
everything (masters already there — zero migration); Google Drive only if space demands it.
Decisions
One repo — platform and courses together; no separate platform repo
Asim's call, reversing the earlier two-repo proposal: "we're gonna stick to this repo… just rename it."
Name: course-studio (or whatever — the rename is cosmetic and his).
Media symlinks live under each course, not at repo root
Asim's call — "otherwise it's hard for me to figure out what's what". Course folder = the whole course.
Claude's working content stays in-repo but ignored
Asim's call — visible enough to inspect, ignored so it never pollutes history, one folder so it never scatters.
Estimated files / edits
Size: S–M — moves, symlinks, ignore rules, path updates in pipeline scripts, a README.