Skip to content

Commit 6b26b74

Browse files
TMHSDigitalclaude
andcommitted
docs: design spec for one page per catalog entry
Brainstormed with the maintainer on 2026-09-24: full entry content, whole-card navigation replacing the dialog, a built-in markdown renderer with no dependencies, /entry/<id>/ URLs, JSON-LD, sitemap of real pages, llms.txt. Awaiting spec review before an implementation plan. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Wc67NX9MM964uaVGn4bpZJ
1 parent 7cac519 commit 6b26b74

1 file changed

Lines changed: 189 additions & 0 deletions

File tree

Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
# Design: one page per catalog entry
2+
3+
Date: 2026-09-24. Status: approved in conversation, awaiting spec review.
4+
5+
## Why
6+
7+
The repo is gaining stars daily. In the 14 days to 2026-09-24: 232 unique visitors,
8+
ChatGPT the second-largest referrer (29 unique, behind github.com at 30), and the most
9+
visited paths after the front page are individual catalog markdown files on GitHub.
10+
11+
The Pages site does not serve those visitors well:
12+
13+
- It is one page. Entry "permalinks" are `#entry-<id>` fragments, which search engines
14+
and AI crawlers do not index separately, so no entry can be found or cited on its own.
15+
- The entry dialog shows frontmatter and the first paragraph only. The Notes (the
16+
catches), the dated Evidence quotes and the Related links exist only on GitHub.
17+
18+
Goals, from the maintainer: be useful to visitors, reach more people, look credible.
19+
Converting visitors into contributors is not a goal of this project.
20+
21+
## What success looks like
22+
23+
- Someone arriving from a search engine or an AI assistant lands on the entry they
24+
asked about and sees its licence, commercial stance and credit requirement at once.
25+
- Every entry has a stable, indexable, shareable URL carrying the full entry.
26+
- The site shows everything the markdown file does, so GitHub is no longer the only
27+
place to read an entry's catches and evidence.
28+
29+
## Decisions taken
30+
31+
| Question | Decision |
32+
| --- | --- |
33+
| Page content | The full entry: summary, facts, Notes, Evidence, Related |
34+
| Clicking an entry on the homepage | Navigates to its page; the dialog is retired |
35+
| Clickable area | The whole card, via a stretched title link |
36+
| Markdown rendering | A small built-in renderer; no dependencies |
37+
| URL scheme | `/entry/<id>/` (ids are unique catalog-wide, so moving an entry between categories keeps its URL) |
38+
| Deprecated entries | Get a page with a banner, marked `noindex`, left out of the sitemap |
39+
| Out of scope | Pages for category READMEs and `docs/`; homepage visual changes |
40+
41+
## Page anatomy
42+
43+
URL: `<siteUrl>/entry/<id>/`. Title: `<name> (<license>) | Free Game Dev Assets`. Meta
44+
description: the entry summary (first body paragraph, as `summaryFromBody` produces it).
45+
46+
Top to bottom:
47+
48+
1. Site top bar, then a breadcrumb: Catalog, then the category (linking to the homepage
49+
with `?cat=<category>`), then the entry name.
50+
2. `h1` with the entry name; the summary paragraph.
51+
3. "At a glance" facts:
52+
- Licence, with `license_spdx` when set
53+
- Commercial use, using the site's existing labels (commercial OK, non-commercial,
54+
per-file review, commercial ?)
55+
- Credit required; when `attribution_string` is set, the string with a Copy button
56+
- Status, with the legend's one-line meaning
57+
- Verified date with the existing fresh / aging / stale cue
58+
- Publisher, formats, and `camera_perspective` / `grid_dimensions` when set
59+
4. Actions: **Go to source** (the entry `url`, primary), **View the file on GitHub**,
60+
**Report a problem with this entry** (the existing `correction.yml` issue template).
61+
5. The rendered body from the first `##` onwards (Notes, Evidence, Related).
62+
6. Previous and next entry within the same category (same order as the homepage
63+
grouping), then the site footer.
64+
65+
Deprecated entries additionally show a banner stating the entry is deprecated and why,
66+
taken from its `- Deprecated:` line.
67+
68+
Without JavaScript the page is complete; the only script is the Copy button.
69+
70+
## Build architecture
71+
72+
`site/build.mjs` stays the orchestrator. Two new modules:
73+
74+
- **`site/lib/markdown.mjs`**: `renderEntryBody(markdown, context)` returns HTML.
75+
- **`site/lib/entry-page.mjs`**: `entryPageHtml(entry, bodyHtml, neighbours, site)`
76+
returns a full HTML document.
77+
78+
`build.mjs` writes `dist/entry/<id>/index.html` for every entry (about 4 MB in total)
79+
and adds `page` (the entry's URL, relative to the site root) to each entry in
80+
`data.json` and `data.js`. `site/README.md` documents the new field.
81+
82+
### Renderer scope
83+
84+
Measured on 2026-09-24 across all 319 entry bodies: paragraphs, `#` and `##` headings,
85+
bullet lists (three entries nest them), bold, italic (`*x*` and `_x_`), inline code,
86+
links (relative in all 319, external in 91), bare URLs (10) and backslash escapes (4).
87+
No tables, code fences, blockquotes, images, raw HTML or `###`.
88+
89+
- Supported blocks: `##` heading (rendered as `h2`), paragraph (consecutive lines
90+
joined), bullet list with nesting by indentation. The `#` title line is dropped.
91+
- Supported inline: `**bold**`, `*italic*`, `_italic_`, `` `code` ``, markdown links
92+
(bracketed text followed by a parenthesised URL), bare `http(s)://` URLs, backslash
93+
escapes.
94+
- All text is HTML-escaped before inline markup is applied. Code spans are not further
95+
processed.
96+
- Anything else at block level (a line starting with `|`, three backticks, `>`, `![`, a
97+
raw HTML tag, `###` or deeper) throws an error naming the file and line. The build
98+
fails; it never renders unsupported syntax silently.
99+
100+
### Link rewriting
101+
102+
Resolved against the entry's own path in the repo:
103+
104+
- Target is another catalog entry (`x.md`, `../<category>/x.md`): relative page URL
105+
`../x/`, which works under the `/Free-Game-Dev-Assets/` base and in a local preview.
106+
- Target is any other repo file (a category `README.md`, `docs/*.md`): its GitHub blob
107+
URL, built from `site.repo`.
108+
- Absolute `http(s)` URLs are left as they are.
109+
- A relative target that does not exist fails the build.
110+
111+
## Homepage changes
112+
113+
- Card titles and the Safe starting points table link to `entry/<id>/`, in both the
114+
prerendered HTML and `app.js`.
115+
- Whole card clickable: the title link's `::after` covers the card; other links in the
116+
card sit above it with `position: relative` and a higher `z-index`. One named link per
117+
card remains for screen readers and keyboard users.
118+
- The entry dialog, its pager, `openEntry` and the dialog CSS are removed.
119+
- Filters already live in the query string, so Back returns to the same filtered list.
120+
Scroll position: on following an entry link, the page stores `scrollY` in
121+
`sessionStorage` keyed by the full homepage URL, and restores it after the list is
122+
re-rendered. Storage failures are ignored.
123+
- Old links: a homepage load with `#entry-<id>` for a known id calls
124+
`location.replace("entry/<id>/")`. Without JavaScript the fragment still scrolls to
125+
the card, because cards keep their ids.
126+
- `404.html` gains a line pointing to the catalog search.
127+
128+
Unchanged: search, filters, grouping, scroll-spy, the Search button, keyboard
129+
shortcuts, the mobile layout.
130+
131+
## Search engines and AI assistants
132+
133+
Per entry page:
134+
135+
- `<link rel="canonical">` to the page's own URL.
136+
- Open Graph and Twitter tags (title, description, URL, the existing `og-card.png`).
137+
- JSON-LD: a `WebPage` whose `mainEntity` is a `CreativeWork` with `name`, `url` (the
138+
source), `description`, `publisher` when set, `dateModified` (the `verified` date),
139+
and `license` as a URL when `license_spdx` is set (`https://spdx.org/licenses/<id>.html`),
140+
omitted otherwise.
141+
- `noindex` on deprecated entries.
142+
143+
Site-wide:
144+
145+
- `sitemap.xml` lists the homepage and every non-deprecated entry page, with `lastmod`
146+
from `verified`. The `#entry-` URLs are removed.
147+
- `llms.txt`: what the catalog is, its rules (links and metadata only, licences
148+
checked at source, what `needs-review` means), then one line per non-deprecated
149+
entry: name, licence, commercial, credit required, page URL.
150+
- `llms-full.txt`: the same header, then each entry's summary and Notes as plain text.
151+
- Both are generated from the same data as the pages, on every build.
152+
153+
## Testing
154+
155+
Added to `site/checks.test.mjs` (runs in both workflows):
156+
157+
- Renderer fixtures: one accepted case per supported feature, including nested lists
158+
and escapes; one rejected case per unsupported block type; escaping (an entry
159+
containing `<script>` renders as text); link rewriting for each target kind,
160+
including a missing relative target failing.
161+
162+
Added to the build (fails on any violation):
163+
164+
- Across all generated pages: no leaked markdown (a double asterisk, a closing bracket
165+
followed by an opening parenthesis, a backtick), exactly one
166+
`h1`, a canonical link, a non-empty title, and every internal link resolving to a
167+
generated file.
168+
169+
Before shipping, checked in a browser as in earlier QoL passes: contrast in light and
170+
dark, keyboard order, the stretched link, back-navigation scroll restore, the
171+
`#entry-` redirect, and layout at 375x800 and 800x400.
172+
173+
## Risks
174+
175+
- **Page count and build time.** 319 small files; the build is pure string work. Watch
176+
the Pages artifact size; no action expected.
177+
- **Renderer drift.** A future entry using new syntax fails the build by design, with
178+
the file and line. The fix is to extend the renderer and its fixtures, or rewrite the
179+
entry.
180+
- **Link rot on GitHub blob URLs** for docs and READMEs, if files move. The validator
181+
already checks relative links on the markdown side, so a move breaks there first.
182+
- **Search engines keeping old fragment URLs.** The redirect covers visitors; the new
183+
sitemap replaces the old URLs for crawlers.
184+
185+
## Follow-ons, not in this project
186+
187+
- Pages for category READMEs (the "choosing" tables) and `docs/` guides.
188+
- Starter stacks by game type (sub-project A), visible trust signals (C), README first
189+
screen (D), and the maintainer-only items (E), as mapped in the brainstorm.

0 commit comments

Comments
 (0)