Static Export
Pre-render your whole app to plain HTML and deploy it free to any static host — Cloudflare Pages, GitHub Pages, Netlify, or an S3 bucket. Static when you can, server when you must.
Choose at create time
When you scaffold a project, pick Static site at the prompt. That wires npm run build to the exporter and drops the production server scripts.
npm create giojs@latest
# ? Which language? › TypeScript / JavaScript
# ? What are you building? › Server app / Static siteYou can also pass it non-interactively:
npm create giojs@latest my-site -- --staticBuild
Develop with npm run dev as usual. When you're ready to ship, export to the out/ folder:
npm run build # runs: gio export → ./outEvery static route is rendered through the real SSR pipeline, so what you see in dev is what you get in out/. getServerSidePropsruns at build time and its data is baked into the HTML.
Dynamic routes
A dynamic route like app/posts/[id]/page.tsx needs to know which paths to render. Export getStaticPaths to list them:
export async function getStaticPaths() {
const posts = await db.posts.all();
return { paths: posts.map((p) => ({ params: { id: String(p.id) } })) };
}getStaticPaths are skipped with a warning — they can only be served by the GioJS server.What can't be static
The exporter skips anything that needs a live server, and tells you what it skipped:
route.tshandlers and Server-Sent Events- WebSocket (
wsHandler) routes - ISR revalidation (
export const revalidate— there's no server to revalidate on) - Runtime image optimization via
/_gio/image(use pre-sized images)
If you need any of those, use Server mode instead.
Deploy
out/ is a self-contained static site — no runtime required. Drop it on any static host:
# Cloudflare Pages / Netlify: build command "npm run build", output dir "out"
# GitHub Pages: push ./out to a gh-pages branch
# Or serve locally to check:
npx serve out