Enrich the Obsidian ROM-hack vault from the valhalla Discord scrape
(/storage1/labdata/romhacks/metadata) plus web research, growing the catalog
from 285 to 368 notes and preparing a data export for a wiki site.
Tooling (all dry-run by default, --apply to write; .scrape/ is gitignored):
- scrape_match.py reconcile scrape entries vs notes (43 overlap / 211 match / 83 new)
- enrich_vault.py backfill frontmatter, merge scrape into curated notes,
create 83 new notes, rebuild import bodies to one layout
- enrich_web.py apply hand/web-verified facts from .scrape/web_facts*.json
- build-wiki-data.py export wiki/catalog.json (the site data source)
Results: 368 notes, 327 with served banner art, 332 rich summaries, 200 with
feature lists; new frontmatter developer/release_date/banner/homepage/scrape_dir;
12 flagship hacks web-verified. wiki/SPEC.md describes the site build.
build-vault-mocs.py Index callout updated for the new counts.
5.3 KiB
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:
{
"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/<dir>/<file>", // 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/<scrape_dir>/<file>(thebannerfield is already a full URL — just use it). - The site should download
bannerimages at build time into its ownpublic/and rewrite to local paths — don't hot-link valhalla in production, and provide a placeholder for the ~41 imageless hacks.
Pages
- 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
facetsfor counts). Free-text search over title + developer + summary. - Sort: by name, by release_date, by platform.
- Hack detail (
/hack/<stem>) — 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. - Browse by platform / base / type — landing lists (mirror the vault MOCs).
- (optional) Play queue — filter by
play_status, showratingstars.
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 fetches 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".