Shared components, layouts, shortcodes, theme, and build tooling for NukeHub documentation sites.
- Astro layouts:
BaseLayout,DocLayout - Docs components:
TableOfContents,Pagination,EditLink,NotFound - React components: header, footer, sidebar, command palette, theme toggle, search, scroll progress, context menu, lightbox
- UI primitives:
Button,Input,Label,Textarea,Checkbox,RadioGroup,Select,Switch,Combobox,MultiSelect,Slider,TimePicker,Calendar,DateRangePicker,Modal,Dialog,ConfirmDialog,SearchInput,Badge,Skeleton,Toast,Toaster - MDX shortcodes:
Callout,Tabs,TabItem,FileTree,Mermaid,Steps,Step,YouTube,Odysee,ImageFigure,SvgFigure,DataTable,Citation - Opt-in interactive shortcodes:
PlotlyandModel3D(requires installingplotly.jsandthree, then passing the components toDocLayoutviamdxComponents) - Theme: Tailwind CSS v4 tokens, dark/light/system mode, accent-color picker, and global styles. The favicon and theme-color meta tag follow the selected accent.
- Utilities:
cn, sidebar/pagination helpers, theme helpers - Build integration:
markdownNegotiationemits a Markdown sibling for every HTML page - Sync CLI:
nukehub-sync-docscopies and cleans docs from../docs/intosrc/content/docs/, rewriting Markdown links and injecting frontmatter (includingeditPath, the repo-relative source path used byEditLink— declareeditPath: z.string().optional()in your docs collection schema)
npm install @nukehub/docs-kit-
Create a fresh Astro project or use the
docs-templaterepo as a starting point. -
Add project-specific files:
src/ ├── content.config.ts ├── data/ │ ├── site.ts │ ├── nav.ts │ └── footer.ts ├── env.d.ts └── pages/ ├── [...slug].astro └── 404.astro -
Import layouts from the kit:
--- import DocLayout from "@nukehub/docs-kit/components/layout/DocLayout.astro"; import BaseLayout from "@nukehub/docs-kit/components/layout/BaseLayout.astro"; ---
Pass your
site,navItems,footerColumns, andfooterLegalas props toDocLayoutandBaseLayout. -
Add
astro.config.mjsusing the kit'smarkdownNegotiationintegration and@tailwindcss/vite. -
Add docs under
docs/and runnpx nukehub-sync-docs.
The kit generates a dynamic, theme-aware favicon so the tab icon matches the user's selected accent and resolved light/dark mode.
- Place a
favicon.svgin your project'spublic/directory. It is used as the no-JS fallback. - When JavaScript runs, the kit replaces it with a data-URI SVG colored from the current
--primaryCSS variable. - The dynamic favicon uses the built-in NukeHub logo paths. To use a custom logo dynamically, pass
faviconPathsin yourSiteConfig. The string should contain SVG elements that usefill="currentColor"/stroke="currentColor"so the kit can tint them with the selected accent. IffaviconPathsis omitted, the default NukeHub logo is used.
Use the NotFound component for a themed 404 page:
---
import BaseLayout from "@nukehub/docs-kit/components/layout/BaseLayout.astro";
import NotFound from "@nukehub/docs-kit/components/docs/NotFound.astro";
---
<BaseLayout site={SITE} navItems={navItems} title={`404 — Page not found | ${SITE.name}`}>
<NotFound base={SITE.base} />
</BaseLayout>SvgFigure inlines an SVG from your public/ directory at build time instead of
rendering it as an <img>, so currentColor and CSS custom properties inside
the SVG follow the site theme. Use it for hand-authored figures that use theme
tokens (currentColor, var(--muted), var(--muted-foreground)); keep
ImageFigure for raster images and opaque external SVGs. The build fails with a
clear error if the file is missing or is not an SVG.
If the SVG carries a root <title>, SvgFigure hoists it out of the markup
(left in place it would trigger the browser-native hover tooltip) and shows it
in the kit's styled Tooltip from a small info button in the figure's corner.
The same text becomes the figure's accessible name unless alt overrides it.
<SvgFigure
src="/theory/figures/peak-anatomy.svg"
alt="Spectrum peak with the c1..c2 window and sideband background"
caption="Sideband sums set the background under the peak window."
/>Props:
src(required): root-relative path into the consumer'spublic/directory, e.g./theory/figures/peak-anatomy.svg.caption(optional): rendered in a<figcaption>bar under the figure.alt(optional): accessible label for the figure; defaults to the SVG's own<title>, which is hoisted into the info-button tooltip either way.className(optional): extra classes merged onto the<figure>.
The kit also provides Plotly and Model3D shortcodes, but they are not enabled by default because they pull in large runtime dependencies.
To use them:
-
Install the optional peer dependencies in the consumer project:
npm install plotly.js three npm install -D @types/plotly.js @types/three
Plotlyloads a partial Plotly bundle (~1 MB vs ~4.4 MB for the full dist): only the scatter, bar, heatmap, and histogram trace types are registered. Charts using any other trace type fail at render time. The Plotly CJS modules reference Node'sglobal, so the consumer'sastro.config.mjsmust shim it:export default defineConfig({ vite: { define: { global: "globalThis" } }, // ... });
-
Import the shortcodes and pass them to
DocLayout:--- import DocLayout from "@nukehub/docs-kit/components/layout/DocLayout.astro"; import Plotly from "@nukehub/docs-kit/components/mdx/shortcodes/Plotly.astro"; import Model3D from "@nukehub/docs-kit/components/mdx/shortcodes/Model3D.astro"; --- <DocLayout ... mdxComponents={{ Plotly, Model3D }} />
-
Use them in
.mdxfiles:<Plotly data={[{ x: [1, 2, 3], y: [1, 4, 9], type: "scatter", mode: "lines+markers" }]} layout={{ title: "Sample chart" }} /> <Model3D src="/models/example.glb" caption="A sample 3D model." />
Both components dynamically load their runtime libraries and only render on the client.
Docs can declare references in frontmatter and cite them inline. DocLayout renders a linked bibliography automatically and offers copy-to-clipboard exports in plain text, BibTeX, and RIS.
-
Add a
referencesarray to your content schema (the shape is exported from@nukehub/docs-kit):import { z } from "zod"; import type { Reference } from "@nukehub/docs-kit"; const docs = defineCollection({ loader: glob({ pattern: "**/*.{md,mdx}", base: "./src/content/docs" }), schema: z.object({ title: z.string(), references: z .array( z.object({ id: z.string(), title: z.string(), url: z.string().url(), source: z.string().optional(), date: z.string().optional(), authors: z.array(z.string()).optional(), type: z.enum(["article", "book", "inproceedings", "techreport", "misc"]).optional(), publisher: z.string().optional(), doi: z.string().optional(), arxiv: z.string().optional(), journal: z.string().optional(), volume: z.string().optional(), issue: z.string().optional(), pages: z.string().optional(), }), ) .default([]), }), });
-
Pass the references to
DocLayout:--- import DocLayout from "@nukehub/docs-kit/components/layout/DocLayout.astro"; --- <DocLayout doc={doc} headings={headings} allDocs={allDocs} site={SITE} navItems={navItems} footerColumns={footerColumns} footerLegal={footerLegal} references={doc.data.references} />
-
Declare references in frontmatter and cite them in the MDX body:
--- title: Nuclear data references: - id: openmc-docs title: OpenMC Documentation url: https://docs.openmc.org/ source: OpenMC Development Team date: "2023" --- OpenMC uses continuous-energy nuclear data<Citation id="openmc-docs" />.
For custom layouts, import References directly from @nukehub/docs-kit/components/mdx/shortcodes/References.
When the kit improves, pull the latest version in any consuming project:
npm update @nukehub/docs-kitNo need to copy files or cherry-pick template changes.
docs-template— reference consumer of this kit.