Astrolabe / ajxpublic /astrolabe
Repository

Astro Theme & Site Rendering

reference scope theme Verification failed
  • theme/src/lib/bundle.ts
  • PageEntry
  • IndexManifest
  • NavGroup
  • ParsedPage
  • theme/src/scripts/site.ts
  • theme/src/components/GraphExplorer.svelte
  • theme/src/layouts/BaseLayout.astro
  • theme/src/pages/pages/[slug].astro
Relevant source files · 6

The theme/ directory is the Astro site that turns an astrolabe wiki bundle — a directory of markdown pages plus index.json and version.json produced by the wiki writer — into a static, browsable website. It is deliberately thin: all rendering happens at build time from plain files, and the browser only ever receives static markup that a small client script enhances with the design system's widget bundle. Nothing in bundle.ts ships to the browser; it exists purely for getStaticPaths and frontmatter code Design note.

Reading the bundle at build time

Everything the theme knows about the wiki comes from theme/src/lib/bundle.ts. The bundle location is resolved from the BUNDLE_DIR environment variable (defaulting to ../bundle) by bundleDir() bundleDir, and readIndex() parses index.json into an IndexManifest — the repo identity, generation metadata, and the canonical ordered list of PageEntry records readIndex. Each PageEntry carries the slug, title, type (overview | reference | guide), scope, documented symbols, citation count, and verification status PageEntry; the verification badge on every rendered page comes straight from this field.

Two derived helpers drive the site chrome. navGroups() builds the sidebar structure: overview pages sit at the top level, every other type becomes a numbered group (2 Reference → 2.1 …), ordered by the fixed TYPE_ORDER of overview, reference, guide navGroups. And readRepo() recovers repository identity in a slightly clever way: the bundle has no repository URL of its own, so readRepo scans the rendered pages for the first source-host blob citation link (GitHub /blob/<ref>/ or GitLab /-/blob/<ref>/), extracts owner, name, and host from it, and caches the result readRepo.

Markdown rendering

theme/src/lib/markdown.ts turns each bundle page's markdown into HTML at build time. parsePage handles frontmatter with gray-matter, body with marked, and produces a ParsedPage: frontmatter data, rendered HTML, h2/h3 headings in document order (for the "On this page" column), and the list of SourceFiles cited by the page ParsedPage. A link-rewrite pass maps bundle-relative targets onto site routes — <slug>.md becomes /pages/<slug>/, src/<path> becomes /src/<path>, while http(s), mailto, and absolute links pass through unchanged rewriteHref. The renderer emits the design system's own markup conventions — heading ids matching what Astrolabe.Prose.slug would produce, code fences as CodeBlock figures, mermaid fences as MermaidViewer figures — so the statically rendered ToC and client enhancement agree Rendered markup.

The page frame

BaseLayout.astro is the frame every page renders into: sticky SiteHeader, left SiteNav, article, and right-hand ToC, all static markup that design/bundle.js enhances on load Layout overview. It pulls the manifest, repo info, and version info from bundle.ts, builds the nav from navGroups, and nests h3 headings under their preceding h2 for the ToC Layout data assembly. Three notable details:

  • An inline script applies the stored theme (astrolabe:theme in localStorage, with a one-time migration from the old astrolabe-theme key) before first paint, falling back to prefers-color-scheme / contrast media queries — the inline equivalent of Astrolabe.ThemeSelector.init() theme initialization script.
  • The header wires up the search button (data-al-search, revealed once the Pagefind index answers), the version and theme selector mounts (data-al-version, data-al-theme), and a breadcrumb built from the repo info recovered by readRepo Header actions.
  • The <article> carries data-pagefind-body only when indexed is set, so only wiki pages enter the search index Article element.
  • The nav's Resources section is conditional on bundle contents: the "Symbol graph" link only appears when graph.json exists, checked with hasFile Nav resources.

Page routes

