Skip to content

P0: Build a fully navigable Django review skeleton #97

Description

@alexeygrigorev

Problem

The Django homepage is reachable at /, but its first-party navigation and discovery cards still send visitors to https://datatalks.club/.... A reviewer therefore leaves the new deployment as soon as they try to explore it. /courses/ is also empty in the deployed review environment, so the adopted Course Management Platform cannot be reviewed as part of the website.

This P0 creates a bounded, read-only, fully clickable review skeleton. It is not the full content migration or the Event/Course domain implementation.

Product and architecture authority

User-visible outcome

A visitor can start at / and remain on the current Django host while navigating a representative slice of Home, Events, Courses/Cohorts, Articles, Podcast, People, Books, Docs, FAQ, Podwiki, and Slack. The homepage remains recognizably DataTalks.Club, with Events and Courses prominent, but all of these surfaces use the already-adopted Course Management Platform visual system.

Content must look like real site content, not placeholder copy. Do not add visible “demo” badges or labels. The one non-submitting registration destination must state plainly that registration is not enabled in this review build.

Representative source slice

Use checked-in, deterministic projections of the following real source records; do not fetch GitHub or the legacy site during a request or test. Preserve source repository, revision, and source path in the projection metadata so later migration work can replace it safely.

Source Pinned revision from the compatibility inventory Required representative records
DataTalksClub/datatalksclub.github.io ee43d3fa0929faf691178d79f19528e6f15a83e5 AI Dev Tools Zoomcamp article; 2026 events; Aleksandr Kim; “How to Build AI That Actually Ships in Production” event and podcast episode; “How Software Fails” book; Slack page copy
DataTalksClub/course-management-platform plus the main-site course page 98a235283904b4ef9ad29e196298540756cf1bcc plus the main-site revision above Manually reviewed presentation mapping ai-dev-tools-zoomcampai-dev-tools-2026; this is not a persistent migration rule
DataTalksClub/docs 3f23e006ffdaa498bbc69697408853b6f5eb37dc Docs hub and AI Dev Tools Zoomcamp getting-started page
DataTalksClub/faq c8da1deea9e24945922702994de101dd90a5380a AI Dev Tools Zoomcamp FAQ and real question fragment 4487db3924
DataTalksClub/podwiki 988b79d0d655bf4755945c3118544cb9e0dbead6 Podwiki hub, AI coding tools page, and search/no-results state

Aleksandr Kim (aleksandrkim) is the required cross-collection identity: /people/aleksandrkim.html is linked from the June 15, 2026 event and from the podcast episode. Render one local Person projection; do not duplicate or subtly vary the biography between surfaces.

Event time/status must be truthful for the review clock. The pinned main-site source includes upcoming records as of grooming (for example, the August 10, 2026 workshop) and the recorded Aleksandr Kim event. If the selected snapshot has no future records at render time, show an honest “No upcoming events” state and recent events; never relabel a past event as upcoming. Freeze time in tests.

Required routes and states

All routes below return a rendered Django response on a clean review install. Exact legacy .html paths, trailing slashes, query strings, and fragments are intentional.

Route Required state
/ Homepage with prominent Events and Courses sections plus links to every hub below
/events.html Upcoming/recent event hub; event cards link to stable sections on this page, the local speaker profile, and only then to a true external provider/recording
/articles.html Article hub
/blog/ai-dev-tools-zoomcamp.html Representative real article detail
/podcast.html Podcast hub
/podcast/s24e06-how-to-build-ai-that-actually-ships-in-production.html Representative real episode detail linking guest aleksandrkim locally
/people/aleksandrkim.html Real local Person profile linking back to the event and episode
/books.html Books hub
/books/20250922-how-software-fails.html Representative real book detail
/docs/ Docs hub
/docs/courses/ai-dev-tools-zoomcamp/getting-started/ Representative real docs detail
/faq/ FAQ hub
/faq/ai-dev-tools-zoomcamp.html#4487db3924 Representative real FAQ detail and preserved ten-character anchor
/podwiki/ Podwiki hub
/podwiki/wiki/ai-coding-tools/ Representative real Podwiki detail
/podwiki/search/?q=no-such-review-topic Useful empty search result; query is preserved in the UI
/slack.html Local first-party Slack information page; the actual Slack join/workspace destination may be external
/courses/ Non-empty Course discovery showing the real AI Dev Tools Zoomcamp family and 2026 cohort card
/courses/ai-dev-tools-zoomcamp/ Read-only Course family detail
/courses/ai-dev-tools-zoomcamp/cohorts/ai-dev-tools-2026/ Read-only Cohort detail
/courses/ai-dev-tools-zoomcamp/cohorts/ai-dev-tools-2026/registration-preview/ GET-only, clearly non-submitting registration preview with a working back link

