Tutorial

Your first Turtle app.

Create a workspace package, render a Server Component, add a Client Component, and run it with Bun.

1. Create the package

packages/my-app/package.json
{
  "name": "@acme/my-app",
  "private": true,
  "type": "module",
  "scripts": {
    "dev": "turtle dev",
    "build": "turtle build",
    "start": "turtle start"
  },
  "dependencies": {
    "react": "19.2.7",
    "react-dom": "19.2.7",
    "turtle": "workspace:*"
  }
}

Run bun install at the workspace root. Applications consume Turtle through its declared package exports and CLI; they never reach into packages/web/src.

2. Configure Turtle

// turtle.config.ts
import { defineConfig } from "turtle";

export default defineConfig({
  stylesheets: ["/styles.css"],
});

3. Add required boundaries and a layout

// app/layout.tsx
export default function Layout({ children }: { children: React.ReactNode }) {
  return <main><nav><a href="/">Home</a></nav>{children}</main>;
}

// app/error.tsx
export default function ErrorPage({ error }: { error: Error }) {
  return <h1>Could not render: {error.message}</h1>;
}

// app/not-found.tsx
export default function NotFoundPage() {
  return <h1>Page not found</h1>;
}

4. Render the home route

// app/page.tsx
export const metadata = { title: "Hello Turtle" };

export default async function HomePage() {
  const greeting = await Promise.resolve("Hello from the server");
  return <article><h1>{greeting}</h1><Counter /></article>;
}

5. Add interactivity at a client boundary

// src/Counter.tsx
"use client";

import "client-only";
import { useState } from "react";

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

Import Counter from the page. Turtle discovers the directive and creates the RSC reference and browser module entries automatically.

6. Run and verify

bun run --cwd packages/my-app dev
# production
bun run --cwd packages/my-app build
bun run --cwd packages/my-app start

Development builds watch the whole application. Production builds create dist/ server graphs and public/assets/browser.js.