theme/src/pages/pages/[slug].astro is the route that renders every wiki page. Its getStaticPaths lists the bundle's pages/*.md files and runs each through parsePage, passing slug, frontmatter data, HTML, headings, and cited sources as props getStaticPaths. The template then renders the page header — title, type and scope badges, a verification badge driven by the manifest's verification field, and symbol chips — followed by a collapsible "Relevant source files" list built from the cited SourceFiles, with line ranges rendered en-dash-separated and capped at four entries per file Page metadata and source list. Finally it injects the rendered HTML and computes prev/next links from the manifest's canonical order (overview first, then scope order), falling back to the index page when there is no previous page Prev/next nav.

A separate theme/src/pages/graph.astro renders the interactive symbol graph using GraphExplorer.svelte as a full-width island — the only Svelte component in the theme — while ordinary pages remain pure static HTML GraphExplorer usage.

Client-side enhancement

theme/src/scripts/site.ts is the single client entry point. It runs after BaseLayout has loaded the design system's bundle as a classic script, reads site metadata out of the al-site JSON element the layout serialized, and then runs three steps: A.enhance() wires up all the design system's [data-al-*] widgets, mountVersions() mounts the version selector, and mountDiagrams() lazily loads Mermaid Enhancement entry point.

The version selector is resilient to how the site was deployed: it tries fetch('/versions.json') (assembled by the deploy pipeline for multi-version sites), normalizes both the design system's Version shape and a legacy shape through toVersion, and — when there is no versions file — synthesizes a single entry from the bundle's own commit and tag so the SHA is always visible mountVersions. Diagram mounting is lazy by design: it only queries figure.al-diagram[data-al-mermaid] elements, returns early when there are none, and dynamically imports the mermaid package just for those pages; on failure the figures stay unmounted so the raw Mermaid source remains readable mountDiagrams.

Relationships

graph TD
    subgraph "Bundle (build input)"
        IDX["index.json"]
        PAGES["pages/*.md"]
        VERSION["version.json"]
    end
    subgraph "theme build time"
        BUNDLE["`theme/src/lib/bundle.ts`"]
        MARKDOWN["`theme/src/lib/markdown.ts`"]
        SLUG["`theme/src/pages/pages/[slug].astro`"]
        GRAPH["`theme/src/pages/graph.astro`"]
        LAYOUT["`theme/src/layouts/BaseLayout.astro`"]
    end
    subgraph "client"
        SITE["`theme/src/scripts/site.ts`"]
        DESIGN["design/bundle.js (window.Astrolabe)"]
        EXPLORER["`theme/src/components/GraphExplorer.svelte`"]
    end
    IDX --> BUNDLE
    VERSION --> BUNDLE
    BUNDLE --> LAYOUT
    PAGES --> MARKDOWN
    MARKDOWN --> SLUG
    SLUG --> LAYOUT
    LAYOUT --> SITE
    SITE --> DESIGN
    GRAPH --> LAYOUT
    GRAPH --> EXPLORER

Reference

Symbol Kind What it does Location
bundle.ts file Build-time readers for the bundle directory (index, version, repo, nav) theme/src/lib/bundle.ts
PageEntry interface One wiki page's manifest record: slug, title, type, scope, symbols, verification theme/src/lib/bundle.ts
IndexManifest interface Root of index.json: repo identity, generation metadata, ordered pages theme/src/lib/bundle.ts
NavGroup interface Sidebar entry: numbered page or labeled group with numbered children theme/src/lib/bundle.ts
ParsedPage interface Result of rendering one page: data, HTML, headings, cited source files theme/src/lib/markdown.ts
site.ts file Client entry: A.enhance(), version selector, lazy Mermaid mounting theme/src/scripts/site.ts
GraphExplorer.svelte file Interactive symbol graph island, mounted by the graph page theme/src/components/GraphExplorer.svelte
BaseLayout.astro file Site frame: header, nav, article, ToC, theme bootstrapping theme/src/layouts/BaseLayout.astro
[slug].astro file Wiki page route: static paths, page metadata, source list, prev/next theme/src/pages/pages/[slug].astro

Generated by astrolabe from commit ecc180b3 (tag 0.4.0).