D. Rimron-Soutter e803274af4 react-bootstrap migration, review & parser fixes
UI / react-bootstrap:
Migrate client components to react-bootstrap (Card, Table, Form,
Alert, Badge, Nav, Button, Spinner, Row, Col): the ZXDB explorers
and detail pages (Labels, Genres, Languages, MachineTypes, Releases,
Entries), TapeIdentifier, home page, Navbar and ThemeDropdown.
Server components (home, zxdb hub, magazines, issues) keep raw
HTML+className — react-bootstrap barrel imports resolve to undefined
under Turbopack in server components. Replace bi bi-* CSS icons with
react-bootstrap-icons. Add aria-labels to search inputs and
visually-hidden captions to data tables.

Code-review remediation (docs/todo.md):
- FileViewer: replace useState-as-effect with a proper useEffect.
- register.service: restore request-level caching of parsed registers.
- middleware: convert .js to .ts, dev-only request logging.
- Extract shared types to src/types/zxdb.ts; add src/server/repo
  barrel for incremental per-domain splitting.
- Extract helpers: parseIdList (params.ts), serialize (serialize.ts),
  buildRegisterSummary/isInfoLine (register_helpers.ts).
- Add loading.tsx skeletons for dynamic ZXDB detail routes.
- generateMetadata + notFound() on entry/release/label detail pages.
- opengraph-image: stable keys; ThemeDropdown: drop hardcoded cookie
  domain; remove unused page.module.css.

Register parser & data:
- Update data/nextreg.txt from upstream tbblue (SpectrumNext FPGA):
  0x04/0x0A/0x0F/0x80/0x81 bit changes, new Issue 5 board id, 0x43
  renamed "Palette Control", 0xF0/0xF8/0xF9/0xFA now "Issues 4 and 5
  Only".
- Add reg_44 custom parser for 0x44 (Palette Value 9-bit): the two
  consecutive writes render as separate "1st write" / "2nd write"
  modes.
- Skip commented-out register headers so the disabled 0xA3 block no
  longer leaks a phantom register.
- Add detailHasContent guard so body-less registers (0xC7/0xCB/0xCF/
  0xFF) and 0xF0's leading blank no longer emit empty tab strips.
- Capture 0xF0's leading "Issues 4 and 5 Only" line as register text.
- Add isIssueRestricted (case-sensitive) to detect the issue badge
  across rewording without flagging per-bit "(issue 5 only)" notes;
  update badge label to "Issues 4 & 5 Only".

claude-opus-4-8@lucy
2026-06-08 22:47:37 +01:00
2026-01-10 18:04:04 +00:00
2025-12-12 13:43:30 +00:00
2025-10-07 22:04:14 +01:00
2025-10-07 22:04:14 +01:00
2025-10-07 22:01:08 +01:00
2025-12-17 20:22:00 +00:00
2025-10-15 23:04:08 +01:00
2026-01-10 22:52:27 +00:00

Spectrum Next Explorer

A Next.js application for exploring the Spectrum Next ecosystem. It ships with:

  • Register Explorer: parsed from data/nextreg.txt, with realtime search and deep links
  • ZXDB Explorer: a deep, crosslinked browser for entries, labels, genres, languages, and machine types backed by a MySQL ZXDB instance
  • Bootstrap 5 theme with light/dark support

Quick start

  • Prerequisites: Node.js 20+, pnpm (recommended), access to a MySQL server for ZXDB (optional for Registers)
  • Install dependencies:
    • pnpm install
  • Run in development (Turbopack, port 4000):
  • Build and start (production):
  • Lint:
    • pnpm lint

Project scripts (package.json)

  • dev: PORT=4000 next dev --turbopack
  • build: next build --turbopack
  • start: next start
  • deploy: merge current branch into deploy and push to explorer.specnext.dev
  • deploy:branch: same as deploy, but accepts a deploy branch argument
  • setup:zxdb-local: configure local submodule excludes for ZXDB SQL files
  • deploy-test: push to test.explorer.specnext.dev
  • deploy-prod: push to explorer.specnext.dev

