Identical learning chrome across the five core language playgrounds — C, C++, JavaScript, Python, C# — so students transition concept-to-concept and language-to-language without relearning the UI, plus three new lesson content layers (books, SpikerSoft text, videos) that every playground inherits at once through the shared shell.
Current state (verified in code)
The rich "subheader" shell is already shared. C#, C, C++, and Python all render LanguagePlaygroundShellComponent (libraries/platform/clang-runtime/src/lib/language-playground-shell.component.html): File/View/Mode/Options/Lessons/Help menus, lesson/sandbox toggle, beginner/advanced sandbox toggle, status chips (connection, local/server/offline, standard, runtime, running, submission, execution time), guided tour, curriculum pane with lesson sidebar, resizable/swappable panes, and right-pane tabs (Concepts / Submissions / Results).
JavaScript is the outlier: libraries/features/dev-tools-javascript-runner/src/lib/javascript-runner.ts wraps the older app-language-runner directly, with its own debugger toolbar and a separate submission-history pane — no shell, no concept pane, no lessons menu chrome.
Books / text / videos do not exist in the lesson model.TutorialPanel (libraries/shared/lesson-platform/src/lib/lesson-types.ts) carries only heading/body/code; backend SpikerSoft.Data/Mongos/Lesson.cs has no reading/media fields. These are new content layers, not parity gaps — landing them in the shared shell gives them to all five languages simultaneously.
Phases
Phase
Scope
P1
Migrate JavaScript playground onto the shared shell
P2
Shell parity audit: C / C++ / Python vs C# small-gap sweep
P3
Books layer — curated external book links per subject/section
P4
Text layer — SpikerSoft's own authored prose per section
P5
Videos layer — official per-lesson + student-submitted/staff-approved per lesson block
Spike
Completion-ratio anonymous unlocks (contribute → see more; account → everything)
Sub-issues are linked in a comment below as they are filed.
## Goal
Identical learning chrome across the five core language playgrounds — C, C++, JavaScript, Python, C# — so students transition concept-to-concept and language-to-language without relearning the UI, plus three new lesson content layers (books, SpikerSoft text, videos) that every playground inherits at once through the shared shell.
## Current state (verified in code)
- **The rich "subheader" shell is already shared.** C#, C, C++, and Python all render `LanguagePlaygroundShellComponent` (`libraries/platform/clang-runtime/src/lib/language-playground-shell.component.html`): File/View/Mode/Options/Lessons/Help menus, lesson/sandbox toggle, beginner/advanced sandbox toggle, status chips (connection, local/server/offline, standard, runtime, running, submission, execution time), guided tour, curriculum pane with lesson sidebar, resizable/swappable panes, and right-pane tabs (Concepts / Submissions / Results).
- **JavaScript is the outlier**: `libraries/features/dev-tools-javascript-runner/src/lib/javascript-runner.ts` wraps the older `app-language-runner` directly, with its own debugger toolbar and a separate submission-history pane — no shell, no concept pane, no lessons menu chrome.
- **Books / text / videos do not exist in the lesson model.** `TutorialPanel` (`libraries/shared/lesson-platform/src/lib/lesson-types.ts`) carries only heading/body/code; backend `SpikerSoft.Data/Mongos/Lesson.cs` has no reading/media fields. These are new content layers, not parity gaps — landing them in the shared shell gives them to all five languages simultaneously.
## Phases
| Phase | Scope |
|---|---|
| P1 | Migrate JavaScript playground onto the shared shell |
| P2 | Shell parity audit: C / C++ / Python vs C# small-gap sweep |
| P3 | Books layer — curated external book links per subject/section |
| P4 | Text layer — SpikerSoft's own authored prose per section |
| P5 | Videos layer — official per-lesson + student-submitted/staff-approved per lesson block |
| Spike | Completion-ratio anonymous unlocks (contribute → see more; account → everything) |
| Spike | Duolingo-style optional progression visualization (menu-launched, sounds, younger audience) |
Sub-issues are linked in a comment below as they are filed.
P1 (#324) first — everything after it lands in the shared shell, so JS must be on the shell before the content layers ship or JS students miss them.
P2 (#325) in parallel or immediately after — small-gap sweep, low risk.
P3 (#326) → P4 (#327) share the shell's new Reading surface; design it once in P3.
P5 (#328) after the moderation/media-pipeline decisions; expect sub-tickets.
Spikes #329/#330 are independent of each other and can run anytime; #330's design should account for #329's lock states, and #329's recommendation on whether books/text/videos join the ratio feeds back into P3–P5.
Account creation = everything unlocked; the ratio is an on-ramp for the anonymous, never a paywall for members.
The progression visualization is opt-in from the menu — the default lesson flow is untouched.
## Sub-issues + status
| Phase | Issue | Status |
|---|---|---|
| P1 JavaScript → shared shell | #324 | Not started |
| P2 C/C++/Python parity audit vs C# | #325 | Not started |
| P3 Books layer | #326 | Not started |
| P4 Text layer (SpikerSoft's own book) | #327 | Not started |
| P5 Videos layer (official + community/approved) | #328 | Not started (largest — may split) |
| Spike: completion-ratio anonymous unlocks | #329 | Not started |
| Spike: Duolingo-style progression visualization | #330 | Not started |
## Suggested order
1. **P1 (#324)** first — everything after it lands in the shared shell, so JS must be on the shell before the content layers ship or JS students miss them.
2. **P2 (#325)** in parallel or immediately after — small-gap sweep, low risk.
3. **P3 (#326) → P4 (#327)** share the shell's new Reading surface; design it once in P3.
4. **P5 (#328)** after the moderation/media-pipeline decisions; expect sub-tickets.
5. Spikes **#329**/**#330** are independent of each other and can run anytime; #330's design should account for #329's lock states, and #329's recommendation on whether books/text/videos join the ratio feeds back into P3–P5.
## Decisions locked in at filing
- Anonymous unlock currency = **lesson/exercise completions** (not submissions or engagement signals).
- Account creation = **everything unlocked**; the ratio is an on-ramp for the anonymous, never a paywall for members.
- The progression visualization is **opt-in from the menu** — the default lesson flow is untouched.
The shared Reading surface (right-pane tab) shipped with P3 and is reused by P4, so P5 Videos plugs into the same shell surface. P5 (#328) is now the only open phase of this epic.
## Status refresh (the earlier table was stale)
Actual merged state on `master`:
| Phase | Issue | Status |
|---|---|---|
| P1 JavaScript → shared shell | #324 | ✅ Merged (angular PR #94) |
| P2 C/C++/Python parity + tour vs C# | #325 | ✅ Merged (angular PR #95) |
| P3 Books layer | #326 | ✅ Merged (backend PR #53, angular PR #96) — closed |
| P4 Text layer (our own book) | #327 | ✅ Merged (backend PR #54, angular PR #97) — closed |
| P5 Videos layer | #328 | ⬜ **Not started — only remaining phase** |
| Spike: ratio unlocks | #329 | ✅ Delivered → #331 (backend PR #56) + #332 (angular PRs #99/#100) — closed |
| Spike: My Journey viz | #330 | ✅ Delivered → #333 (angular PR #98) + #334 (backend PR #55) — closed |
The shared **Reading** surface (right-pane tab) shipped with P3 and is reused by P4, so P5 Videos plugs into the same shell surface. **P5 (#328) is now the only open phase of this epic.**
End-to-end today: staff/admins can moderate community videos; all five playgrounds show approved official + community videos grouped by block; logged-in users can submit a video (URL + metadata) that lands Pending for review; anonymous users never see unapproved content.
Remaining:#337 P5b media pipeline (upload → ClamAV scan → ffmpeg transcode to MP4 + poster → move-to-final → static serving), which upgrades the submit flow from URL-based to file-upload. Architecture + storage/format decisions are recorded on #337 (local SERVER fusionio bind-mount, ffmpeg→MP4, mirror BlogMediaProcessor); implementation is the last step to fully close the epic.
### Status update — P5 Videos (#328)
Three of the four P5 sub-tickets are merged and closed:
- **#336** P5a backend foundation — merged (spikersoft-backend #57)
- **#338** P5c admin moderation queue — merged (spikersoft-angular #101)
- **#339** P5d playground Videos tab + submit — merged (spikersoft-angular #102)
End-to-end today: staff/admins can moderate community videos; all five playgrounds show approved official + community videos grouped by block; logged-in users can submit a video (URL + metadata) that lands Pending for review; anonymous users never see unapproved content.
**Remaining:** **#337** P5b media pipeline (upload → ClamAV scan → ffmpeg transcode to MP4 + poster → move-to-final → static serving), which upgrades the submit flow from URL-based to file-upload. Architecture + storage/format decisions are recorded on #337 (local `SERVER` fusionio bind-mount, ffmpeg→MP4, mirror `BlogMediaProcessor`); implementation is the last step to fully close the epic.
The uniformity goal and all three new content layers (books, text, videos) now ship to all five playgrounds through the shared shell. The only remaining item is the optional Duolingo-style progression-visualization spike — leaving this epic open to track that; it can be closed if that spike is out of scope.
Optional follow-up carried from P5: swap the playground video-submit flow from URL entry to the in-browser file upload (POST /api/Lessons/{n}/videos/upload) now that the media pipeline exists.
**P5 (Videos layer, #328) complete and closed** — with it, all five core phases are done:
| Phase | Status |
|---|---|
| P1 — JavaScript onto shared shell | ✅ done |
| P2 — shell parity audit (C/C++/Python vs C#) | ✅ done |
| P3 — Books layer (#326) | ✅ done |
| P4 — Text layer (#327) | ✅ done |
| P5 — Videos layer (#328: #336/#337/#338/#339) | ✅ done |
| Spike — completion-ratio anonymous unlocks (#332) | ✅ done |
| Spike — Duolingo-style optional progression viz | ⚪ not started (optional/exploratory) |
The uniformity goal and all three new content layers (books, text, videos) now ship to all five playgrounds through the shared shell. The only remaining item is the optional Duolingo-style progression-visualization spike — leaving this epic open to track that; it can be closed if that spike is out of scope.
**Optional follow-up carried from P5:** swap the playground video-submit flow from URL entry to the in-browser file upload (`POST /api/Lessons/{n}/videos/upload`) now that the media pipeline exists.
Correcting the previous comment: the Duolingo-style progression-visualization spike (#330) was not "not started" — it was delivered and closed earlier the same day. The "not started" line was a stale regression that contradicted the 15:07 refresh and the actual master code.
The Duolingo spike shipped as feature-my-journey: menu-launched Learn ▸ My Journey (/my-journey), a per-language winding trail with completed/current/available/locked-prereq/locked-horizon node states (buildTrail), opt-in synthesized JourneyAudioService (no assets/CDN), and the repo's first reduced-motion pref (JourneyPrefsService), backed by the anonymous-friendly GET /api/Lessons/journey aggregation.
Optional P5 follow-up also landed: the playground video-submit flow now supports in-browser file upload (POST /api/Lessons/{n}/videos/upload) alongside URL entry — angular #103.
The uniformity goal and all three content layers (books, text, videos) ship to all five playgrounds through the shared shell, and both spikes are delivered. Nothing outstanding — closing the epic.
## Epic complete — closing
Correcting the previous comment: the **Duolingo-style progression-visualization spike (#330) was not "not started"** — it was delivered and closed earlier the same day. The "not started" line was a stale regression that contradicted the 15:07 refresh and the actual `master` code.
Final, verified state on `master`:
| Phase | Issue(s) | Status |
|---|---|---|
| P1 — JavaScript onto shared shell | #324 | ✅ done (angular #94) |
| P2 — shell parity audit (C/C++/Python vs C#) | #325 | ✅ done (angular #95) |
| P3 — Books layer | #326 | ✅ done (backend #53, angular #96) |
| P4 — Text layer | #327 | ✅ done (backend #54, angular #97) |
| P5 — Videos layer | #328 (#336/#337/#338/#339) | ✅ done (backend #57/#58, angular #101/#102, infra #4) |
| Spike — completion-ratio anonymous unlocks | #329 → #331/#332 | ✅ done |
| Spike — Duolingo-style progression viz | #330 → #333/#334 | ✅ done (angular #98, backend #55) |
The Duolingo spike shipped as `feature-my-journey`: menu-launched `Learn ▸ My Journey` (`/my-journey`), a per-language winding trail with completed/current/available/locked-prereq/locked-horizon node states (`buildTrail`), opt-in synthesized `JourneyAudioService` (no assets/CDN), and the repo's first reduced-motion pref (`JourneyPrefsService`), backed by the anonymous-friendly `GET /api/Lessons/journey` aggregation.
**Optional P5 follow-up also landed:** the playground video-submit flow now supports in-browser file upload (`POST /api/Lessons/{n}/videos/upload`) alongside URL entry — angular #103.
The uniformity goal and all three content layers (books, text, videos) ship to all five playgrounds through the shared shell, and both spikes are delivered. Nothing outstanding — closing the epic.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Goal
Identical learning chrome across the five core language playgrounds — C, C++, JavaScript, Python, C# — so students transition concept-to-concept and language-to-language without relearning the UI, plus three new lesson content layers (books, SpikerSoft text, videos) that every playground inherits at once through the shared shell.
Current state (verified in code)
LanguagePlaygroundShellComponent(libraries/platform/clang-runtime/src/lib/language-playground-shell.component.html): File/View/Mode/Options/Lessons/Help menus, lesson/sandbox toggle, beginner/advanced sandbox toggle, status chips (connection, local/server/offline, standard, runtime, running, submission, execution time), guided tour, curriculum pane with lesson sidebar, resizable/swappable panes, and right-pane tabs (Concepts / Submissions / Results).libraries/features/dev-tools-javascript-runner/src/lib/javascript-runner.tswraps the olderapp-language-runnerdirectly, with its own debugger toolbar and a separate submission-history pane — no shell, no concept pane, no lessons menu chrome.TutorialPanel(libraries/shared/lesson-platform/src/lib/lesson-types.ts) carries only heading/body/code; backendSpikerSoft.Data/Mongos/Lesson.cshas no reading/media fields. These are new content layers, not parity gaps — landing them in the shared shell gives them to all five languages simultaneously.Phases
Sub-issues are linked in a comment below as they are filed.
Sub-issues + status
Suggested order
Decisions locked in at filing
Status refresh (the earlier table was stale)
Actual merged state on
master:The shared Reading surface (right-pane tab) shipped with P3 and is reused by P4, so P5 Videos plugs into the same shell surface. P5 (#328) is now the only open phase of this epic.
Status update — P5 Videos (#328)
Three of the four P5 sub-tickets are merged and closed:
End-to-end today: staff/admins can moderate community videos; all five playgrounds show approved official + community videos grouped by block; logged-in users can submit a video (URL + metadata) that lands Pending for review; anonymous users never see unapproved content.
Remaining: #337 P5b media pipeline (upload → ClamAV scan → ffmpeg transcode to MP4 + poster → move-to-final → static serving), which upgrades the submit flow from URL-based to file-upload. Architecture + storage/format decisions are recorded on #337 (local
SERVERfusionio bind-mount, ffmpeg→MP4, mirrorBlogMediaProcessor); implementation is the last step to fully close the epic.P5 (Videos layer, #328) complete and closed — with it, all five core phases are done:
The uniformity goal and all three new content layers (books, text, videos) now ship to all five playgrounds through the shared shell. The only remaining item is the optional Duolingo-style progression-visualization spike — leaving this epic open to track that; it can be closed if that spike is out of scope.
Optional follow-up carried from P5: swap the playground video-submit flow from URL entry to the in-browser file upload (
POST /api/Lessons/{n}/videos/upload) now that the media pipeline exists.Epic complete — closing
Correcting the previous comment: the Duolingo-style progression-visualization spike (#330) was not "not started" — it was delivered and closed earlier the same day. The "not started" line was a stale regression that contradicted the 15:07 refresh and the actual
mastercode.Final, verified state on
master:The Duolingo spike shipped as
feature-my-journey: menu-launchedLearn ▸ My Journey(/my-journey), a per-language winding trail with completed/current/available/locked-prereq/locked-horizon node states (buildTrail), opt-in synthesizedJourneyAudioService(no assets/CDN), and the repo's first reduced-motion pref (JourneyPrefsService), backed by the anonymous-friendlyGET /api/Lessons/journeyaggregation.Optional P5 follow-up also landed: the playground video-submit flow now supports in-browser file upload (
POST /api/Lessons/{n}/videos/upload) alongside URL entry — angular #103.The uniformity goal and all three content layers (books, text, videos) ship to all five playgrounds through the shared shell, and both spikes are delivered. Nothing outstanding — closing the epic.