DataTalksClub / DataTalksClub/website
Ship real public content on the final editorial route map
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 0
- Forks
- 0
- PR merge metrics
- No merged PRs in 30d
Description
Outcome
web.dtcdev.click becomes a useful real-data, server-rendered, read-only product laboratory with:
- 55 articles;
- 205 podcasts and 203 available inline transcripts;
- 98 books;
- 421 public events, each with an internal detail page;
- 438 GitHub editorial People, excluding only _people/_template.md;
- 282 Wiki pages;
- 12 tracked public course catalogs; and
- a homepage populated from real records.
This revision supersedes the earlier #105 assumptions that hubs retain their old .html/trailing-slash spelling, Events have fragment-only details, People are incomplete, Wiki details use /wiki/wiki/, or development sitemaps are necessarily empty. It does not change established editorial content-detail URLs: those existing .html pages remain canonical.
The existing uncommitted issue-105 candidate is the engineering starting point, not accepted behavior. Its pinned data/provenance/sanitization work may be retained, but its routes, event model/presentation, missing People projection, layout, SEO coverage, and tests must be brought to this contract. The independent QA template-readability failure also remains release-blocking.
Product and architecture authority
Update and follow:
- _docs/specs/02-url-link-seo-compatibility.md for this exact route/redirect/canonical/sitemap decision;
- _docs/specs/03-github-content-and-people.md for all 438 public people and resolved relationships;
- _docs/specs/04-courses-and-cohorts.md for the bounded no-slash public catalog projection without claiming the later Course-to-Cohort migration;
- _docs/specs/05-events-registration-email.md for read-only event details and internal speaker relationships;
- _docs/specs/07-security-privacy-operations.md for public-only data, sanitization, and safe diagnostics;
- _docs/specs/09-migration-rollout-roadmap.md for the owner-approved route and Wiki transition;
- _docs/specs/10-verification-strategy.md for automated route/link/SEO/accessibility parity; and
- the checked URL/SEO manifests and compatibility fixtures affected by these changes.
Docs and FAQ keep their established paths and semantics. The final route decisions below are explicit exceptions to older draft clauses; no global slash or extension normalizer is allowed.
Checked source contract
No request fetches GitHub or a legacy website. The deterministic builder pins immutable revisions, verifies bounded public fields and checksums, and bakes the projection into the image. It never follows moving main, executes source content, writes the runtime database, or activates a ContentRelease.
| Projection | Exact checked source | Required count |
|---|---|---|
| Articles, podcasts/transcripts, books, media | Preferred DataTalksClub/content@b9a40ba974fdef67ee3a2a70f114734f2581033c, tree 701fa3f7aa35973e65736a188161c480982f1cb3, repair-manifest SHA-256 80d3014c47bf57de792473fc1da8f7569daeb55107688c3485153f773948d3aa | 55 / 205 / 203 / 98 |
| Reviewed main-content fallback | DataTalksClub/datatalksclub.github.io@ee43d3fa0929faf691178d79f19528e6f15a83e5 through the immutable selection represented by DataTalksClub/content@373bef2912342ece1d2a2d2a9395aa3417243283 | same four counts |
| Events | DataTalksClub/datatalksclub.github.io@ee43d3fa0929faf691178d79f19528e6f15a83e5, _data/events.yaml | 421 |
| People | The same exact legacy-main revision, _people/*.md, excluding only _people/_template.md | 438 |
| Wiki | DataTalksClub/podwiki@988b79d0d655bf4755945c3118544cb9e0dbead6, _wiki/ and checked graph/search inputs | 282 |
| Courses | DataTalksClub/course-management-platform@98a235283904b4ef9ad29e196298540756cf1bcc, scripts/production_like_course_specs.json | 12 |
Every projected record retains repository, exact revision, source path, stable key, checksum, and safe edit/source link when appropriate. Wrong origin/SHA, count drift, duplicate route/key, unresolved required person, unsafe or oversize input, and unexplained omission fail the build with bounded non-sensitive diagnostics. Missing optional media uses the code-owned image-unavailable presentation and never guesses or remotely fetches a substitute.
Final canonical route map
Canonical hub routes are extensionless and have no trailing slash only where this table says so.
Existing editorial content-detail routes keep their established .html suffix.
| Content | Canonical hub | Canonical detail |
|---|---|---|
| Blog/articles | /blog | /blog/.html |
| Podcast | /podcast | /podcast/.html |
| Books | /books | /books/.html |
| People | /people | /people/.html |
| Events | /events | /events/ |
| Courses | /courses | /courses/ for this public catalog projection |
| Wiki | /wiki | /wiki/ |
The owner-approved hub cleanup does not extend to existing content pages. Editorial detail canonicals remain /blog/<slug>.html, /podcast/<slug>.html, /books/<slug>.html, and /people/<short>.html. In particular, the course-guide example remains canonical at /blog/guide-to-free-online-courses-at-datatalks-club.html. Docs/FAQ are unchanged, /podwiki* remains absent, and Wiki/Events/Courses retain the clean contracts in the table. This is an explicit route-family decision, not a global extension or trailing-slash normalizer.
The public course hub/detail are no-slash. When a matching copied-CMP Course row exists, the same canonical public path dispatches to the existing behavior without overwriting it. Deeper authenticated/learner compatibility routes remain unchanged and are not globally normalized in this issue.
Wiki search/filtering is GET /wiki?q= with optional checked type/view query values so the real editorial page whose slug is search can remain /wiki/search. Wiki graph/feed/data/assets use reviewed non-HTML endpoints and must not take a projected page slug. All 282 editorial detail paths are /wiki/, never /wiki/wiki//.
Explicit permanent redirects
Implement only the reviewed aliases, before any catch-all, as one-hop permanent GET/HEAD redirects whose Location preserves the original query string byte-for-byte:
| Legacy/alternate path | Exact target |
|---|---|
| /articles.html | /blog |
| /blog/ | /blog |
| /podcast.html and /podcast/ | /podcast |
| /books.html and /books/ | /books |
| /people.html and /people/ | /people |
| /events.html and /events/ | /events |
| /courses/ | /courses |
| /wiki/ | /wiki |
| /blog/ and /blog// | /blog/.html |
| /podcast/ and /podcast// | /podcast/.html |
| /books/ and /books// | /books/.html |
| /people/ and /people// | /people/.html |
Any additional alias must come from the checked route manifest and be added as an explicit tested row. The four editorial detail patterns above are explicit reviewed families; do not infer a global .html/slash rule for Docs, FAQ, Wiki, Events, Courses, or unrelated paths. Existing .html details are canonical 200 destinations, not redirect sources. Explicit hub and candidate-clean aliases are retained indefinitely. Redirect targets return canonical 200 directly. There are no chains, loops, soft 404s, request-host-derived destinations, or homepage fallbacks. Unsafe methods remain non-mutating and are not silently converted through a redirect.
The /podwiki mount is deliberately retired without compatibility:
- /podwiki, /podwiki/, every descendant, query variant, and representative percent-encoded form return the normal real 404;
- no response has a Location header;
- no route, redirect table, navigation, canonical, form, sitemap, JSON-LD, asset, feed, graph, or rendered internal link contains a /podwiki destination; and
- unrelated unknown paths are also real 404s.
Docs, FAQ, Slack, account, Django admin, Studio, management API, health, and copied-CMP routes retain their established contracts. In particular, do not apply this hub policy to /docs/ or /faq/.
Homepage and visual design
Use the adopted CMP shell, tokens, typography, spacing, focus treatment, and existing icon system.
- The homepage has exactly one featured course: retain the existing owner-approved AI Dev Tools Zoomcamp 2026 feature from #95 and its internal course/cohort destination.
- Immediately after that feature, provide one clear internal Browse all courses link to /courses. Do not render the twelve catalog records as a homepage grid.
- Homepage collection previews and all hubs use full-width CMP-style divided rows. Do not use multi-column card grids for Events, Courses, Blog, Podcast, Books, People, or Wiki.
- Rows have a clear primary internal link, truthful source date/type/summary, stable ordering, honest empty/media fallback, and useful grouping/pagination where needed. Every record is reachable without JavaScript.
- Decorative icons are aria-hidden. Any icon-only control has an accessible name; links retain visible text. External/new-tab icons supplement, never replace, a descriptive label. Do not use ambiguous unlabeled arrows or color alone.
- Templates remain readable, indented, line-broken source. Adjacent structural tags and same-line Django block/control markup in the failed QA report are corrected and guarded by an automated source test.
- Semantic landmarks/headings/lists, keyboard order, visible focus, descriptive image alt/fallback, 200% zoom, reduced motion, and 390 px reflow have no content loss or horizontal overflow.
Events and People
Every one of the 421 events has a stable internal /events/ detail route.
- Homepage and /events rows link only to the internal event detail, never directly to Luma or another provider.
- The detail renders checked title, type, timezone-aware start/end, description/body where present, speakers, recording/recap, and public provider fields.
- An external Luma registration/event link may appear only on the internal detail and is clearly labelled as external/opening a new tab. Recording links are likewise safe and labelled.
- Event slugs are deterministic from checked source data; collisions or changes against the route manifest fail generation.
- Every speaker key resolves to one of the 438 projected people and renders as an internal /people/.html link on event rows/details. Plain speaker text is not acceptable when a key exists.
All 438 non-template _people records are projected and discoverable from /people.
- Each canonical /people/.html page preserves checked public name, bio/body, portrait/fallback, roles/relationships, and sanitized public social/source links.
- Stable identity is the checked short value. Filename/key mismatch, duplicate short/path, unsafe link, missing required speaker, or source-template leakage fails the build.
- Article author, podcast guest/host, book author, event speaker/host, and course instructor relationships use internal person links whenever a checked person key exists. Do not invent a person relation from display-name similarity.
- Public editorial people do not create or imply Django users, staff access, account data, registrations, or private joins.
Read-only, privacy, and content safety
Projection pages allow GET/HEAD only and create no user, session, content, event, course, cohort, registration, enrollment, submission, job, audit, token, email, or other business row. There is no public mutation endpoint.
Use only already-public editorial/catalog fields. Never read or bake production users, emails, credentials, sessions, registrations, learner activity, provider payloads, admin data, or private joins. Sanitize Markdown/HTML using the content-kind policy; reject/escape script, handlers, unsafe protocols, traversal/symlinks, arbitrary embeds/fetches, and executable source.
SEO, robots, and sitemaps
The route move must preserve the full existing DataTalks.Club SEO contract, not only canonical and title.
For every homepage, hub, detail, Docs/FAQ page, and relevant media page, compare the accepted source/crawl manifest and preserve or intentionally map:
- title, meta description, primary heading, language, and meaningful body fingerprint;
- Open Graph type/title/description/URL/image and image metadata;
- Twitter card/site/title/description/image;
- valid JSON-LD types, identifiers, URLs, Event/Person/BlogPosting/PodcastEpisode fields, and breadcrumb structure;
- visible breadcrumbs and their final canonical destinations;
- primary/list image URL, dimensions where known, and meaningful alt/fallback;
- source published and modified timestamps and sitemap lastmod; and
- internal links, fragments, form actions, edit/source links, and allowed external destinations.
Canonicals use https://datatalks.club plus the final route table. Redirect aliases are never canonical. Existing Blog/Podcast/Book/Person .html destinations return 200 and self-canonicalize; candidate clean and trailing-slash variants redirect directly to them. Internal links, alternate/canonical metadata, Open Graph URLs, JSON-LD, breadcrumbs, feeds/search projections, and sitemaps use the unchanged .html editorial details and the reviewed clean hubs. Development pages still emit production-origin canonical/OG/JSON-LD URLs.
Preserve robots.txt, the root sitemap, and section sitemaps/feeds for Blog, Podcast, Books, People, Events, Courses, Wiki, Docs, and FAQ according to the checked inventory. Every sitemap URL must be a production-origin canonical public HTML URL that returns 200 in the same candidate. Sitemaps contain no redirect source, 404/405, query/search/filter URL, fragment, private/auth/admin/Studio/API/health route, development host, /podwiki path, or external URL. Sitemap indexes reference only valid section sitemaps, and lastmod is source-derived rather than build time.
On web.dtcdev.click, every HTML, XML, JSON/feed, redirect, and error response remains under the development noindex/nofollow policy; robots.txt disallows crawling. The review environment may emit the production canonical metadata and sitemap structure for parity testing, but indexing is enabled only during the separately approved production cutover. No sitemap is submitted in this issue.
Editorial migration SEO release gate
Production cutover is blocked until an exhaustive generated route manifest covers every Blog, Podcast, Book, and Person detail plus every hub alias. It must prove: no missing source, duplicate final, route collision, chain, or loop; every established .html detail returns 200 and self-canonicalizes; every explicit hub or candidate-clean alias returns 301 with raw query preserved directly to one final; missing slugs return 404; and only canonical destinations occur in internal links, alternate/canonical metadata, Open Graph, JSON-LD, breadcrumbs, search/feed projections, and root/section sitemaps.
Production robots must permit the accepted public finals at cutover while development remains noindex/nofollow and robots-disallowed. Legacy redirects are retained indefinitely. The cutover runbook submits final sitemaps to Search Console, monitors indexing/coverage, old/new landing traffic, Googlebot crawl/redirect errors, and material organic-search regressions, and names an owner plus a quantitative rollback threshold. Rollback restores the last known-good application while retaining a compatible direct old-to-final redirect surface; it never redirects missing content to home.
Acceptance criteria
- Projection generation reports exactly 55 articles / 205 podcasts / 203 transcripts / 98 books / 421 events / 438 people / 282 Wiki pages / 12 course catalogs with exact immutable provenance and deterministic complete-tree checksums.
- All canonical hubs/details in the final table return useful server-rendered GET/HEAD 200 with exact self-canonical production URLs; every record is discoverable without JavaScript.
- Every inventoried Blog/Podcast/Book/Person
.htmldetail remains a direct200with its exact self-canonical URL; explicit clean/trailing-slash aliases redirect one hop with raw query preserved to that.htmldestination, and missing slugs return real404without home/hub fallback. - Docs/FAQ remain unchanged;
/podwiki*remains404; Wiki/Events/Courses retain their accepted clean route families. - /podwiki and descendants return real 404 without Location and are absent from all generated/rendered destinations. Candidate-only /wiki/wiki/ routes are not shipped.
- Homepage shows exactly the existing #95 featured course plus Browse all courses. Homepage/hub collections use divided rows, not columns/card grids, and meet the icon/accessibility/template-readability contract.
- Every event has an internal /events/ detail. Home/hub links are internal; Luma appears only as a labelled safe external link on detail; speaker keys link to canonical internal People.
- All 438 People are discoverable at /people and canonical /people/.html details with checked public fields and relations; no user/private identity is imported.
- Complete SEO parity covers titles/descriptions/headings, canonical, OG, Twitter, JSON-LD, breadcrumbs, images/alt, published/modified/lastmod, fragments, links, robots, root/section sitemaps, and meaningful body. Every sitemap URL is canonical public 200.
- The exhaustive editorial route manifest has no omission/duplicate/collision/chain/loop; established
.htmldetails are direct200/self-canonical, explicit aliases are direct301, only canonicals appear in metadata/links/sitemaps, redirects persist, and a quantitative rollback threshold/runbook is documented and tested. - [HUMAN] At authorized production cutover, robots permits final public pages, final sitemaps are submitted to Search Console, and named monitoring confirms index coverage/crawl/old-new traffic within the approved rollback threshold.
- Development remains noindex/nofollow and robots-disallowed while emitting production canonical metadata; production indexing remains disabled until cutover.
- All routes are read-only, sanitizer/provenance limits fail closed, and responses/artifacts/logs contain no secret, credential, cookie, registration/learner/private/provider data.
- Focused Django/builder/route/SEO/accessibility tests, template source scan, full automated crawl, normal uv-backed quality/Django suites, and make test-playwright-core pass.
- Independent tester opens desktop and mobile screenshots for home; every hub type; representative oldest/latest details; event detail with speaker/Luma; person detail; Wiki query/detail; missing-media/empty states; each redirect destination; /podwiki 404; Docs/FAQ; and confirms content/layout rather than merely file existence.
Required test scenarios
- Rebuild preferred and fallback projections twice. Compare exact counts, ordering, keys, routes, provenance, checksums, relations, event slugs, transcript associations, media, and complete-tree digest. Vary origin/SHA/count/key/path/person/media and prove deterministic fail-closed behavior without partial output.
- Table-drive every canonical and redirect route for GET/HEAD/status/Location/query preservation/canonical/H1. Assert each established
.htmldetail is the direct final200, every explicit alias is exactly one hop, and hub moves do not alter detail canonicals. Reject inferred aliases, slash loops, APPEND_SLASH dependence, redirect-source canonicals, and unsafe-method mutation. - Crawl every rendered first-party link, canonical, OG/JSON-LD URL, breadcrumb, form action, image/asset, fragment, redirect, root sitemap, and section sitemap. Follow to terminal response; require the approved route/status, zero chains/loops/soft 404s, and no /podwiki or unintended legacy-host destination.
- Compare every selected page with the accepted SEO manifest for title/description/H1/body, OG, Twitter, structured data, breadcrumbs, images/alt, published/modified/lastmod, canonical, and external link. Any unexplained loss fails; expected hub moves are explicit manifest mappings.
- Render all 421 event details, resolve every speaker to the 438-person set, and assert home/hub event anchors are internal. Luma on home/hub fails; safe labelled Luma on detail passes. Freeze timezone boundaries and test duplicate derived slugs.
- Render/index all 438 people. Reject _template, duplicate/mismatched short, unsafe social URL, unresolved required relationship, guessed display-name match, private field, or external speaker link.
- Verify exactly one featured homepage course, one Browse all link, no catalog grid, divided-row structure across every collection, icon accessible names/aria-hidden behavior, semantic heading order, keyboard/focus, 200% zoom, reduced motion, 390 px reflow, and meaningful JavaScript-disabled content.
- Parse every production-mode sitemap and request every listed URL. Require canonical public 200, source lastmod, correct section membership, and no aliases/query/fragments/private/non-HTML/dev-host/external paths. In development verify noindex/nofollow headers and robots disallow across representative HTML/XML/JSON/redirect/error responses.
- Seed database/session/job/email canaries, traverse all public routes and redirects, and prove row/outbox/job/session state unchanged. Run sanitizer/traversal/oversize/secret-PII fixtures and assert safe bounded diagnostics.
- Fail the template source test on same-line Django control blocks, adjacent nested structural tags, compressed markup, inaccessible icon-only controls, or column-grid collection classes in the changed public templates.
Use uv and uv-backed Make targets. All scratch, crawl reports, and screenshots remain below the project-local .tmp/ directory.
Browser acceptance
At desktop approximately 1440x900 and mobile 390x844, with JavaScript enabled and disabled:
- Home shows one featured AI Dev Tools Zoomcamp 2026 course, Browse all courses, real divided-row previews, correct counts, and no grid overflow.
- Navigate each hub and representative detail entirely internally. Confirm clean hub spelling, unchanged
.htmleditorial detail address/self-canonical spelling, direct candidate-clean aliases, internal Event/Person links, and Wiki/wiki/<slug>. - Open an event from home/hub, then its person detail, then the clearly labelled Luma link from the event detail only.
- Exercise /wiki search with q, a Wiki detail including /wiki/search, chips/citations/graph, People pagination/grouping, event empty/upcoming states, and missing media.
- Visit every redirect alias with a query and verify one-hop final URL/content. Visit /podwiki, a child, and an encoded/query variant and verify the normal useful 404 without navigation.
- Inspect Docs/FAQ preservation, SEO metadata, development noindex/robots, root/section sitemaps, keyboard/focus, icons, headings, 200% zoom, reduced motion, and no mobile horizontal overflow.
Store and inspect screenshots only below .tmp/screenshots/issue-105/. Do not capture credentials, private/admin pages, cookies, registration data, or production data.
Dependencies and lifecycle
Closed #30, #34, #35, #37, #95, #97, and the accepted content repair used by the candidate provide sufficient foundations. #38/#39/#40/#43/#44, final Event/Course database migration, complete sync/cutover, and Milestones 7–8 remain related but do not block this bounded public projection.
This issue does not introduce content/Studio/admin API mutation, registration/enrollment/email, AWS change, production deployment, sitemap submission, or indexing activation.
Local implementation and independent QA can prove routes, screenshots, crawl, read-only behavior, development noindex, redirect retention, and the production-mode manifest. Production robots activation, Search Console submission, and post-cutover monitoring remain the named HUMAN criterion. The engineer commit uses Refs #105, the issue retains human, and #105 closes only after that authorized evidence passes.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the existing uncommitted issue-105 candidate and read _docs/specs/02-url-link-seo-compatibility.md, _docs/specs/09-migration-rollout-roadmap.md, and _docs/specs/10-verification-strategy.md. Then inspect the checked URL/SEO manifests and compatibility fixtures. Done means the required projections, routes, redirects, accessibility checks, source-readability test, and verification coverage satisfy the stated counts and contracts.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- django, python
- Domain
- full-stack, testing, web-dev
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 25/100