Installation
Add the islandcn engine to a React project with the shadcn CLI and mount the island once.
By the end of this page your app renders a black pill at the top centre of the window, ready for activities.
You need React 19 and a project set up for shadcn (a components.json at the root). If you don’t have one, run npx shadcn@latest init first.
Install the engine
npx shadcn@latest add https://islandcn.dev/r/island-core.jsonpnpm dlx shadcn@latest add https://islandcn.dev/r/island-core.jsonyarn dlx shadcn@latest add https://islandcn.dev/r/island-core.jsonbunx shadcn@latest add https://islandcn.dev/r/island-core.jsonThis writes the engine to lib/island/, under your lib alias. It adds no npm packages.
Mount the provider and the island
Render IslandProvider once, high in the tree, and Island once inside it. placement="viewport" pins the pill to the top centre of the window. Without it, the pill draws at the top of its nearest positioned parent, which is what you want inside a phone mockup.
IslandProvider holds state, so it renders on the client. Put it in a client file and use that file from the root layout.
"use client";
import type { ReactNode } from "react";
import { Island, IslandProvider } from "@/lib/island";
export const Providers = ({ children }: { children: ReactNode }) => (
<IslandProvider>
<Island placement="viewport" />
{children}
</IslandProvider>
);import type { ReactNode } from "react";
import { Providers } from "./providers";
const RootLayout = ({ children }: { children: ReactNode }) => (
<html lang="en">
<body>
<Providers>{children}</Providers>
</body>
</html>
);
export default RootLayout;Wrap the root once in main.tsx. The shadcn CLI needs the @ path alias in tsconfig.json and vite.config.ts; npx shadcn@latest init tells you if it is missing.
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import { Island, IslandProvider } from "@/lib/island";
import { App } from "./app";
const root = document.getElementById("root");
if (root) {
createRoot(root).render(
<StrictMode>
<IslandProvider>
<Island placement="viewport" />
<App />
</IslandProvider>
</StrictMode>,
);
}Check it
Reload the page. A black pill sits at the top centre. It does nothing yet: it waits for an activity.
Add a preset
Each preset is its own registry item and names it on its page. The first one you add also installs island-content, the kit the presets share. For example, the timer:
npx shadcn@latest add https://islandcn.dev/r/timer-activity.jsonpnpm dlx shadcn@latest add https://islandcn.dev/r/timer-activity.jsonyarn dlx shadcn@latest add https://islandcn.dev/r/timer-activity.jsonbunx shadcn@latest add https://islandcn.dev/r/timer-activity.jsonDone when
lib/island/index.tsexists.- The page shows a black pill at the top centre when no activity runs.
- Starting an activity grows the pill, and ending it returns the pill to rest. The quick start does exactly that.