Astro → Zigapagos

Most of an Astro project converts mechanically. zigapagos migrate scans your project and writes a worklist mapping every file to its target, with a first pass at each island's imports available via --scaffold. These are the mappings that worklist follows — the cases it cannot decide for you are listed, not guessed.

zigapagos migrate ./my-astro-site -o MIGRATION.md

The mapping

React and Preact components become .island.tsx with the same hooks. The import source changes; the component body usually does not.

Astro

// src/components/Counter.jsx
import { useState } from "react";

export default function Counter({ start }) {
  const [n, setN] = useState(start);
  return <button onClick={() => setN(n + 1)}>{n}</button>;
}

Zigapagos

// components/Counter.island.tsx
import { useState } from "@z/runtime";

export interface Props { start: number }

export default function Counter({ start }: Props) {
  const [n, setN] = useState(start);
  return <button onClick={() => setN(n + 1)}>{n}</button>;
}

What it will not do

The parts that need a decision get reported, not guessed

Integrations

An Astro integration has no equivalent to convert into — Zigapagos has no plugin system. zigapagos migrate flags astro.config.* for manual review rather than enumerating each integration inside it; deciding whether one is replaceable, unnecessary, or already covered is on you.

Server-rendered routes

Zigapagos has no request-time rendering. An SSR endpoint becomes either a build-time computation or a call to a real backend, and which one is a design decision.

The full mapping is specified in migrating from Astro, written precisely enough that an agent can complete a port unattended, with per-pattern conversions in recipes.