Skip to content

Standardize a docs-site stack for pack templates: Hugo vs Astro vs Docusaurus #14

Description

@viniciusdc

Summary

We don't currently scaffold a docs site in this template: packs inherit a long README and three reference markdowns under docs/. As more packs ship and we want a consistent "Nebari pack" presentation, we need to pick a static site generator (SSG) and bake it into the template so that every new pack starts with the same shape.

The current state of the art across our repos is inconsistent:

Repo Docs stack
nebari-dev/nebari-docs Docusaurus
nebari-dev/nebari-nebi-pack Docusaurus
nebari-dev/skillsctl Custom site, without Nebari theming
Every other pack (incl. provenance-collector) README only — no docs site

This issue captures the comparison and trade-offs from a recent design discussion, so the team (and future template consumers) can see how the choice was reached and what's still open.

Constraints we're working under

The decision is mostly determined by how nebari-dev/nebari-design is distributed. After looking at it in depth:

  • It's a shadcn/ui-style registry, not a published npm package ("private": true in package.json).
  • Components are TSX source under registry/nebari/ui/, built on React 19 + Base UI primitives + Tailwind v4 + lucide-react + class-variance-authority + tailwind-merge.
  • Consumers integrate via bunx shadcn add <component> — which copies the React source into the consumer's repo. There's no CDN bundle, no compiled UMD, no web-component wrappers.
  • The CSS tokens (registry/nebari/globals.css) are Tailwind v4 @theme declarations: light + dark, semantic naming (background / foreground / primary / etc.), OKLCH colors. These are framework-agnostic as long as your build runs Tailwind v4.
  • The repo's own build:pages script ships Storybook + the registry to GitHub Pages, so the integration model is "consumers fetch from a hosted registry."

Two implications follow:

  1. Any docs site that wants to use nebari-design components needs React + Tailwind v4 + TypeScript in its build. There's no escape hatch — the components don't exist as a pre-compiled bundle that you can <script src> into HTML.
  2. Any docs site that wants nebari-design's colors / typography / spacing needs Tailwind v4 in its build, because the tokens are Tailwind v4 @theme declarations.

So the practical question is "which SSG fits a Tailwind-v4-plus-shadcn-React design system most naturally?"

Hosting policy

The org runs two different deploy targets depending on the docs site's scope:

  • nebari.dev (the main docs, currently Docusaurus) lives on Netlify. Netlify earns its keep there: deploy previews on every PR, redirects, custom-domain wiring, larger build budget — the long-lived flagship docs need that.
  • Pack docs sites should default to GitHub Pages. Reasons:
    • One workflow file per repo; no separate Netlify project or dashboard to manage per pack.
    • No subscription / build-minutes dependency. Public-repo gh-pages is free and scales horizontally to N packs.
    • Each pack gets a predictable URL (<org>.github.io/<repo> or a custom domain) without org-level coordination.
    • Avoids the "who pays for the Netlify account when a pack maintainer is no longer on the team" footgun.

This is a default, not a constraint — an individual pack maintainer can migrate their pack's docs to Netlify if they have a genuine need (deploy previews on PRs, large traffic, redirect rules). But the template scaffolding should ship a gh-pages workflow as the out-of-the-box path.

All three SSGs we're comparing deploy to gh-pages cleanly via the standard actions/upload-pages-artifact + actions/deploy-pages chain, so this constraint doesn't break the tie between them — but it does shape the workflow shape we'll bake into the template, and it's worth surfacing here so reviewers don't assume Netlify everywhere.

Options

Hugo

  • Pros: blazing-fast builds (Go binary), single tool, simple authoring (markdown + frontmatter + occasional shortcodes), team has prior experience (Chuck + others). Native gh-pages deploy via the official action. Themes like Doks / Geekdoc / Hextra are technical-docs-friendly.
  • Cons against nebari-design: needs a Tailwind v4 build step bolted on via Hugo Pipes + PostCSS, so the "no Node in CI" advantage evaporates the moment we import globals.css. Cannot consume shadcn components at all without us writing per-component web-component shims and re-publishing them — a maintenance liability that grows with nebari-design.
  • Fit verdict: clean for pack docs that want visual identity without runtime components. Forces a parallel build pipeline if we ever want to ship an interactive widget.

