DataTalksClub / DataTalksClub/website

Shared-curriculum sub-modules: umbrella

Open
#396 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

courses enhancement P1
Dominant language
Python
Stars
0
Forks
0
PR merge metrics
No merged PRs in 30d

Description

Design doc: _docs/planning/shared-curriculum-submodules-design.md (committed 7a9816e5) — read it in full before implementing any phase; this issue is a summary and phase tracker, not the source of truth.

Motivation

LLM Zoomcamp's real content already has modules that informally split into parts (module 1: "Part 1: RAG" / "Part 2: Agents" in its README prose; module 3 has five parts; module 4 has two) — but there is currently zero machine-readable representation of this anywhere in the pipeline. module.yaml has a flat units: list, and the website builds a flat SharedModule -> SharedLesson graph with no second level.

Verified in the real content: the current single homework for module 1 spans both parts (Q1-5 are Part 1, Q6 is Part 2) — so the model must support a module keeping ONE homework across its parts, not force a split. Separately, Part 2 already advertises a standalone workshop entry point, so a future cohort anchoring a homework to just one part is realistic, not hypothetical. Both shapes (homework on the whole module, homework on one part) are first-class requirements, not one common case and one rare edge case.

Design summary

  • SharedSubModule — a new, flat (one level only, no self-referential tree) model, required FK to SharedModule. Rejected a self-referential parent FK on SharedModule itself: every existing SharedModule query (module page, family syllabus count, sitemap, inventory, the two-segment router) would need a parent__isnull=True guard it doesn't have today, and SharedModule's own constraints (slug/position uniqueness, the cohort-identifier collision check) are root-shaped.
  • SharedLesson.sub_module — new nullable FK, validated to belong to the lesson's module. A module with no sub-modules is simply all-None — zero change for the common case.
  • Homework anchoringCohortSharedModule (the per-cohort homework placement) gains a nullable sub_module FK: a homework anchors to either the whole module OR one specific sub-module, per cohort, never both, never neither. Because homework is cohort-owned and the shared module graph isn't, two different cohorts can anchor differently against the same shared content (2026 keeps one module-level homework; a future 2027 could split it) with no change to the shared rows.
  • Three DB constraints ship in the first phase (not deferred): one module-level homework per module per cohort, one homework per sub-module per cohort, and each homework anchored at most once — see the design doc section 4 for the exact conditional-unique SQL shape (a plain 3-column unique constraint does NOT work here; Postgres treats NULLs as distinct).
  • Course-repository side: module.yaml gains an optional sub_modules: list (nested, exclusive with units:); cohort.yaml homework bindings gain an optional sub_module: <slug>. No schema version bump — additive schema-2 extension, safe because both the parser and the zoomcamp-ops checker already reject unknown keys (that strictness IS the rollout safety net). Folders stay flat; no lesson/image/code file moves — the grouping lives only in module.yaml, matching how authors already number parts in ranges (module 4's 0611 gap). Full field-by-field YAML shape and checker rule list in the design doc's "Course-repository representation" section.
  • llm-zoomcamp's real 2026 content needs zero changes to ship this — all seven of its homework bindings stay module-level anchors. Splitting sub_modules: into module.yaml for modules 1/3/4 is Phase D, separate from and not required by Phases A-C.

Phases (in dependency order)

Phase Summary
A Additive DB models only: SharedSubModule, nullable SharedLesson.sub_module, nullable CohortSharedModule.sub_module, the three constraints, clean() validation, admin. Zero renderer changes. Ships safely with zero sub-modules in real data.
B Website importer/parser support for optional sub_modules: in module.yaml and optional sub_module: in cohort homework bindings, plus all-or-nothing and lesson-contiguity import-time validators. Absent keys mean today's behavior, unchanged.
C Rendering: module page and rail group lessons by sub-module when present (flat fallback otherwise), place each anchored homework after its anchor's last lesson, ModuleFlowItem gains an optional sub-module, anchor-aware homework breadcrumb, inventory report gains the anchor.
D Course-repository side, in this exact order (each step independently revertible): (1) zoomcamp-ops checker rules/fixtures for the new schema + tests green; (2) website Phase B/C deployed and dry-run tested against the checker's fixture; (3) the pinned checker-workflow commit llm-zoomcamp's CI calls gets updated to the new pin (a reviewed change); (4) llm-zoomcamp content: author sub_modules: for modules 1, 3, 4 in three separate commits, CI green, merge, import. cohorts/2026/cohort.yaml is not touched — Homework 1 keeps closing the whole module.

Open questions (design doc has full detail; flagging here for visibility)

  1. Should a module ever be allowed both a module-level AND a sub-module-level homework anchor in the same cohort? Schema permits it (each has a well-defined rendering); if it should be forbidden, that's an opt-in zoomcamp-ops checker rule (mixed_homework_anchors), not a DB constraint. Not enabled by default.
  2. Phase D timing — author real sub_modules: content for llm-zoomcamp as soon as B/C ship, or leave the capability built but unused for now?
  3. Sub-module pages: this design gives parts headings + fragment anchors on the existing module page, not their own routes/URLs. Confirm that's sufficient (a standalone "Part 2: Agents" workshop page could be added later without touching content, since the sub-module slug is already a stable identity).
  4. Sub-module slug/title convention: proposed ordinal-free slugs (rag, agents) with README-matching titles ("Part 1: RAG") — confirm, or prefer ordinal-free titles with the website deriving "Part N" from list position.

Each phase will be filed as its own groomed sub-issue per _docs/PROCESS.md, dependent on the previous phase.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Read _docs/planning/shared-curriculum-submodules-design.md at commit 7a9816e5 in full; this umbrella issue is only a phase tracker. Start with the independently groomed Phase A–D sub-issues in dependency order, and treat completion as shipping each phase with its listed models, validators, rendering, repository, and checker work while resolving the open design questions.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
backend, database, full-stack
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.