Skip to content

Commit 9597dec

Browse files
committed
ADR-1-8: MyST flat slugs vs Hugo paths
Netlify's link checker is failing due to a URL structure mismatch between Hugo and MyST.
1 parent 864a43f commit 9597dec

3 files changed

Lines changed: 111 additions & 0 deletions

File tree

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
# ADR 0008 — URL structure: MyST flat slugs vs Hugo hierarchical paths
2+
3+
Date: 2026-05-18
4+
Status: Proposed
5+
Branch: lb/myst-migration
6+
7+
## Context
8+
9+
Hugo derives page URLs from the directory structure: `content/about/governance.md`
10+
`/about/governance/`. The directory hierarchy IS the URL, and `content/` is
11+
treated as the URL root — it is stripped from every path.
12+
13+
MyST's default behaviour derives URLs from the filename only, ignoring the
14+
containing directory: `content/about/governance.md``/governance`. Files
15+
named `index.md` in subdirectories collide on the slug `index` and are
16+
deduplicated as `index-1`, `index-2`, etc.: `content/about/index.md`
17+
`/index-1`.
18+
19+
MyST does support directory-based URLs via `site.options.folders: true` in
20+
`myst.yml`. However, MyST has no concept of a "content root" — it has no
21+
config option equivalent to Hugo's `content/` stripping. MyST grew from the
22+
Jupyter notebook world where content lives at the project root alongside
23+
`myst.yml`; a top-level `content/` subdirectory is a Hugo convention, not a
24+
MyST one. With `folders: true` and content in `content/`, the output is
25+
`/content/about/governance/` — the `content/` prefix is preserved.
26+
27+
Verified in MyST 1.9.0: no frontmatter field (`slug`, `url_path`, etc.)
28+
controls a page's URL. URL generation is internal to MyST.
29+
30+
This was surfaced by `netlify-plugin-checklinks` during the first Netlify
31+
deploy of the PR. The build succeeds; the link checker finds 12 broken internal
32+
links because content was authored for Hugo-style hierarchical URLs
33+
(`/about/governance`, `/contributors/`, etc.) that do not exist under MyST's
34+
default flat-slug output.
35+
36+
Affected link types:
37+
38+
- Section index cards: `:link: /contributors/`, `:link: /documentation/` etc.
39+
in `content/index.md`
40+
- Inline markdown links: `[Role](/community/role)` in `content/community/index.md`
41+
- Sidebar navigation links generated by MyST from the toc (use actual slugs,
42+
so these are self-consistent but don't match the Hugo URL shape)
43+
44+
## Options considered
45+
46+
1. **Enable `site.options.folders: true` + move content to project root**
47+
- Enable `site.options.folders: true` in `myst.yml`.
48+
- Move all content from `content/<section>/` to `<section>/` at the project
49+
root (e.g. `content/about/governance.md``about/governance.md`).
50+
- Update all `toc` file paths in `myst.yml` accordingly.
51+
- Result: `about/governance.md``/about/governance/`, matching Hugo's
52+
URL structure exactly.
53+
- `<section>/index.md` files become section landing pages
54+
(`/contributors/`, `/about/`, etc.) — matching Hugo's behaviour.
55+
- Pros: follows MyST's documented design and conventional project structure;
56+
preserves URL continuity for external links; no SEO disruption; no
57+
redirects needed.
58+
- Cons: restructuring all file paths is a significant mechanical change;
59+
any tooling or scripts that reference `content/` must be updated.
60+
61+
2. **Rename `index.md` to `section.md` + update all internal links to flat URLs**
62+
- Rename each `content/<section>/index.md` to `content/<section>/<section>.md`
63+
so MyST generates slug `/<section>` instead of `/index-N`.
64+
- Update all cross-page links in content to use flat URLs (`/governance`
65+
not `/about/governance`).
66+
- Add a Netlify `_redirects` file mapping old Hugo URLs to new flat URLs for
67+
external link / bookmark compatibility.
68+
- Pros: flat URLs are shorter; avoids project restructure.
69+
- Cons: large mechanical content churn; URL structure changes permanently;
70+
external links to the Hugo site break without redirects; flat URLs lose
71+
section context; SEO impact from changed URLs persists until redirects
72+
are indexed.
73+
74+
3. **Netlify `_redirects` shim (keep Hugo-style links, redirect to flat URLs)**
75+
- Keep content links as-is; add a `_redirects` file that maps every
76+
hierarchical Hugo URL to the corresponding flat MyST slug.
77+
- Pros: no content changes; external links preserved.
78+
- Cons: fragile — `index-N` numbering shifts if toc order changes;
79+
maintenance burden every time a page is added; masks the underlying issue.
80+
81+
4. **Disable `netlify-plugin-checklinks` failure / warn-only**
82+
- Configure or remove the plugin so broken links produce warnings, not a
83+
build failure. Defers URL fix to a follow-up issue.
84+
- Pros: unblocks the PR immediately.
85+
- Cons: leaves broken links in the deployed site; removes the link-integrity
86+
safety net established by ADR 0007.
87+
88+
## Decision
89+
90+
_Pending team discussion._
91+
92+
Recommendation: Option 1 (`folders: true` + move content to project root). It
93+
follows MyST's documented design and conventional project structure, preserves
94+
the existing URL shape without content link edits, and avoids the fragility of
95+
redirect shims. The file restructure is mechanical and one-time.
96+
97+
## Consequences
98+
99+
- Option 1 requires moving all content files out of `content/` to the project
100+
root and updating all `toc` entries in `myst.yml`. No content link edits
101+
are needed since URLs are preserved.
102+
- External links from the Hugo site (`/about/governance/`, `/contributors/`,
103+
etc.) continue to work unchanged — no redirects needed.
104+
- Until resolved, `netlify-plugin-checklinks` will fail on every Netlify deploy
105+
with 12 broken internal links.

docs/decisions/0001-myst-migration/PLAN.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,11 @@ mapping pattern **once per shortcode type**, not nine times.
202202
203203
### CI status: Netlify deploy still failing (same reason as Phase 2).
204204
205+
**Note:** Phase 3 card `:link:` values and inline markdown links were authored
206+
with Hugo-style hierarchical URLs. ADR 0008 must be resolved before or
207+
alongside Phase 3 commits in the final history — if Option 1 (rename +
208+
flat URLs) is chosen, Phase 3 link values need a fixup commit.
209+
205210
---
206211
207212
## Phase 4 — MyST config completeness

myst.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,3 +56,4 @@ site:
5656
options:
5757
domain: learn.scientific-python.org
5858
logo: assets/images/logo.svg
59+
folders: true

0 commit comments

Comments
 (0)