Astro

  • Pros: purpose-built for "mostly static markdown, with islands of interactive components." Native React + Tailwind v4 + MDX. Can consume the shadcn registry directlybunx shadcn add button inside an Astro pack's docs/ lands the same TSX the rest of Nebari uses. Static-by-default like Hugo; same gh-pages workflow shape. Components hydrate only on pages that use them, so markdown pages stay pure HTML.
  • Cons: Node + a bundler in CI (but we're paying that anyway for Tailwind v4). Team has less institutional experience than Hugo. Versioning / search / i18n need to be assembled from parts (Pagefind for search, branch-based versioning, etc.) — not built-in like Docusaurus.
  • Fit verdict: lowest-friction option for the nebari-design integration specifically. Marginal cost over Hugo is small once you accept Tailwind v4 in the toolchain.

Docusaurus

  • Pros: already proven in nebari-docs and nebari-nebi-pack. Native React + MDX. Versioning, search, i18n, blog, plugins all built-in. Maintainers across the org already know the authoring conventions.
  • Cons: heavier runtime than Astro for similar React-native capability. Theming is more opinionated; aligning with nebari-design's Tailwind v4 tokens fights Docusaurus's own theming layer somewhat. Larger bundles = slower first paint than Hugo or Astro.
  • Fit verdict: correct choice for the deep, long-lived nebari-docs site. For a thin pack-docs scaffold that ships in every pack template, heavier than necessary.

Tradeoff at a glance

Hugo Astro Docusaurus
Tailwind v4 (tokens) Add via Hugo Pipes + PostCSS Native Native (but fights theme layer)
Shadcn component adoption Custom-element shim per component bunx shadcn add works directly bunx shadcn add works directly
First paint Lowest (no JS) Low (islands hydrate only where used) Medium (SSR + hydration of React shell on every page)
CI weight Hugo binary + Node + Tailwind Node + bundler Node + bundler
Versioning / search / i18n DIY DIY (lightweight) Built-in
Team familiarity High (Chuck + others) Medium (some experience) High (nebari-docs incumbent)
Authoring Markdown + Hugo shortcodes Markdown / MDX + Astro components MDX
Migration story for existing Docusaurus packs Re-author Re-author None (already there)
gh-pages workflow fit (org default for packs — see "Hosting policy" above) Native; standard upload-pages-artifact action Native; standard upload-pages-artifact action Native; docusaurus deploy or upload-pages-artifact. Main docs on Netlify is org-policy, not a tool limit.

Recommendation

Astro for pack docs, deployed to gh-pages, consuming nebari-design via shadcn add.

Reasoning:

  1. The moment a pack imports nebari-design/registry/nebari/globals.css to get the visual identity, we need Tailwind v4 in the build. Hugo's "no Node toolchain" advantage stops being an advantage at that point.
  2. The shadcn distribution model is fundamentally React-native. Astro consumes it with zero adapter code. Hugo would require a web-component shim layer that we'd maintain forever. That asymmetry is large enough to overrule team-familiarity arguments.
  3. Astro is also lighter than Docusaurus for the same React capability, leaving nebari-docs (Docusaurus) as the heavy / long-lived docs site and packs as fast / lightweight satellites. Clean mental model: "deep docs = Docusaurus, pack docs = Astro."

Hugo stays defensible if the team decides pack docs explicitly don't need to consume nebari-design components — only its visual identity, hand-replicated in vanilla CSS. That's a valid simplification but it means the design library's value proposition stops at pack docs.

Docusaurus stays defensible as the choice for any individual pack that wants the nebari-docs feature set (versioning / search / i18n). New packs can opt in if they need it; the template default doesn't force them.

Proposed next step

Spike a minimal Astro docs site in provenance-collector to prove the integration end-to-end.

If it lands well, the skeleton graduates into this template as docs/site/ (or similar) and every future pack gets it for free via "Use this template."

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    Priority

    None yet

    Start date

    None yet

    Target date

    None yet

    Size

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions