Quick start
Install
zigapagos is a standalone executable. You do not need a Zig toolchain to build a site — nothing in a Zigapagos project is compiled from Zig source.
The shortest path is npm, which brings everything a site can need in one install:
npx zigapagos init
That pulls @zigapagos/cli, which ships the binary, the @z/runtime sources, the Bun sidecar, and Bun and ZigBase as optional dependencies. It needs Node 18 or newer to run the launcher, and covers everything: content sites, islands, native SPAs and the dev loop.
Prefer a bare binary? Download one from the releases page — an x86_64 Linux (musl) or x86_64 macOS build — and put it on your PATH. That archive is the binary and nothing else, which is enough for a content-only site but not for islands or SPAs; those additionally need Bun and the @z/runtime tree, and the npm install is the way to get both. The full rule, per command, is in runtime dependencies.
Generate a site
mkdir my-site && cd my-site
zigapagos init
init writes a complete sample site: a homepage, an about page, a blog section, a devlog, the layouts that render them, and the assets they reference. It is worth reading before deleting — the sample copy demonstrates SuperMD syntax you will otherwise have to look up.
Write a page
A content file opens with a Ziggy frontmatter block. Two fields are required:
---
.title = "About",
.layout = "page.shtml",
---
.title is the page’s title and .layout names the template in layouts/ that renders it. Every other field has a default — .description and .author are empty, .date is the Unix epoch, .draft is false, .tags, .aliases and .alternatives are empty lists — so add one when something reads it, not by habit. A blog post needs .date because the listing layout renders it for each entry; a landing page usually needs neither a date nor an author, and the scaffold init writes reflects that.
Run the development server
zigapagos dev
dev needs no arguments: it builds the site into public/, serves that tree at http://127.0.0.1:1990 with ZigBase — downloading the pinned release the first time if you have none — and rebuilds when you edit content, layouts, or assets. The page in your browser refreshes itself.
Run zigapagos with no command and you get the help menu, not a server; every command is explicit.
Add an island
Create components/Hello.island.tsx:
import { useState } from "@z/runtime";
export interface Props { name: string }
export default function Hello({ name }: Props) {
const [waves, setWaves] = useState(0);
return (
<button onClick={() => setWaves(waves + 1)}>
Hello {name} — waved {waves} times
</button>
);
}
Declare it on the build command:
zigapagos release --island=components/Hello.island.tsx
Once a project has more than one, keep that invocation in a build.sh so the entries are declared in one place — see configuration.
And use it in a layout — not in a .smd file, which rejects raw HTML:
<island src="components/Hello.island.tsx" client:visible prop-name="world"></island>
Rebuild. The button is server-rendered into the HTML, and hydrates when it scrolls into view.
Next
The tutorial builds something real. Islands is the full reference for directives, props, and slots.