feat: read guides and wiki nav from data

Platform guides, device groups, terminal tabs, pack README manuals and
logo credits move from Python tables to platforms/_guides.yml, checked
against the registry on load. A folder row without a path is the
registry's extract_to, written once.

Wiki pages place themselves in the navigation with order and nav_title
in their front matter. Generated docs/ and mkdocs.yml are unchanged.
This commit is contained in:
Abdessamad Derraz committed 2026-10-22 15:06:52 +02:00
1 parent b77cc0b8fd
commit be3324f869
28 files changed
+1207 -610

No files matched your search

+54 -12
View File
@@ -1,5 +1,6 @@
---
level: contribute
order: 20
---
# Adding a platform
@@ -175,18 +176,8 @@ platforms:
`device_group` places the platform among the devices a reader picks from: on
the site's "Get your files" page, in the "Your setup" navigation and on the home
page. The groups and their labels are `DEVICE_GROUPS` in
`scripts/siteguides.py`, and the same file holds the platform's guide text
(what it is, where its BIOS folder is, where the install command runs). A
test fails when a registered platform has no group or no guide.
The guide text is read by someone who knows their device and little else.
`summary` is one plain sentence, with no chip or board names. `notes` hold
one fact each that the reader acts on. A source citation, a list of models or
how the installer finds the folder goes in `reference_notes`, which open the
Reference part of the page, and a rare build goes in `more_folders`, shown
folded. The guide part of every setup page is held to the word budgets of
[Pages for newcomers](testing-guide.md#pages-for-newcomers).
page. The groups, their labels and their anchors are under `device_groups` in
`platforms/_guides.yml`, beside the platform's [guide text](#guide-text).
A platform without a scraper (`scraper: null`, `schedule: null`) keeps its YAML
as a hand-maintained file. Every registered platform has a scraper today, so
@@ -235,6 +226,56 @@ platform hands it no folder. `platform_layouts` builds one view per directory,
so the builder, the manifest, verify and slots read the same placement, and the
resolver still looks the collection up by the core's own path.
### Guide text
`platforms/_guides.yml` holds each platform's guide: what it is, where its
BIOS folder is, where the install command runs. It is data, edited like the registry, and
no Python changes when a platform is added. The registry keeps what tools read
and `_guides.yml` keeps what people read, so neither grows unreadable.
```yaml
guides:
knulli:
summary: A system for handhelds, based on Batocera.
folders:
- where: On KNULLI # no path: the registry's extract_to
run: [device] # terminal tabs, in the order shown
reference_notes:
- KNULLI runs on handhelds among them the RG35XX family (H700).
logo_owner: KNULLI
logo_licence: GitHub organisation avatar of knulli-cfw
```
- `summary`, `folders` and `run` are required. Every value is Markdown.
- A folder row without `path` shows the registry's `extract_to`. That folder
is written once, where the installer and the release notes read it too.
- `run` names entries of `terminals` in the same file: `windows`, `macos`,
`linux`, `steamdeck`, `android`, `device` or `server`.
- `dest` puts `--dest` in the command, and `on_card: true` makes it the SD
card's path.
- `more_folders` lists rare builds, shown folded under `more_folders_title`.
`more_folders_detected: true` adds a row for each named system the
registry's `install.detect` rules find the platform on.
- `download_hint` adds a line under the pack download.
- `pack_manual` is the manual part of the README inside the pack, in plain
text. Without it the README names the `bios_path` of the detection rules.
- `logo_owner` and `logo_licence` credit the registry's `logo`, read by
`scripts/fetch_site_images.py`.
The guide text is read by someone who knows their device and little else.
`summary` is one plain sentence, with no chip or board names. `notes` hold
one fact each that the reader acts on. A source citation, a list of models or
how the installer finds the folder goes in `reference_notes`, which open the
Reference part of the page. The guide part of every setup page is held to the
word budgets of [Pages for newcomers](testing-guide.md#pages-for-newcomers).
`scripts/siteguides.py` loads the file and stops the build with the key at
fault: a registered platform without a guide, a guide for no registered
platform, a misspelt key, an unknown terminal, a group the file does not
describe. `tests/test_site_content_data.py` also fails when a script holds a
table of text keyed by platform or a page branches on one platform's name:
that text belongs in a guide field.
### Optional fields
```yaml
@@ -634,6 +675,7 @@ Verification is not optional. A platform that passes `pipeline.py` today may bre
- [ ] `fetch_requirements()` and `validate_format()` implemented
- [ ] System ID mapping covers all upstream systems
- [ ] Entry added to `platforms/_registry.yml`
- [ ] Guide added to `platforms/_guides.yml`
- [ ] Platform YAML generated and verified
- [ ] `python scripts/pipeline.py --offline` passes
- [ ] Exporter in `scripts/exporter/<name>_exporter.py` (if applicable)
+1
View File
@@ -1,5 +1,6 @@
---
level: contribute
order: 30
---
# Adding a scraper
+1
View File
@@ -1,5 +1,6 @@
---
level: reference
order: 100
---
# Build your own packs
+1
View File
@@ -1,5 +1,6 @@
---
level: reference
order: 90
---
# Architecture
+1
View File
@@ -1,5 +1,6 @@
---
level: reference
order: 140
---
# Projects using this data
+2
View File
@@ -1,5 +1,7 @@
---
level: start
order: 50
nav_title: Common questions
---
# FAQ
+2
View File
@@ -1,5 +1,7 @@
---
level: start
order: 30
nav_title: First install, step by step
---
# First install
+1
View File
@@ -1,5 +1,6 @@
---
level: start
nav: false
---
# Getting started
+2
View File
@@ -1,5 +1,7 @@
---
level: start
order: 60
nav_title: Glossary
---
# Words used on this site
+1
View File
@@ -1,5 +1,6 @@
---
level: reference
order: 0
---
# Reference
+1
View File
@@ -1,5 +1,6 @@
---
level: explore
order: 30
---
# All installer options
+2
View File
@@ -1,5 +1,7 @@
---
level: explore
order: 40
nav_title: "Is it legal?"
---
# The project's legal position
+2
View File
@@ -1,5 +1,7 @@
---
level: contribute
order: 10
nav_title: Profiling an emulator
---
# Profiling guide
+2
View File
@@ -1,5 +1,7 @@
---
level: reference
order: 130
nav_title: Project terms
---
# Terms of the reference pages
+1
View File
@@ -1,5 +1,6 @@
---
level: contribute
order: 50
---
# Release process
+1
View File
@@ -1,5 +1,6 @@
---
level: reference
order: 120
---
# Technical questions
+31 -1
View File
@@ -1,5 +1,7 @@
---
level: contribute
order: 40
nav_title: Testing
---
# Testing guide
@@ -54,7 +56,7 @@ Every module in `tests/`, by the area it guards.
| Handheld port | stubbed PortMaster dialogs, fake installer | `test_port` |
| Truth and native export | synthetic + cached originals | `test_export_counts`, `test_export_native_layer`, `test_export_report`, `test_exporters`, `test_truth_data_dir_readers`, `test_truth_diff`, `test_truth_layout` |
| Scrapers, upstream and provenance | inline sources, synthetic | `test_check_freshness`, `test_dedup`, `test_elec_scrapers`, `test_fbneo_parser`, `test_find_pinned_revision`, `test_hash_merge`, `test_launchers`, `test_launchers_emudeck`, `test_launchers_recalbox`, `test_launchers_retrobat`, `test_launchers_retrodeck`, `test_launchers_retropie`, `test_launchers_rocknix`, `test_mame_devices`, `test_mame_parser`, `test_mame_ref_audit`, `test_profile_sync`, `test_provenance`, `test_refresh_data_dirs`, `test_refresh_failures`, `test_refresh_stale`, `test_retrodeck_scraper_errors`, `test_romset_recipes`, `test_scraper_contract`, `test_upstream`, `test_upstream_index` |
| Site, docs and repository contracts | rendered pages, sources | `test_contributing_text`, `test_coverage_cache`, `test_data_dir_refs`, `test_dataclass_defaults`, `test_doc_pages`, `test_doc_surfaces`, `test_optional_dependencies`, `test_prose_style`, `test_site_availability`, `test_site_copy`, `test_site_cores`, `test_site_emulator_page`, `test_site_exports`, `test_site_funnel`, `test_site_images`, `test_site_platform_hashes`, `test_site_render`, `test_site_system_links`, `test_site_validation`, `test_site_weight`, `test_site_write`, `test_validate_pr`, `test_validate_pr_flow`, `test_validate_pr_hashes`, `test_workflow_paths` |
| Site, docs and repository contracts | rendered pages, sources | `test_contributing_text`, `test_coverage_cache`, `test_data_dir_refs`, `test_dataclass_defaults`, `test_doc_pages`, `test_doc_surfaces`, `test_optional_dependencies`, `test_prose_style`, `test_site_availability`, `test_site_copy`, `test_site_content_data`, `test_site_cores`, `test_site_emulator_page`, `test_site_exports`, `test_site_funnel`, `test_site_images`, `test_site_platform_hashes`, `test_site_render`, `test_site_system_links`, `test_site_validation`, `test_site_weight`, `test_site_write`, `test_validate_pr`, `test_validate_pr_flow`, `test_validate_pr_hashes`, `test_workflow_paths` |
## Test architecture
@@ -362,6 +364,34 @@ and reads less on a phone. Facts a newcomer does not act on (legal analysis,
source lines, annotated runs) are kept, on the page one level down. To see
the numbers of every page, run `python -m tests.test_site_copy --report docs`.
### Adding a wiki page
A page in `wiki/` is published as soon as it exists, and its front matter
places it in the navigation. No Python changes.
```yaml
---
level: explore # its tab: start, setup, explore, reference or contribute
order: 35 # its place in the tab, the smallest first
nav_title: Save files # only when the menu names it otherwise than its heading
---
```
- `level` picks the tab and the label shown at the top of the page.
- `order` sorts the tab. Pages are spaced by ten, so a new page fits between
two without renumbering. The generated pages (systems, emulators, the gaps
and data pages) hold fixed places among them, set in `generate_mkdocs_nav`.
- `nav_title` is the menu label. Without it the menu shows the page's `# `
heading. It is not `title`, which both MkDocs and Astro Starlight read as
the page's own title.
- `nav: false` keeps a page out of the menu on purpose.
`getting-started.md` does, since it only links the pages that took its
content.
`python scripts/generate_site.py` stops with the page's name when `level` or
`order` is missing, or when two pages of a tab take the same `order`.
`tests/test_site_content_data.py` checks the same on every page in `wiki/`.
## Landing a change
A commit subject is English, 50 characters at most, `type: description` with a
+1
View File
@@ -1,5 +1,6 @@
---
level: reference
order: 110
---
# Command-line tools
+1
View File
@@ -1,5 +1,6 @@
---
level: start
order: 40
---
# When a game does not start
+1
View File
@@ -1,5 +1,6 @@
---
level: reference
order: 10
---
# How each platform checks files
+2
View File
@@ -1,5 +1,7 @@
---
level: start
order: 10
nav_title: What BIOS files are
---
# What is a BIOS?