DataTalksClub / DataTalksClub/website

Make /slack the canonical destination for Slack links in the Docs

Open
#184 17 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

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

Description

User outcome

Every link in rendered source-backed content that sends a reader to the DataTalks.Club Slack
community lands on this site's own /slack page instead of going straight to an external
Slack URL. /slack is the one canonical destination for community-Slack links.

Owner note (recorded at intake): the /slack page itself does not need to show a Slack
join/invite link. That is an explicit non-goal; the missing invite is not a gap.

Normative links

  • _docs/specs/02-url-link-seo-compatibility.md § "Route rules that must remain exact"
    (historical hub aliases redirect permanently in one hop, queries preserved; no catch-all
    redirects) and § "Link preservation checks" (rendered-page link resolution).
  • _docs/specs/01-platform-architecture.md § "Member signup, profile, Slack, and course
    registration" (the authenticated Slack-access reveal is a different, member-flow surface —
    see Non-goals).
  • Issue #167 (closed, commit 14b7812) established the render-time rewrite layer this issue
    extends.

Current state at main (9603342)

Already canonical today
  • /slack is served by content/review_views.py::slack from
    content/review_projection.json (slack record: title, lead, 8 channel chips, one
    troubleshooting CTA) and is primary navigation
    (templates/core/_site_shell_head.html:25,197).
  • Route and alias contract is exact and tested
    (content/tests/test_canonical_routes.py::test_slack_route_and_alias_have_exact_method_and_query_contracts):
    GET/HEAD /slack → 200 with canonical https://datatalks.club/slack; POST → 405
    (Allow: GET, HEAD, no-store); GET/HEAD /slack.html?<query> → 301 to
    /slack?<query> preserving the raw query byte-for-byte (website/urls.py:73).
  • Render-time hub-alias rewrites to /slack already exist:
    • Docs (content/docs_projection.py _INTERNAL_HUB_PATHS, lines 145-152): /slack.html
      and /slack/guidelines.html, both relative and https://datatalks.club absolute, inside
      Markdown link spans, preserving query and fragment.
    • Course FAQ (content/faq_data.py::render_faq_answer, the
      https?://datatalks.club/slack.html substitution).
    • Article FAQ (content/article_faq.py::_rewrite_legacy_links, same family).
Remaining inventory (checked projections at main)

Verified by scanning Markdown link destinations in content/docs_projection.json and
content/faq_projection.json:

  1. Workspace deep links in Docs — the core gap. 32 distinct external Slack URLs for this
    workspace (31 https://app.slack.com/client/T01ATQK62F8/<channel> plus
    https://datatalks-club.slack.com/archives/<channel>), 72 link occurrences across 16 pages,
    concentrated in /docs/general/slack/ (channel directory), course "getting started",
    "resources", and zoomcamp-logistics pages, and community guidelines pages. All still go
    straight to Slack.
  2. FAQ workspace links. One app.slack.com/client/T01ATQK62F8/... link and one
    datatalks-club.slack.com/archives/... link, in answers rendered on
    /faq/machine-learning-zoomcamp.html and /faq/llm-zoomcamp.html.
  3. Absolute canonical-form links in Docs. 6 pages link
    https://datatalks.club/slack (already the right destination, wrong form: absolute
    same-host instead of root-relative /slack). The #167 map does not normalize it.

Classification of what is not a community-Slack link and must stay untouched:

  • https://slack.com/help/articles/... (2 in Docs, 1 in FAQ): Slack's own product
    documentation, cited as reference, not an entry to our community.
  • /docs/general/slack/ and {{ '/general/slack/' | relative_url }} links: Docs-internal
    pages about Slack, already routed correctly by _docs_url.
  • Event descriptions: content/event_description_link_policy.py already removes
    app.slack.com (provider action) and forbids join.slack.com (join host) in reviewed event
    descriptions. There are no join.slack.com invite links anywhere in the Docs projection.

Destination contract

  • The canonical destination for community-Slack links in rendered source-backed content is
    the root-relative /slack (canonical https://datatalks.club/slack).
  • A link is a community-workspace link when its host is datatalks-club.slack.com (any
    path) or its host is app.slack.com and its first path segment is T01ATQK62F8 (this
    workspace's ID). Workspace links rewrite to /slack and drop their query and fragment:
    both address Slack's own UI (/client/..., /archives/...), not anchors on /slack.
  • Hub aliases (/slack.html, /slack/guidelines.html, absolute https://datatalks.club/slack)
    continue to rewrite to /slack preserving query and fragment per the existing #167
    mechanism; absolute https://datatalks.club/slack joins the map so it normalizes to
    root-relative.
  • Preserving a ?utm_*/?source= tag on hub-alias rewrites stays safe: /slack has no
    strict query grammar (the view ignores the query string), so the catalogue-query strictness
    addressed in 643ea32 does not apply here.
  • Rewrites happen at render time, keeping the checked projections byte-identical — the
    architecture #167 set and the immutability test enforces
    (content/tests/test_docs_projection.py::test_rendering_keeps_projection_source_and_metadata_immutable).

Scope

  1. Extend the render-time link policy in content/docs_projection.py with the
    community-workspace rule above (Docs Markdown link destinations only, not literal text or
    code spans, matching the existing span-scanning approach).
  2. Extend content/faq_data.py::render_faq_answer with the same community-workspace rule.
  3. Normalize absolute https://datatalks.club/slack link destinations in Docs to /slack.
  4. Add the missing legacy alias: GET/HEAD /slack/guidelines.html?<query> → 301
    /slack?<query> in one hop, query preserved, with the same method/cache contract as
    /slack.html (website/urls.py, alongside line 73). This serves inbound legacy links that
    today get a 404, per spec 02's no-unexplained-404 parity rule.
  5. Documentation: add one clarifying sentence to _docs/specs/01-platform-architecture.md
    § "Member signup, profile, Slack, and course registration" distinguishing the public
    /slack landing page from the specified authenticated
    /accounts/community/slack/ reveal surface. No change to that member-flow contract.
  6. Focused tests: new rewrites (Docs and FAQ), unaffected links byte-for-byte, the new
    redirect's method/query contract, and projection immutability.

Non-goals

  • No join/invite link on /slack (owner note above) and no change to the /slack page's
    content, channels list, or design.
  • No per-channel anchors on /slack (e.g. /slack#ml-zoomcamp): the page lists channels as
    plain chips today; adding 30+ targets is a separate product decision. Deep links rewrite to
    plain /slack, accepting the loss of channel-specific landing.
  • No edits to content/docs_projection.json, content/faq_projection.json, or the upstream
    content source; the immutability tests must stay green.
  • No changes to the event-description link policy (already removes these hosts there) or the
    article-FAQ pipeline (zero workspace links in content/article_faq.json today; adding
    untestable rewrite code there is not part of this slice).
  • No rewriting of slack.com/help/... product documentation links or any other external host.
  • No decision here on the member-flow Slack-access reveal: whether/how
    /accounts/community/slack/ gets built stays with the member-onboarding flow and
    _docs/specs/open-decisions.md (open decision 19). This issue only clarifies the wording.
  • No newsletter, Luma, or other hub-link changes (#167 owns those).

Dependencies

  • None open. The render-time rewrite layer (#167, commit 14b7812) and the source-backed Docs
    renderer (#176, commit 896799b) are on main.

Acceptance criteria

  • Rendered Docs Markdown link destinations matching the community-workspace rule emit
    href="/slack"; no rendered Docs page emits href="https://app.slack.com/client/T01ATQK62F8/…"
    or href="https://datatalks-club.slack.com/…".
  • All 16 affected Docs pages and both affected FAQ answers are covered by focused tests
    that assert the rewrite (the FAQ test asserts the rendered answer HTML, not the source).
  • Absolute https://datatalks.club/slack link destinations in Docs render as
    root-relative /slack with query and fragment preserved.
  • Links to slack.com/help/..., /docs/general/slack/, and every unrelated external link
    remain byte-for-byte unchanged in rendered output.
  • GET/HEAD /slack/guidelines.html?x=1 returns 301 to /slack?x=1 preserving the raw
    query; POST returns 405 with Allow: GET, HEAD and Cache-Control: no-store, max-age=0,
    matching the /slack.html contract.
  • content/docs_projection.json and content/faq_projection.json are byte-identical
    before and after rendering (existing immutability tests stay green and cover the new rule).
  • Link-preservation/compat checks over rendered pages stay green with the rewritten links
    resolved internally against /slack.
  • Spec 01 clarification sentence added; the member-flow contract text is otherwise
    unchanged.
  • Tester screenshots at desktop and mobile for /docs/general/slack/,
    /docs/courses/ml-zoomcamp/getting-started/, /faq/machine-learning-zoomcamp.html, and
    /slack show the expected pages with working links, not errors or broken layouts.

Browser scenarios

  1. Open /docs/general/slack/; every channel entry links to /slack; following one lands on
    /slack (community page with channel chips), not Slack.
  2. Open /docs/courses/ml-zoomcamp/getting-started/; the community/asking-questions links
    land on /slack; a slack.com/help/... citation still opens Slack's own article in a new
    context without being redirected.
  3. Open /faq/machine-learning-zoomcamp.html; the "How do I get help if I'm stuck?" answer's
    Slack link lands on /slack.
  4. Visit /slack/guidelines.html?utm_source=docs; the browser ends at
    /slack?utm_source=docs in one hop showing the community page.
  5. Repeat 1-3 at mobile width; content and links remain readable and usable.

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

Start with the render-time link handling in content/docs_projection.py and content/faq_data.py, then inspect website/urls.py and the existing canonical-route and projection-immutability tests. Add focused coverage for workspace-link and absolute-/slack rewrites, the guidelines redirect, unaffected links, and the documentation clarification; done means the listed rendered-page, method/query, immutability, and link-preservation checks pass.

Written by the indexing model from the issue text.

Assessment

Tech stack
markdown, python
Domain
backend, documentation, testing
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
58/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.