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.

BucketRuleWhere
Checked inIf it's text or code, it's in git.packages/ · courses/* (except media) · DESIGN.md
In-repo, ignoredDisposable working artefacts — visible, deletable, never committed.scratch/
ExternalAnything 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

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.