Installation

Start with a minimal React app that runs locally on the Workers runtime.

On this page

Prerequisites

  • Local tools: Use Node.js 22 or newer and pnpm.
  • Cloudflare account: An account is needed only for deployment. Local development works without a login. You don't need a paid Workers plan to build and deploy with Goribu.

Create an app

Terminal
pnpm create goribu@latest my-app
cd my-app
pnpm install
pnpm dev
Terminal
pnpm create goribu@latest my-app --js
cd my-app
pnpm install
pnpm dev

Open the local URL printed in your terminal. The starter is ready for you.

  • App name: Use up to 50 lowercase letters, digits or hyphens. Start with a letter and end with a letter or digit. Pass a name, not a path.
  • Existing directories: The starter generator does not overwrite an existing directory.
  • Dependency installation: The starter generator does not install dependencies for you.

For JavaScript, add --js:

Terminal
pnpm create goribu@latest my-app --js

Both variants use the same framework APIs.

Find your way around

FilePurpose
src/routes/index.tsxsrc/routes/index.jsxThe home page.
public/Static assets served at the site root.
src/setup/_document.tsxsrc/setup/_document.jsxOptional custom HTML document around your pages.
src/setup/client-entry.jsRequired browser bootstrap and global CSS imports.
src/styles/global.cssGlobal styles and the Tailwind import.
goribu.config.jsApp runtime, deployment, and resource settings.
vite.config.jsVite, Goribu, and Tailwind plugins.
AGENTS.mdProject instructions for coding agents.

Your pages and handlers go in the src/routes together, while reusable components can go in other folders like src/components/. Leave .goribu/, .wrangler/, goribu.wrangler.jsonc, and node_modules/ to the tools that generate them.

Start coding with your agent

Your agents will read the included AGENTS.md before changing the app. If not, just ask them to. Then describe a feature and its expected behavior. The AI coding guide explains how to provide useful context and At a glance there's a compact API introduction to point your agents to.

Commands

Run commands from your app directory.

CommandPurpose
pnpm devDevelop locally with hot updates.
pnpm typecheckCheck TypeScript without emitting files. TypeScript starter only.
pnpm buildBuild the Worker, browser assets, and static pages.
pnpm checkInspect the production target, resources, and migrations without changing them.
pnpm exec goribu cloudflare-loginLog in to Cloudflare through Wrangler.
pnpm run deployBuild and deploy to Cloudflare.
  • Custom port: Run pnpm dev --port 5199 to use a specific port number (in this case 5199) instead of the default. The command fails if the port is already in use.
  • Network access: Add --host to your pnpm dev to listen on every network interface. Then other devices on your network can reach the development server.
  • Persistent defaults: Set development defaults in vite.config.js.
Alternative development commands
pnpm dev --port 5199
pnpm dev --host

If using npm, add -- before script options so npm forwards them to the development server: npm run dev -- --host or npm run dev -- --port 5199.

Development and production builds compile TypeScript without type checking. Run pnpm typecheck separately in TypeScript projects.

Use the full pnpm run deploy command (don't forget the run part) to ship your app to Cloudflare. See Deploys when you are ready to publish.

Write a route

Create src/routes/hello.tsxsrc/routes/hello.jsx with the following example, then visit /hello?name=Kate. Use type-only imports to describe your page props and request handlers:The handler passes props to the page with res.render():

src/routes/hello.tsx
import type { Handler } from "goribu/server";
import type { Meta } from "goribu";

type Props = { name: string };

// Read the query string and pass serializable props to the page.
export const GET: Handler<Props> = (req, res) => {
  const name = req.query.get("name")?.trim() || "friend";
  return res.render({ name });
};

export const meta: Meta<Props> = ({ props }) => ({
  title: `Hello, ${props.name}`,
});

// Render the same props on the server and in the browser.
export default function HelloPage({ name }: Props) {
  return <h1>Hello, {name}.</h1>;
}
src/routes/hello.jsx
// Read the query string and pass serializable props to the page.
export const GET = (req, res) => {
  const name = req.query.get("name")?.trim() || "friend";
  return res.render({ name });
};

export const meta = ({ props }) => ({
  title: `Hello, ${props.name}`,
});

// Render the same props on the server and in the browser.
export default function HelloPage({ name }) {
  return <h1>Hello, {name}.</h1>;
}
  • Handler generics: Handler<Props, Env, Params> also accepts types for Worker bindings and dynamic parameters.
  • Runtime validation: Types describe expectations, so validate request input at runtime. The API reference lists public types.