Routes

  • / — Home
  • /registers — Register Explorer
  • /zxdb — ZXDB Explorer (hub)
  • /zxdb/entries — Entries search + filters
  • /zxdb/entries/[id] — Entry detail
  • /zxdb/releases — Releases search + filters
  • /zxdb/labels and /zxdb/labels/[id] — Labels search and detail
  • /zxdb/genres and /zxdb/genres/[id] — Genres list and entries
  • /zxdb/languages and /zxdb/languages/[id] — Languages list and entries
  • /zxdb/machinetypes and /zxdb/machinetypes/[id] — Machine types list and entries
  • /zxdb/magazines and /zxdb/magazines/[id] — Magazines list and issues
  • /zxdb/issues/[id] — Issue detail (contents and references)

ZXDB setup (database, env, and helper tables) The Registers section works without any database. The ZXDB Explorer requires a MySQL ZXDB database and one environment variable.

  1. Prepare the database (outside this app)
  • Import ZXDB data into MySQL. If you want only structure, use ZXDB/ZXDB_mysql_STRUCTURE_ONLY.sql in this repo. For data, import ZXDB via your normal process.
  • Create the helper search tables (required for fast search):
    • Run ZXDB/scripts/ZXDB_help_search.sql against your ZXDB database.
  • Create a readonly role/user (recommended):
    • Example (see bin/import_mysql.sh):
      • Create role zxdb_readonly
      • Grant SELECT, SHOW VIEW on database zxdb
  1. Configure environment
  • Copy .env from example.env.
  • Set ZXDB_URL to a MySQL URL, e.g. mysql://zxdb_readonly:password@hostname:3306/zxdb.
  • On startup, src/env.ts validates env vars (t3.gg pattern with Zod) and will fail fast if invalid.
  1. Run the app
  1. Keep the ZXDB submodule clean (recommended)
  • Run pnpm setup:zxdb-local once after cloning.
  • This keeps ZXDB/ZXDB_mysql.sql and ZXDB/ZXDB_mysql_STRUCTURE_ONLY.sql available locally without appearing as untracked changes.

API (selected endpoints)

  • GET /api/zxdb/search?q=...&page=1&pageSize=20&genreId=...&languageId=...&machinetypeId=...&sort=title&facets=1
  • GET /api/zxdb/entries/[id]
  • GET /api/zxdb/releases/search?q=...&year=...&languageId=...&machinetypeId=...&sort=...
  • GET /api/zxdb/labels/search?q=...
  • GET /api/zxdb/labels/[id]?page=1&pageSize=20
  • GET /api/zxdb/genres and /api/zxdb/genres/[id]?page=1
  • GET /api/zxdb/languages and /api/zxdb/languages/[id]?page=1
  • GET /api/zxdb/machinetypes and /api/zxdb/machinetypes/[id]?page=1
  • GET /api/zxdb/{availabletypes,casetypes,currencies,filetypes,roletypes,schemetypes,sourcetypes}

Implementation notes

  • Next.js 15 dynamic params: pages and API routes that consume params must await it, e.g. export default async function Page({ params }: { params: Promise<{ id: string }> }) { const { id } = await params; }
  • ZXDB integration uses Drizzle ORM over mysql2 with a singleton pool at src/server/db.ts; API routes declare export const runtime = "nodejs".
  • Entry and detail pages serverrender initial content and use ISR (revalidate = 3600) for fast timetocontent; index pages avoid a blocking first client fetch.
  • Database Schema: Repository queries include graceful fallback checks (via information_schema.tables) to remain functional even if optional tables (like releases or downloads) are missing from the connected MySQL instance.

Further reading

  • ZXDB details and API usage: docs/ZXDB.md
  • Agent/developer workflow and commit guidelines: AGENTS.md

License

  • See LICENSE.txt for details.
Description
Languages
TypeScript 93.8%
JavaScript 3.7%
SCSS 1.2%
Shell 1.2%
Dockerfile 0.1%