Submit an issue View all issues Source
MIR-854

Add static site generator support to stackbuild

Open public
phinze phinze Opened Mar 23, 2026 Updated Apr 2, 2026

Summary

Stackbuild currently detects application frameworks (Rails, Django, FastAPI, Express, etc.) and generates build configurations for long-running server processes. Static site generators are a common class of project that stackbuild doesn't handle well today — they need a build step that produces static HTML/CSS/JS, then a lightweight file server to serve the output.

Proposed Approach

Add detection for common static site generators, with a shared build pattern:

  1. Detect the SSG framework from marker files / config
  2. Build using the framework's build command
  3. Serve the output directory with a minimal Go binary wrapping http.FileServer

Static file server

Most SSGs ship a serve command, but they're all explicitly dev-only (single-threaded, no compression, no caching headers). The production pattern is a real HTTP server (nginx, Caddy, etc.) serving the built output.

Since httpingress already handles TLS termination, routing, compression, and caching, the in-container server doesn't need any of that. A tiny Go binary (~50 lines) wrapping stdlib http.FileServer is sufficient:

  • Handles MIME types, range requests, If-Modified-Since out of the box
  • Optional SPA fallback routing (serve index.html for unmatched paths)
  • No new dependencies — fits naturally in the repo
  • No need to be battle-tested for the public internet since it never touches the internet directly

Frameworks to support

Framework Detection signal Build command Output dir
Hugo hugo.toml / hugo.yaml / config.toml with baseURL hugo public/
Jekyll _config.yml + Gemfile with jekyll jekyll build _site/
Eleventy (11ty) .eleventy.js / eleventy.config.* npx @11ty/eleventy _site/
MkDocs mkdocs.yml mkdocs build site/
Astro astro.config.* npm run build / bun run build dist/
Gatsby gatsby-config.* gatsby build public/
Docusaurus docusaurus.config.* npm run build build/
VitePress docs/.vitepress/config.* vitepress build .vitepress/dist/
Next.js (static export) next.config.* with output: 'export' npm run build out/
Nuxt (static) nuxt.config.* with static preset nuxt generate .output/public/

Design considerations

  • SSG detection should take priority over generic language detection — a repo with package.json + astro.config.mjs should be detected as Astro, not generic Node.js
  • Shared static serving layer — all SSGs produce static files, so the runtime image is the same regardless of which SSG built the site
  • Configurable output dir — support a convention for overriding the default output directory
  • Hybrid frameworks — Next.js, Nuxt, SvelteKit can be SSR or static depending on config; detection needs to distinguish these modes

Suggested phasing

  1. Phase 1: Hugo, Jekyll, Eleventy, MkDocs — pure SSGs with simple detection + the static file server binary
  2. Phase 2: Astro, Gatsby, Docusaurus, VitePress — JS-ecosystem SSGs (build on Node/Bun stacks)
  3. Phase 3: Next.js/Nuxt/SvelteKit static export detection — hybrid framework support