Menu
AkurAI-Build
publicLatest change 1c2159692a31765cd66ed709791ba11468054873 - Initial commit: bunfork v0.1.0 source tree by Olafur Bui
## Verdict
Next.js confirms pass 3’s conclusion: the smallest honest cross-ecosystem contract is one immutable static-artifact format, not framework compatibility.
> Bunfork may host validated, prebuilt browser artifacts produced by official static-export configurations. It does not build, execute, or emulate framework source or server output.
Next explicitly distinguishes static export (“limited” support) from Node/Docker deployments (“all” features) ([deploying.mdx](/home/olafurbui/bunfork/.refrepos/nextjs/docs/01-app/01-getting-started/17-deploying.mdx:6)). With `output: 'export'`, `next build` emits an `out` directory containing HTML/CSS/JS assets ([static-exports.mdx](/home/olafurbui/bunfork/.refrepos/nextjs/docs/01-app/02-guides/static-exports.mdx:10)). App Server Components run at build time; static Route Handlers may emit files, but only `GET` is supported ([static-exports.mdx](/home/olafurbui/bunfork/.refrepos/nextjs/docs/01-app/02-guides/static-exports.mdx:43), [static-exports.mdx](/home/olafurbui/bunfork/.refrepos/nextjs/docs/01-app/02-guides/static-exports.mdx:193)).
### Unified artifact contract
Use pass 3’s proposed `bunfork-static-v1`:
```json
{
"format": "bunfork-static-v1",
"root": ".",
"mode": "mpa | spa",
"base": "",
"fallback": null,
"trailing_slash": "ignore | redirect | directory",
"precompressed": true,
"immutable": true
}
```
For Next exports:
- Admit only the contents of the configured export directory (`out`, or configured `distDir`), plus this manifest.
- Require a real, immutable artifact root. Reject symlinks, traversal, hidden segments, device files, and files escaping the root.
- Permit HTML, CSS, JavaScript, WASM, images, fonts, JSON, source maps, and other ordinary static files. Browser code is copied and served, never executed by Bunfork.
- Require `base` to be explicit and reject requests outside it. Next’s `basePath` affects routing and generated asset/data URLs; it is not equivalent to `assetPrefix`, which is intended for CDN assets ([next-routing/resolve-routes.ts](/home/olafurbui/bunfork/.refrepos/nextjs/packages/next-routing/src/resolve-routes.ts:237), [static-exports.mdx](/home/olafurbui/bunfork/.refrepos/nextjs/docs/01-app/02-guides/static-exports.mdx:18)).
- Resolve `/` to `index.html`, `/a/` to `a/index.html`. Do not invent `.html` mappings. Next documents `trailingSlash: true` as changing `/me` to `/me/` and emitting `/me/index.html` ([static-exports.mdx](/home/olafurbui/bunfork/.refrepos/nextjs/docs/01-app/02-guides/static-exports.mdx:18)).
- Support `GET` and `HEAD`; return `405` plus `Allow` for other methods. `HEAD` must preserve GET status and headers without a body.
- In MPA mode, missing pages return `404`; use an explicit `404.html` when present.
- In SPA mode, apply the declared fallback only after normal file lookup fails, never for missing assets or API-like paths.
- Serve negotiated `.br`/`.gz` variants only when advertised, with `Vary: Accept-Encoding`.
- Apply long immutable caching only to content-addressed or clearly hashed static assets. HTML, fallback, and error documents must be revalidated or non-cacheable. This is consistent with Next tests asserting immutable cache headers for static assets ([base-path-static.test.ts](/home/olafurbui/bunfork/.refrepos/nextjs/test/e2e/next-image-legacy/base-path/base-path-static.test.ts:62)).
- Preserve bytes. Do not rewrite HTML, inject scripts, interpret RSC payloads, or infer framework routes.
- Generate and verify a digest/file manifest before binding.
### Sharp rejection boundary
Reject `output: 'standalone'`, `.next/standalone`, `.next/server`, `server.js`, Node dependencies, and `.nft.json` traces. Standalone is a minimal Node production deployment containing traced dependencies and a generated server; it must be started with Node and does not include `public` or `.next/static` unless copied separately ([output.mdx](/home/olafurbui/bunfork/.refrepos/nextjs/docs/01-app/03-api-reference/05-config/01-next-config-js/output.mdx:9), [output.mdx](/home/olafurbui/bunfork/.refrepos/nextjs/docs/01-app/03-api-reference/05-config/01-next-config-js/output.mdx:28)). The official Docker example confirms that it launches the standalone server ([next.config.ts](/home/olafurbui/bunfork/.refrepos/nextjs/examples/with-docker/next.config.ts:1), [Dockerfile](/home/olafurbui/bunfork/.refrepos/nextjs/examples/with-docker/Dockerfile:33)).
Also reject:
- SSR, ISR, dynamic rendering, RSC server responses, streaming, middleware/proxy, rewrites, redirects requiring request logic, API routes, non-`GET` Route Handlers, server actions, cookies, headers, authentication, and runtime environment access.
- Dynamic routes not fully materialized by `generateStaticParams` or `getStaticPaths`.
- Any artifact whose behavior depends on Bunfork’s database, secrets, Rust handlers, or a server-side JS runtime.
- Manifest claims that cannot be verified from the files.
Next’s adapter output model makes this distinction explicit: with `config.output === 'export'`, only `outputs.staticFiles` is populated; pages, API routes, app routes, and prerenders are empty ([output-types.mdx](/home/olafurbui/bunfork/.refrepos/nextjs/docs/01-app/03-api-reference/07-adapters/09-output-types.mdx:9)). That is the admission rule: static files only.
### Current Bunfork mismatch
Current Bunfork is not yet this host:
- Startup requires SQLCipher, migrations, database key, and API token ([src/main.rs](/home/olafurbui/bunfork/src/main.rs:213)).
- It scans MiniJinja `.html` pages and renders them dynamically rather than serving exported files ([src/server.rs](/home/olafurbui/bunfork/src/server.rs:188), [src/server.rs](/home/olafurbui/bunfork/src/server.rs:376)).
- It has fixed `/assets` routing and no base-path, file-index, SPA-fallback, artifact-cache, or static-export manifest semantics ([src/server.rs](/home/olafurbui/bunfork/src/server.rs:198)).
- Deployment copies Bunfork’s own `app/pages` and `public`, not a framework export ([src/main.rs](/home/olafurbui/bunfork/src/main.rs:365)).
Thus Next static-export hosting remains a future contract, not a current capability.
### Black-box fixture gates
Use the official `with-docker-export-output` fixture, whose config is exactly `output: "export"` ([next.config.ts](/home/olafurbui/bunfork/.refrepos/nextjs/examples/with-docker-export-output/next.config.ts:1)). Build it with the official Next CLI, copy only `out` plus `bunfork-static-v1.json`, and test:
1. `/`, a nested prerendered route, `/404`, and missing routes.
2. `/a` versus `/a/` under each declared trailing-slash mode.
3. Base-path requests and rejection outside the base.
4. `GET`, `HEAD`, `POST`, missing assets, traversal encodings, hidden paths, and malformed percent-encoding.
5. Exact bytes, MIME, `Content-Length`, ETag/digest, cache headers, CSP, `nosniff`, compression negotiation, and `Vary`.
6. Browser-enabled and JavaScript-disabled crawling, including client navigation and static JSON/Route Handler outputs.
7. Negative fixtures containing standalone output, API routes, server actions, cookies/headers, dynamic params, middleware, and malformed manifests; all must fail admission before startup.
The same fixture suite should run against SvelteKit `adapter-static` output. That preserves pass 3’s distinction: one minimal artifact-hosting format serves both ecosystems, while their source, compiler, SSR/RSC, server-action, and standalone/server deployments remain explicitly outside scope.