The copied platform route /courses/ai-dev-tools-2026/ and its existing behavior remain intact when backed by a real Course row. The skeleton may wrap or link to copied presentation components, but must not replace, rename, or fork the copied business implementation.

Functional requirements

Shared shell and navigation

  • Replace the standalone homepage visual shell with the Course Management Platform base, tokens, typography, spacing, buttons, cards, responsive behavior, dark mode, and accessibility patterns. core/base.html may become a thin compatibility wrapper, but must not retain an independent palette or component system.
  • Provide a shared desktop and mobile navigation for the required first-party hubs. Mobile navigation is keyboard-operable, exposes its expanded state, keeps visible focus, and does not create horizontal overflow at 390 px.
  • Every user-interactive first-party href, form action, card, breadcrumb, and CTA uses a relative/same-host URL and resolves without a 404. This rule does not apply to canonical metadata: on web.dtcdev.click, <link rel="canonical"> intentionally points to the corresponding https://datatalks.club/... production URL with the exact preserved path, as required by the SEO specification.
  • Genuine destinations outside the website—GitHub repositories, YouTube/Spotify/Apple recordings, LinkedIn profiles, Luma/calendar providers, and the actual Slack workspace—may remain external and must be visually/semantically recognizable as external.

Read-only content presentation

  • Build the smallest view/presentation layer needed for the listed records and states. Reuse the existing content primitives where they fit; do not add a second generalized importer framework.
  • Preserve source wording and relationships. Do not invent dates, availability, biographies, instructors, guests, course claims, registration status, or external URLs.
  • The representative slice creates no editorial rows, Course/Cohort rows, Event/Person registrations, jobs, or email. It has no Studio/admin/API mutation surface.
  • Missing optional media renders a stable text/card fallback. A missing required pinned record fails loudly in a deterministic check; it must not silently produce a fabricated card.

Course review path

  • /courses/ is reviewable even when the database contains no imported course rows, using the read-only pinned presentation slice above.
  • The family and cohort pages use target Course → Cohort terminology without implementing the migrations owned by Migrate edition-like Course records to reusable Course → Cohort #51/Add Course/Cohort lifecycle, public routes, and complete cohort duplication #53. The single reviewed mapping is explicit data, never slug inference.
  • The registration preview contains no form that can submit, no POST handler, no enrollment/registration service call, and no email/job side effect. POST returns 405 (or an equivalently explicit non-mutating response).
  • Existing copied Course Management Platform tests, account behavior, staff behavior, and dark-mode behavior continue to pass.

URL and SEO safety

  • Preserve the exact paths in the route table. No catch-all, iframe, client-side redirect, proxy, or redirect to the old host is acceptable.
  • Keep the existing environment SEO policy: development responses remain noindex, are disallowed by development robots.txt, and are omitted from the production sitemap (or served from an empty development sitemap). A production-equivalent page on web.dtcdev.click emits the corresponding https://datatalks.club/... canonical with the exact preserved path; this metadata must not change the same-host behavior of user navigation.
  • Rendered interactive internal links use their exact preserved local route form. Fragment links land on an element with the exact ID.

Non-goals

The open collection/domain issues are coordination owners, not blockers for this narrow presentation slice. This issue must not close them or claim their acceptance criteria.

Implementation workstream ownership

Implementation may be delegated later by source collection, with one integration owner. Keep ownership non-overlapping:

  1. Shell/integration: shared Course Management Platform base, site navigation, homepage composition, route-level link audit.
  2. Main-site collection: Articles, Podcast, People, Books, and Slack projections from datatalksclub.github.io.
  3. Events collection: event hub sections/status logic and Person links only; no Event model or registration.
  4. Courses collection: read-only Course/Cohort discovery/detail/registration-preview while preserving copied platform code.
  5. Docs collection: only the two listed Docs routes/records.
  6. FAQ collection: only the listed hub/page/fragment.
  7. Podwiki collection: only the listed hub/detail/search-empty routes.
  8. Independent tester: run Django and Playwright acceptance after integration and attach desktop/mobile screenshots; no implementation commits.

