Stedefast

Templates

Islands

2 min read

Islands are React components that run in the browser. Stedefast bundles each island separately and hydrates them after page load.

Create an island

Place islands in theme/islands/:

// theme/islands/Counter.tsx
import { useState } from "react";

interface CounterProps {
  initial?: number;
}

export default function Counter({ initial = 0 }: CounterProps) {
  const [count, setCount] = useState(initial);
  return (
    <button onClick={() => setCount(c => c + 1)}>
      Count: {count}
    </button>
  );
}

Use an island in a template

Add a data-island mount point in your template's JSX:

// In a React template
<div
  data-island="Counter"
  data-props={JSON.stringify({ initial: 5 })}
/>

At build time, Stedefast:

  1. Detects the data-island="Counter" attribute
  2. Bundles theme/islands/Counter.tsxdist/islands/Counter.js
  3. Injects <script type="module" src="/islands/Counter.js"> before </body>

At runtime, the island hydrates its mount point with React.createRoot.

Scaffold an island

stedefast scaffold island Counter

Creates theme/islands/Counter.tsx with a useState starter template.

Module islands

Modules like @stedefast/module-comments and @stedefast/module-claps ship with their own pre-built islands. You use them the same way as custom islands — mount them with data-island in your template.

Module island names are the component's export name:

// CommentsIsland from @stedefast/module-comments
<div
  data-island="CommentsIsland"
  data-props={JSON.stringify({
    pageId: page.slug,
    pageUrl: `${site.baseUrl}${page.url}`,
    initialComments: modules.comments?.data ?? [],
  })}
/>

Customising a module island

To edit a module island's markup or behaviour, eject it into your theme:

stedefast scaffold module-island comments

This copies the island source to theme/islands/CommentsIsland.tsx, rewriting imports to use the module's full package name. Update your config to point the module at the local copy:

CommentsModule({
  islandComponentPath: "./theme/islands/CommentsIsland.tsx",
})

The ejected file imports its data-fetching hooks and types directly from the module package:

import { useComments, postComment } from "@stedefast/module-comments/hooks";
import type { CommentsIslandProps } from "@stedefast/module-comments";

If the module's API changes in a future version, TypeScript will error at these import sites — so you know exactly what to update before deploying.

See scaffold module-island for the full list of supported modules and error cases.