# Pokémon ROM-Hack Wiki — build spec
A handoff for the session that builds the browsable wiki site. Everything the
site needs is already exported to **`wiki/catalog.json`** by
`scripts/build-wiki-data.py` (re-run it after any vault edit).
## Data source
`wiki/catalog.json`:
```jsonc
{
"generated": "2026-06-08",
"count": 368,
"image_base": "https://romhacks-files.ginnoir.com",
"facets": { // pre-counted, for filter UI
"platform": { "GBA": 188, "NDS": 47, "Unknown": 45, "PC": 40, "GBC": 22, "GB": 14, "3DS": 6, "Patch": 6 },
"base": { "...": 0 },
"status": { "Complete": 0, "Ongoing": 0, "Beta": 0, "Unknown": 0 },
"type": { "Expansion": 143, "New Experience": 129, "Difficulty": 105, "QoL": 50, "Vanilla+": 21, "Cosmetic": 11, "Demake": 8, "Roguelite": 5 },
"play_status": { "Unplayed": 0 }
},
"hacks": [
{
"stem": "Radical Red", // unique id / route slug
"title": "Pokémon Radical Red",
"platform": "GBA", "base": "FireRed", "version": "4.1",
"status": "Complete", "type": ["Difficulty","Expansion"],
"generation": "Gen 1–9",
"developer": "Soupercell (Yuuiii) & koala4",
"release_date": "2024", // ISO date or bare year, may be null
"banner": "https://romhacks-files.ginnoir.com/_meta/
/", // may be null
"homepage": "https://...", // canonical info page, may be null
"source": "https://...", // download / thread, may be null
"library_path": "...", "play_status": "Unplayed", "rating": 4, // rating optional
"summary": "…2-3 sentence overview…",
"notability": "…why it stands out (flagship hacks only)…",
"story": "…plot, when known…",
"features": ["…", "…"],
"links": [ { "label": "Download", "url": "…" } ],
"tags": ["hack","platform/gba","base/firered","type/difficulty"]
}
]
}
```
Nulls are real: ~45 `platform: null` (Unknown), some `base/version/status` null.
The UI must degrade gracefully (hide the chip, don't print "null"/"—").
## Coverage (what's populated, as of this export)
- 368 hacks · **327 with banner images** · 332 with a rich summary · 200 with feature lists.
- ~20 flagship hacks (Radical Red, Unbound, Gaia, Infinite Fusion, Reborn,
Rejuvenation, Emerald Rogue, Elite Redux, Sacred/Storm, Crystal Clear,
Snakewood, Inclement Emerald, …) have hand-verified dev/version/notability.
- The long tail is scrape-sourced: good summary + image, sometimes null base/version.
## Images
All art is served from Caddy on valhalla:
- Scrape art (every hack): `https://romhacks-files.ginnoir.com/_meta//`
(the `banner` field is already a full URL — just use it).
- The site should **download `banner` images at build time** into its own
`public/` and rewrite to local paths — don't hot-link valhalla in production,
and provide a placeholder for the ~41 imageless hacks.
## Pages
1. **Home / directory** — the headline surface.
- Hero with the total count + a few flagship cards.
- A filterable, searchable **grid of hack cards**. Facets: platform, base,
type, status (use `facets` for counts). Free-text search over title +
developer + summary.
- Sort: by name, by release_date, by platform.
2. **Hack detail** (`/hack/`) — banner, title, the info chips
(platform · base · version · status · dev · release), summary, "Why it
stands out", story, features list, links, and play-status/rating if set.
Cross-link to other hacks sharing base/developer.
3. **Browse by** platform / base / type — landing lists (mirror the vault MOCs).
4. (optional) **Play queue** — filter by `play_status`, show `rating` stars.
## Visual direction (per ginnoir's design-quality rules — no generic templates)
- Pick an opinionated direction. Suggested: **"retro game-cartridge / Pokédex"**
— a dark, slightly CRT-tinted base with one strong accent per *type*
(Difficulty=red, Expansion=violet, New Experience=teal, QoL=green,
Vanilla+=blue, Demake=amber, Roguelite=magenta, Cosmetic=pink). Use the type
accent as the card's left border / chip color so the grid reads at a glance.
- Cards: banner image with a gradient scrim, title, base+platform chip row,
a one-line summary clamp. Hover = lift + accent glow (compositor-only
transform/opacity). Real focus-visible states.
- Hierarchy through scale: big editorial hero, dense but rhythmic grid.
- Typography: a characterful display face for titles + a clean sans for body
(two families max). Tabular nums for versions/dates.
- Treat the platform/type facets as a designed filter rail, not a stock sidebar.
## Tech suggestion
Static, no backend. **Astro** (content-collection from `catalog.json`) or a
small **Vite + vanilla/Preact** SPA that `fetch`es `catalog.json`. Build to
static HTML, host on the same Caddy box (add a stack in `homelabstack`) or any
static host. Keep JS budget small (<150 kB) — it's a catalog, not an app.
## Regenerating the data
```
python scripts/build-vault-mocs.py # refresh in-vault MOC tables (Obsidian)
python scripts/build-wiki-data.py # refresh wiki/catalog.json (the site)
```
The vault notes are the single source of truth. To enrich more hacks before
building, see `../README.md` → "Enrichment pipeline".