Add a new rules reference topic to the unified rules lookup feature from a remote markdown source.
ultrathink
Add a new rules topic to the unified rules lookup: $ARGUMENTS
All rules topics share a single route (/rules), a single floating button, a single sidebar, and a single search. Adding a new topic means extending the existing config and hook — not creating new layouts, routes, or entry points.
Read every file listed below before writing any code. These are the source of truth.
Config & Types:
src/configs/draw_steel_config.ts — all config maps (sources, anchors, labels, groups, children, project levels)src/types/draw_steel_rules.ts — RulesSection and RulesProject interfaces (shared, do not duplicate)Data Hook:
src/hooks/use_draw_steel_rules.tsx — fetches all sources in parallel, parses markdown, assigns project IDs, returns accessor functionsLayout (generalized, shared by all topics):
src/components/rules/rules_lookup_layout.tsx — RulesLookupConfig and RulesLookupData interfaces, header + sidebar + content areasrc/pages/rules/rules_layout.tsx — thin wrapper passing Draw Steel config to RulesLookupLayoutPage Components (shared, reused for all topics):
src/pages/rules/rules_page.tsx — branching router: loading → error → empty → project detail → project index → child page (with back link) → single page (with optional sub-page links)src/pages/rules/rules_section_list.tsx — renders RulesSection[] with heading + markdown + hash scrollsrc/pages/rules/rules_project_index.tsx — intro sections + clickable project card linkssrc/pages/rules/rules_project_detail.tsx — back link + project sectionsSidebar & Search (shared):
src/components/rules/rules_sidebar.tsx — grouped pages with section headers, nested child pages, project sub-links, exit button with sessionStorage origin trackingsrc/components/rules/rules_search.tsx — search with breadcrumbs, snippets, project-aware navigationsrc/components/rules/rules_markdown.tsx — styled markdown rendererEntry Point & Routes:
src/components/rules_book_button.tsx — single floating button, stores origin in sessionStorage, navigates to /rules/project-overviewsrc/navigation/routes.tsx — single /rules route with :page_key and :page_key/:project_id childrensrc/configs/constants.tsx — nav_paths.rules = /rulesFetch the markdown URL and analyze its structure:
### through ######) and what each level represents._ (e.g., _example_tests) so they're parsed but not shown in the sidebar.Document findings before writing any code.
Edit src/configs/draw_steel_config.ts — add entries to the existing maps:
Add a new entry to the array:
const RULES_SOURCES = [
// ... existing sources
{
url: "https://raw.githubusercontent.com/.../NewChapter.md",
default_page: "new-default-page",
},
]
The default_page is the page_key assigned to sections before the first anchor heading is encountered in this source.
Add mappings from UPPERCASE heading text to page_key for every heading that should switch the current page context:
const ANCHOR_HEADINGS: Record<string, string> = {
// ... existing entries
"NEW TOPIC HEADING": "new-page-key",
}
Key rules:
_ (e.g., "UNWANTED SECTION": "_hidden")Add display labels for every new page_key:
const PAGE_LABELS: Record<string, string> = {
// ... existing entries
"new-page-key": "Display Label",
}
Add a new group or extend an existing one. Groups define sidebar section headers:
const PAGE_GROUPS: PageGroup[] = [
// ... existing groups
{ label: "New Group Name", keys: ["page-a", "page-b", "page-c"] },
]
The keys array determines sidebar order within the group. Only include top-level pages here — child pages are listed in PAGE_CHILDREN instead.
If some pages should be nested under a parent page in the sidebar:
const PAGE_CHILDREN: Record<string, string[]> = {
// ... existing entries
"parent-page": ["child-a", "child-b", "child-c"],
}
Behavior:
PAGE_GROUPS.keys — they're only listed in PAGE_CHILDRENIf a page contains discrete items that should each get their own sub-page (index + detail views):
const PROJECT_LEVELS: Record<string, number> = {
// ... existing entries
"new-page": 4, // h4 headings define projects on this page
}
Behavior when set:
/rules/page-key/project-idThe hook at src/hooks/use_draw_steel_rules.tsx automatically:
RULES_SOURCES in parallel via Promise.allparse_markdown(text, source.default_page)assign_project_ids() on the combined flat arrayNo hook changes needed unless the new markdown source requires different parsing (e.g., different heading levels, closing hashes, etc.). If so, adjust parse_markdown().
The heading regex /^(#{3,6})\s+(.+)/ skips # and ## levels by default. If the source uses those meaningfully, adjust the regex.
All page components, sidebar, search, and layout are fully generalized:
RulesPage branches on: project_id param + has_sub_pages() + find_parent() + page_childrenRulesSidebar reads PAGE_GROUPS, PAGE_CHILDREN, and project data to render the full nav treeRulesSearch uses base_path, page_labels, and project_id to build correct URLs and breadcrumbsRulesLookupLayout orchestrates header, sidebar, and content area with mobile responsivenessif (loading) → spinner
if (error) → error message
if (no sections) → empty state
if (project_id && has_sub_pages) → RulesProjectDetail (back link + sections)
if (has_sub_pages) → RulesProjectIndex (intro + project card links)
if (find_parent) → back link to parent + sections
else → sections + optional child page card links
Pages automatically render clickable card-style links to their sub-items within the content area:
PROJECT_LEVELS): After intro sections, a grid of card links appears — one per project. Each links to /rules/page-key/project-id. Styled as gold-text cards with subtle border on dark background.PAGE_CHILDREN): After the page's section content, a grid of card links appears — one per child page. Each links to /rules/child-key. Same card styling as project cards.This means users can navigate to sub-items both from the sidebar AND from within the page content itself.
The existing route structure handles all topics:
{
path: nav_paths.rules, // "/rules"
element: <RulesLayout />,
children: [
{ index: true, element: <Navigate to="project-overview" replace /> },
{ path: ":page_key", element: null },
{ path: ":page_key/:project_id", element: null },
]
}
If the new topic should be the default landing page, update the index redirect.
The single floating button at src/components/rules_book_button.tsx:
sessionStorage("rules_entry_origin") before navigating/rules/project-overview (the default page)/rules| Type | Config | URL | Content |
|---|---|---|---|
| Single page | page_key in PAGE_GROUPS.keys, not in PROJECT_LEVELS or PAGE_CHILDREN | /rules/page-key | All sections rendered with optional child page links at bottom |
| Project index | page_key in PROJECT_LEVELS | /rules/page-key | Intro sections + clickable project card grid |
| Project detail | (navigated from index) | /rules/page-key/project-id | Back link + project's sections |
| Parent page | page_key in PAGE_CHILDREN keys | /rules/page-key | Sections + child page card links at bottom |
| Child page | page_key in PAGE_CHILDREN values | /rules/child-key | Back link to parent + sections |
| Hidden page | page_key starts with _, not in PAGE_GROUPS | (not navigable) | Content parsed but not shown |
npm run build — zero errorsPROJECT_LEVELS: index shows intro + project cards, detail shows project content, back link worksPAGE_CHILDREN: parent shows child links at bottom, children show back link to parent, sidebar nests children under parent