GioJS
Changelog

Releases

What's new in each version of GioJS. Updated on every release and patch.

  1. 0.1.0-beta.8

    latest

    The production release: security on by default with a gio.toml switch for every protection, sessions and forms, a worker pool, on-demand revalidation, a metadata API, CSS Modules, a testing kit, a Next.js migration tool, a real gio CLI, a starter with optional features, and a rebuilt documentation site with search and a full API reference. Tested on Node.js 20, 22 and 24.

    Security
    • Every response carries default security headers; a Content-Security-Policy with fresh per-response nonces is one line of gio.toml - cache hits, PPR shells and streamed responses included. Cross-site POST/PUT/PATCH/DELETE requests and cross-origin WebSocket upgrades are refused in Rust before Node sees them.
    • Encrypted, signed cookie sessions (createSessionStorage), cookie and signing helpers, and require_session guards that verify the session in the Rust layer before any Node code runs.
    • Trusted proxies: real client IPs for rate limits, metrics and req.ip, plus request ids on every response and log line in both processes.
    • Production mode is anything but NODE_ENV=development: error responses carry only a digest that matches the log line. Connection caps and slowloris/TLS/body timeouts, Host- and Origin-gated dev endpoints, a closed /_gio namespace, and supply-chain hardening (committed Cargo.lock, cargo-deny, pinned CI actions, SECURITY.md).
    • Every protection and feature is on by default and has a gio.toml switch - [security.csrf] enabled, [security] default_headers, [cache], [images], [prefetch], [health], [env] and more. Each loosened protection logs a startup warning that giojs-server --check-config reports too; the Security switches guide lists them all, and the few that stay fixed on purpose.
    • Fail closed: a middleware.ts that throws, a guard or rule that cannot be enforced, or an invalid [i18n] setting stops startup instead of being skipped, and --check-config lists every problem in one run with its line. A worker that cannot boot ends startup with its own error.
    Routing, data and rendering
    • Catch-all and optional catch-all segments, route groups, private folders, layouts by folder ancestry, and per-folder not-found, error and loading files with notFound(). Router hooks (usePathname, useParams, useSearchParams, useRouter) and a persistent client root that keeps shared layout state across soft navigations.
    • Page actions and <GioForm>: forms that post to the page, work without JavaScript, and upgrade to client-side submissions with validation errors and Post/Redirect/Get.
    • On-demand revalidation: tag pages, purge with revalidateTag() / revalidatePath(), or call POST /_gio/revalidate from a CMS webhook. HTML responses get Cache-Control and ETags.
    • WebSocket route params, rooms and connection auth; streamed route handler responses; every Set-Cookie header survives the Rust-Node boundary.
    • .env files, GIO_PUBLIC_* variables in client code, and a server-only guard that turns a leaked server import into a build error.
    Styling, assets and SEO
    • CSS imports from any component and CSS Modules, bundled and minified by the CSS pipeline; public/ served at the site root; CSS that revalidates instead of going stale.
    • A metadata API (metadata / generateMetadata with title templates), app/sitemap.ts, robots.ts and manifest.ts, and a <JsonLd> component. GioImage srcsets follow the [images] widths in gio.toml.
    • Static export hydrates: exported pages are interactive and navigate client-side on any static host.
    Operations and developer experience
    • A supervised pool of Node render workers ([server] workers = N or "auto"), workers that can never be orphaned, JSON logs, and Prometheus metrics labeled by route pattern.
    • gio.toml is strict - an unknown key stops startup with the closest valid one - and ships a JSON Schema for editor autocomplete; PORT and GIO_HOST/GIO_PORT are honored.
    • @gio.js/core/testing (renderPage, callRoute, createTestServer), typed app conventions (PageProps, LayoutProps, Metadata...), whole-project dev watch, and create-giojs migrate for Next.js projects.
    • New guides - environment variables, deploying to Docker, Fly.io, Railway, Render and a Linux server, a production checklist - and a list of known limitations.
    • Reproducible builds: the same code always builds the same client chunks, so the deployment ID stays put across restarts and pods. CI tests Node.js 20, 22 and 24.
    Documentation
    • A rebuilt docs site: one API reference page per component, hook, function, file convention, page export, gio.toml section and CLI command, instant search (Ctrl/Cmd+K), an on-this-page outline, and copy-as-Markdown on every page.
    • New guides for upgrading, streaming, redirecting, Content Security Policy and turning protections on and off.
    CLI and starters
    • A real gio CLI: gio dev and gio start (with --port, --host and --open), gio routes, gio typegen, gio doctor and gio info, plus gio migrate and gio add. giojs-server --check-config validates a deploy's configuration without starting it.
    • npm create giojs takes a target directory, --pm, --no-git and --force, and its starter imports its CSS, self-hosts its fonts and declares page metadata. Optional starter features - Tailwind CSS, an API route with a form, authentication, a SQLite database, Docker and CI - come from flags at creation or create-giojs add / gio add later.
    Upgrading from beta.7
    • Unknown or never-implemented gio.toml keys ([cache] memory_mb, [cache.redis], ...) now stop the server with a hint - fix or remove them.
    • Cross-site form posts are refused by default: list OAuth form_post, SAML and payment-provider callbacks in [security.csrf] exempt, and other origins of yours in trusted_origins.
    • Behind a reverse proxy, set [server] trusted_proxies so rate limits and req.ip see visitors, and [security] hsts = true when the proxy terminates TLS.
    • The Node worker follows the server's mode: an unset NODE_ENV is production on both sides (production React build, no error details in responses). Run the dev server with NODE_ENV=development, as npm run dev does.
    • A page with revalidate that reads ctx.cookies, the cookie/authorization header or the client's IP or host is no longer cached - it used to be stored and served to everyone. Drop revalidate, or cache the shell with shell = 'cache' and personalize inside Suspense holes.
    • Every response now sends X-Frame-Options: SAMEORIGIN, X-Content-Type-Options: nosniff and a Referrer-Policy - override or remove them in [security.headers] - and req.json() in a route handler answers 415 unless the body was sent as JSON.
    • Routing follows the App Router: _private folders are never routed, (group) folders leave the URL, catch-all params are one /-joined string, and conflicting routes stop startup. public/ files are served at the site root and win over a page with the same path.
    • In production, error.tsx receives a generic message and a digest, and it now also runs in the browser as an error boundary, so it must not import server-only code.
    • Idle HTTP/1.1 keep-alive connections are closed after 10 seconds: keep a pooling proxy's upstream idle timeout below that, or raise header_read_timeout_secs and idle_timeout_secs.
    • Bare gio no longer starts a server - it prints the help and exits with code 2. Use gio start or gio dev. giojs-server refuses arguments it does not take (exit 2): configure it with gio.toml and environment variables.
    • Rules fail closed: a middleware.ts that throws, a guard without a requirement, a redirect, rewrite or header rule that cannot compile, or an invalid [i18n] setting now stops startup instead of being skipped.
    • A [metrics] section without a token or ip_allowlist answers only this machine; list your scrapers in ip_allowlist. And 0 now lifts a limit everywhere in gio.toml ([prefetch], [websocket] max_connections, [server] max_body_bytes ...) where it used to refuse.
  2. 0.1.0-beta.7

    Partial prerendering - cached shell, per-user Suspense holes streamed into the same response - and standalone deploys: one self-contained folder that runs on any server with only Node installed.

    Partial prerendering (PPR)
    • export const shell = 'cache' next to revalidate splits a Suspense page: the pre-Suspense shell is cached in Rust and served instantly, while the holes re-render per request (getServerSideProps reruns with the requester's own cookies) and stream in behind it. The contract: the shell renders identically for every visitor - only Suspense content may be personalized.
    • Degrades gracefully - a failed holes render ends the body after the shell with the Suspense fallbacks still visible - and X-Gio-Cache reports it all: ppr; shell=stored / hit / stale.
    Standalone deploys
    • gio build standalone packages the app into one folder: the Rust server binary, the whole Node side bundled to a single worker.js (React included, no tsx/esbuild at runtime), a run.mjs launcher, hydration chunks, and public/. Copy it to any server with only Node installed and run node run.mjs - no node_modules, no npm install.
    • --target cross-builds for any installed @gio.js/server-<platform> package: build on Windows or macOS, deploy to a Linux VPS.
    Fixed
    • latest-tag promotion retries through npm registry propagation lag instead of silently skipping, and the scaffold's typecheck config was fixed (Bundler moduleResolution + @types/node).
  3. 0.1.0-beta.6

    Repaired npm publishing (beta.5 shipped broken packages), cache-poisoning and SSRF fixes, and a developer-experience wave: Rust-executed middleware rules, streaming SSR, typed routes, cache observability, gio bench, and a smarter dev overlay.

    Release integrity & security
    • Emergency npm repair: beta.5 published @gio.js/react without dist/ and create-giojs without its bin targets. The release workflow now builds before publishing, a tarball gate refuses to publish packages with missing entry points or binaries, tag pushes run the full test matrix first, and latest-tag promotion covers the platform binaries.
    • Security: background revalidation can no longer cache a cookie-personalized page under the shared key (cache poisoning); the image optimizer allowlist is WHATWG-parsed, closing an SSRF that reached internal IPs through crafted URLs; plus decode limits, rate-limited /_gio/image, and header sanitization fixes.
    • A restart no longer throws away the disk cache: deployment IDs are content-derived (pin with GIO_DEPLOYMENT_ID), so identical builds keep their cache warm.
    Developer experience
    • Middleware: declarative redirects, rewrites, response headers, and cookie guards from gio.toml and/or middleware.ts (defineMiddleware), with :param / *rest patterns and substitution - compiled and executed in Rust before routing, so no request header can bypass them.
    • Streaming SSR: personalized (uncacheable) pages flush React's shell as soon as it renders and stream Suspense content in the same response, instead of buffering the full document - cacheable pages keep the buffered path and serve from cache at memory speed.
    • Typed routes: .gio/routes.d.ts is generated from your app/ directory at boot, and href('/posts/:id', { id }) autocompletes and typechecks with zero annotations.
    • Cache observability: every response carries X-Gio-Cache (hit / stale / miss / bypass / static with ttl and age details), and gio cache explain <url> decodes it in plain English.
    • gio bench: a zero-dependency load generator reporting req/s, p50/p90/p99/max latency, and the X-Gio-Cache label of what it measured - single URL or --suite table mode.
    • The dev error overlay shows codeframes for project frames, and stack file:line links open your editor (GIO_EDITOR/VISUAL/EDITOR).
    • /_gio/health now reports deploymentId, nodeReady, cacheEntries, and uptimeSecs; <GioLink prefetch="viewport"> prefetches when a link scrolls into view; the docs serve llms.txt and scaffolds include AGENTS.md.
  4. 0.1.0-beta.5

    The big one: client-side hydration, API routes, dev watch mode, worker supervision, and a hardened Rust↔Node boundary.

    New
    • Client-side hydration: per-route esbuild bundles, a #__gio hydration boundary, and props serialized safely into the page - interactive React with zero hydration-mismatch surface. getServerSideProps and its server-only imports are stripped from client bundles.
    • API routes: route.ts files export GET/POST/PUT/PATCH/DELETE handlers receiving params, query, headers, parsed cookies, and the request body - return JSON, a web Response, or a GioEventStream (SSE). Unexported methods get a proper 405.
    • getServerSideProps now receives the full request (method, path, headers, cookies) and can return response headers like set-cookie - such pages are automatically uncacheable.
    • app/not-found.tsx and app/error.tsx render real 404/500 pages through your layouts; static export writes 404.html so hosts like Cloudflare Pages return a real 404 for unknown URLs instead of the home page.
    • Dev watch mode: edit a file and the server clears caches, restarts the worker, and reloads your browser - about 1.5 seconds edit-to-browser.
    • Alpine/musl Linux binaries (@gio.js/server-linux-x64-musl) with automatic libc detection.
    Reliability & security
    • The Node worker is supervised: crashes respawn in ~300 ms instead of taking the server down, and a hard-killed server can never orphan the worker (Windows Job Objects).
    • Renders are never shared across users: coalescing is credential-aware and only ever shares explicitly cacheable pages.
    • The IPC boundary is versioned (enforced at handshake), authenticated with per-instance tokens, and carries request bodies - binary-safe - plus vary/cacheTags/cancel frames.
    • Client disconnects and timeouts now abort in-flight React renders instead of finishing work nobody reads.
    • All @gio.js/* packages, platform binaries, and templates are version-locked; releases publish with npm provenance; CI runs a real Rust↔Node integration suite on Linux and Windows.
  5. 0.1.0-beta.4

    Packaging and clean-install fixes following beta.3.

    Fixed
    • Clean-install issues found while testing the published packages end-to-end: tsx as a runtime dependency, package file lists, and template fixes.
  6. 0.1.0-beta.3

    SEO-ready static exports.

    New
    • Static export auto-generates robots.txt and a full sitemap.xml (absolute URLs from GIO_SITE_URL).
    • Exported pages no longer reference a client bootstrap script that 404s on static hosts.
  7. 0.1.0-beta.2

    Static export - build to plain HTML and deploy anywhere, for free.

    New
    • Static export: gio export pre-renders your whole app to out/ as plain HTML - deploy free to Cloudflare Pages, GitHub Pages, or any static host.
    • create-giojs now asks "Server app or Static site?" and wires npm run build accordingly (gio export for static).
    • getStaticPaths() convention to pre-render dynamic routes during export.
    • getServerSideProps runs at build time, baking its data into the exported HTML.
  8. 0.1.0-beta.1

    First public beta on npm, published under the @gio.js scope.

    Highlights
    • Published to npm: @gio.js/server, @gio.js/core, @gio.js/react, create-giojs, and prebuilt platform binaries (linux-x64, win32-x64, darwin-x64, darwin-arm64).
    • npm create giojs@latest - interactive scaffolder with an arrow-key picker for TypeScript / JavaScript.
    Framework
    • Rust HTTP/2 server with brotli/gzip compression, static file serving, and rustls TLS.
    • Image optimization endpoint (/_gio/image): AVIF → WebP → JPEG with a two-layer cache.
    • ISR page cache with stale-while-revalidate and deployment-aware invalidation.
    • React SSR via renderToReadableStream, getServerSideProps, nested layouts, and file-based routing for .tsx / .jsx / .js.
    • Route handlers, Server-Sent Events, and WebSockets over a dedicated IPC pipe.
    • Self-hosted fonts (WOFF2), i18n routing, Prometheus metrics, and a dev dashboard.

Subscribe on GitHub to be notified when a new version ships.