Add static site generator support to stackbuild
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:
- Detect the SSG framework from marker files / config
- Build using the framework's build command
- 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.htmlfor 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.mjsshould 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
- Phase 1: Hugo, Jekyll, Eleventy, MkDocs — pure SSGs with simple detection + the static file server binary
- Phase 2: Astro, Gatsby, Docusaurus, VitePress — JS-ecosystem SSGs (build on Node/Bun stacks)
- Phase 3: Next.js/Nuxt/SvelteKit static export detection — hybrid framework support