Rich interfaces. Simple output.
HTML, CSS, and TSX. Fast production builds. Static files to deploy.
Build directly or with your coding agent. Bring your styles and your backend.
Website Β· Islands Β· SPAs Β· Migrate from Astro Β· Migrate from Rails
Zigapagos turns pages, interactive components, and client-routed applications into static files. A native core generates HTML; Bun renders and bundles TSX at build time. Pages without islands need no framework runtime. Add the interaction your product needs and control when it loads.
Work in familiar web languages: HTML templates, CSS, and Preact-compatible TSX. Use plain CSS, bring a CSS framework's generated stylesheet, or build on your own design system. Zigapagos supplies the rendering and build pipeline, without requiring a visual style or an AI service. Its SuperHTML templates, SuperMD content, and Ziggy configuration add specific conventions, documented explicitly.
Build quickly, then deploy the files. The frontend needs no production Bun or Node process. Use a compatible static host and your existing API; configure SPA routing and headers for that host. Pair with ZigBase when you want data, authentication, server-enforced access rules, files, realtime, jobs, and custom backend logic on the same origin. See Building applications.
Direct development and coding agents use the same source, local tools, and verification commands. Structured diagnostics make the feedback easier to act on. Here is an interactive component:
// components/Counter.island.tsx
import { useState } from "@z/runtime";
export default function Counter({ start = 0 }: { start?: number }) {
const [n, setN] = useState(start);
return <button onClick={() => setN(n + 1)}>clicked {n} times</button>;
}At build time each .island.tsx is server-rendered through a Bun sidecar and
embedded into the page as real HTML. In the browser it hydrates on your
terms β client:load, client:idle, client:visible, client:media, or
client:only β sharing ONE Preact instance across every island via an import
map. No island on the page? Zero JavaScript shipped.
- TSX islands β Preact-compatible components (
useState,useEffect, context, portals, β¦) via the first-party@z/runtime, SSR'd at build time and partially hydrated. - Native SPAs β a single
.spa.tsx(exportedspa+routes) becomes a client-routed app: prerendered route skeletons, two-phase hydration, soft navigation, route guards, nested layouts. Host-agnostic routing manifests (ZigBase / Nginx / Apache) generated for you. - Prefetching β a SPA
<Link>starts a lazy route's chunk load on hover by default (prefetch="viewport"andprefetch={false}per link), skipped under the browser's data-saver signal. On content pages, opt-in.speculation_rules = trueinjects declarative Speculation Rules prefetch hints β zero runtime JS, inert on browsers without support. - View transitions β
viewTransitions: trueon a SPA wraps soft navigation indocument.startViewTransition(); feature-detected and off by default, so without the opt-in or the API navigation stays the instant flip. Content pages get the cross-document equivalent with one CSS rule. - Build-time image optimization β
.image_optimize = {}resamples content images into WebP at your configured widths and emits a<picture>with a full responsivesrcset/sizesand the untouched original as fallback; opt-in AVIF through an externalavifenc-compatible encoder you supply. Variants are cached across rebuilds and never upscaled. Off by default β see docs/images.md. - Pagination β a section index opts in with
.pagination = { .page_size = 10 }and is rendered once per window of subpages, in a choice of three URL styles;$page.subpages()returns the current window, so an existing layout loop paginates with no edit. - First-class framework migration β
zigapagos migrate <source>detects Astro, Next.js, Gatsby, Nuxt/Vue, Hugo, Jekyll, Eleventy, Hexo, or Rails and writes a source-specificMIGRATION.md.--target <new-site>assembles a minimal valid project from every safe deterministic transform: React β@z/runtimeislands, Markdown/Ziggy frontmatter, fixed-URL assets, and the supported Rails ERB presentation subset. Rails migrations add versioned discovery and handoff manifests, durable operator decisions, ZigBase backend bindings, and generated parity runners; unsupported or uncertain behavior remains explicit instead of being guessed. The Astro and Rails workflows ship as installable Agent Skills in the openSKILL.mdformat. Generated targets must be missing or empty; source files are read-only and nested targets are rejected. Astro remains the reference path and retains the deeperinit --from-astroscaffold, whilemigrate --targetis the uniform baseline for every supported adapter. - Agent-legible diagnostics β
--format=jsononrelease,validate,doctorandexplain-codeemits NDJSON with stableZP_*codes, so an agent's build β fix β validate loop matches on codes instead of parsing prose.zigapagos initscaffoldsAGENTS.mdandCLAUDE.mdinto a new site. - Zero-config dev loop β
zigapagos devrebuilds the site, serves the real release tree with the stock ZigBase binary (same-origin API and admin UI, not a proxy shim), and live-reloads the browser over SSE. Islands hot-swap with theiruseStateintact.dev --backgrounddetaches the loop βdev stop|status|logsmanage it afterward, and a build-awareGET /_zigapagos/statuslets a script poll for its own edit to land β anddevbackgrounds itself automatically in a recognized AI-agent environment. - Deployable host config β a release with islands or SPAs also writes a
hash-strict Content-Security-Policy (CSP3
style-src-elem/style-src-attrsplit) and a site-wideCache-Controlpolicy beside the routing manifests, each in ZigBase, Nginx and Apache form. - A real templating stack, no JS required β SuperHTML layouts and SuperMD content with build-time correctness checks, inherited from Zine.
- Fast native core β the site graph and content pipeline are Zig; the only JS toolchain is Bun, used surgically for TSX.
Building a site needs no Zig toolchain. zigapagos is a standalone
executable; nothing in a Zigapagos project is compiled from Zig source.
curl -fsSL https://valthon.github.io/zigapagos/install.sh | sh
zigapagos init # scaffold a site
zigapagos dev # dev loop at http://127.0.0.1:1990That one command installs the zigapagos binary, the @z/runtime tree it renders
islands and SPAs through, and β only if you don't already have them β Bun and
ZigBase. Everything goes under ~/.local/share/zigapagos with a launcher in
~/.local/bin: no sudo, no edits to your shell startup files, and nothing is
written until each download has been verified against the release's published
SHA-256 sums. Re-running installs a new version alongside the old one and
repoints the launcher; to uninstall, remove those two paths.
| sh -s -- --help lists the options: --version for a specific release,
--prefix / --bin-dir to move where things go, --no-bun / --no-zigbase to
leave those to you. It is one file β read it before you pipe it
anywhere.
Prebuilt releases support x86_64 and arm64 on Linux and macOS, including Apple Silicon. Each host gets a native binary; neither installer substitutes an emulated build. Windows needs WSL2.
npx zigapagos init # scaffold a content site
npx zigapagos dev # dev loop at http://127.0.0.1:1990
npx zigapagos release --output=public --force # build itThe same complete install, if you would rather have it in a project's
node_modules than on your machine β this one needs Node.js 18+, which the shell
installer does not. zigapagos is an alias for the canonical
@zigapagos/cli. Either channel covers everything: content
sites, the CLI tooling (init, migrate, doctor, validate, explain),
islands, native SPAs and zigapagos dev. The package ships the
@z/runtime sources and the Bun sidecar, and depends on bun and
@zigbase/server, so release discovers your *.island.tsx / *.spa.tsx
entries and bundles them itself.
Each release publishes the four per-target archives, a runtime.tar.xz, and a
SHA256SUMS. The per-target archives contain the binary alone: islands and
SPAs additionally need the @z/runtime tree out of runtime.tar.xz, with
ZIGAPAGOS_RUNTIME_DIR pointed at it. Doing that by hand is exactly what
install.sh does for you, so this route is for people who want to place the
pieces themselves.
docs/runtime-dependencies.md is the full
account: what each command needs installed, how Bun and ZigBase are obtained, and
what each channel supplies.
To add your first island, see docs/islands.md. A complete
worked example lives in examples/tsx-site/ β islands,
a SPA slice, SSR + real-browser hydration tests.
content/*.smd βββΊ Zig core (SuperMD/SuperHTML) βββΊ page HTML ββ
components/*.island.tsx βββΊ Bun sidecar (SSR) βββββββββββββββββ€βββΊ static site
βββΊ esbuild-style bundle ββββββββββ + import map
(@z/runtime external) + one shared runtime
One render seam: after a page renders, islands found in it are SSR'd and the
resulting HTML + data-z-props are injected, along with a modulepreload hint,
an import map, and the shared runtime script. Everything else is ordinary static
generation.
Zigapagos is pre-1.0: APIs may change between minor versions. Only the most recent release is supported β see releases for the current one and CHANGELOG.md for what changed. The islands engine, SPA support, and the Astro and Rails migration workflows are covered by unit, shell, and real-browser tests.
Building Zigapagos itself is the only thing that needs a Zig toolchain (0.16.0 β we track released Zig, not nightlies). See CONTRIBUTING.md for the setup, the test suites, and the review standard in NO_SLOP.md.
Zigapagos is a permanent fork of Zine by
Loris Cro β a fast, elegant, deliberately JavaScript-free
SSG. The Zig core, SuperHTML, SuperMD, and Ziggy are his work and the reason
this project could exist. Zigapagos diverges philosophically (we embrace a
minimal TSX toolchain for interactivity; Zine's whole point is not to), which
is why this is a fork rather than a contribution. The original README is
preserved at docs/upstream/ZINE-README.md;
fork point: zine v0.11.2 (496e42d).
MIT β see LICENSE, which retains the upstream Zine copyright.