The integration owner resolves shared-template and URL-conf changes. Collection owners must not edit another collection’s projection or broaden their slice.

Acceptance criteria

  • Every route in the table returns 200 on a clean review install, except POST to the registration-preview route, which is explicitly non-mutating/405; the existing unknown-path 404 remains.
  • Starting at /, a reviewer can reach every hub and every representative detail without leaving the current host or manually editing the URL.
  • The homepage is recognizably based on the original information hierarchy and makes Events and Courses prominent above or directly after the opening introduction.
  • All listed public pages use the Course Management Platform visual system; there is no parallel homepage palette/component system.
  • /courses/ is non-empty with the real AI Dev Tools Zoomcamp → 2026 cohort relationship and working Course, Cohort, and registration-preview paths even when imported DB content is absent.
  • The registration preview cannot write database state, enqueue a job, or send email.
  • Aleksandr Kim is one local Person identity reached from both the real event and real podcast episode, with truthful source content.
  • Event upcoming/recent status is timezone-aware and truthful; the no-upcoming state is useful and tested.
  • The FAQ anchor, Podwiki query, and all exact .html/trailing-slash paths are preserved.
  • Every rendered first-party href, card, breadcrumb, and CTA is same-host and non-404; only genuine third-party destinations are external.
  • Development noindex/sitemap behavior and existing copied platform/account tests do not regress.
  • No request-time network call, content/domain migration, mutation endpoint, catch-all, iframe, or legacy-host redirect is introduced.

Required Django tests

Add deterministic tests that:

  1. Parameterize the route table and assert status, exact local request path, corresponding https://datatalks.club canonical metadata, expected heading/content marker, and development robots behavior.
  2. Parse rendered links from / and each hub; classify first-party versus allowed external destinations; follow every first-party link and assert non-404.
  3. Assert the source revision/path metadata and the exact shared aleksandrkim relationship across event, Person, and episode contexts.
  4. Freeze time on both sides of a representative event and assert upcoming/recent ordering plus the no-upcoming empty state.
  5. Start with no imported Course rows and assert the Course → Cohort traversal is still rendered; separately prove existing copied platform views still use their database-backed behavior.
  6. GET the registration preview, attempt POST, and assert no relevant row, email outbox entry, or queued job changes.
  7. Assert #4487db3924 exists, the Podwiki query is retained/escaped, missing optional images fall back, and an unknown path still returns 404.
  8. Fail if a user-interactive first-party href or form action points at datatalks.club/courses.datatalks.club, while explicitly excluding canonical metadata from that rule and allowing the named true external destination classes.

Use uv or the repository’s uv-backed Make targets.

Required browser acceptance

Run Playwright against a deterministic local dataset at desktop (about 1440×900) and mobile (about 390×844):

  1. From /, use the visible navigation to visit Events, Courses, Articles, Podcast, Podwiki, Books, Docs, FAQ, and Slack; assert same origin, expected heading, and no horizontal overflow.
  2. Follow the recorded event’s speaker to /people/aleksandrkim.html, then its podcast link to the episode; navigate back without a dead end.
  3. Traverse /courses/ → Course → Cohort → registration preview; verify the preview is visibly unavailable/non-submitting and the back link works.
  4. Follow the article, book, docs, FAQ fragment, and Podwiki detail links; verify the FAQ anchor is in view and a no-result Podwiki search is useful.
  5. On mobile, open/close the menu with keyboard controls, verify focus visibility and expanded state, and ensure all targets remain reachable.
  6. Confirm light/dark presentation uses the same adopted shell and that broken asset fallbacks do not collapse layouts.

The tester stores screenshots only under .tmp/, attaches representative desktop/mobile evidence to the issue, and posts an independent test report before product acceptance.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P0Must-have or release-blockingaccessibilityArea: accessibilitybugSomething isn't workingcontentArea: contentcoursesArea: courseseventsArea: eventsfrontendArea: frontendhumanCode complete; manual verification requiredseoArea: seotestingArea: testing

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions