## File: README.md

A full-stack monorepo template for building SaaS applications with React 19, tRPC, and Cloudflare Workers. Type-safe from database to UI, deployable to the edge in minutes.

## Highlights

- **Type-safe full stack** – TypeScript, tRPC, and Drizzle ORM create a single type contract from database to UI
- **Edge-native** – Three Cloudflare Workers (web, app, api) connected via service bindings
- **Auth + billing included** – Better Auth with email OTP, passkey, Google OAuth, organizations, and Stripe subscriptions
- **Modern React** – React 19, TanStack Router (file-based), TanStack Query, Jotai, Tailwind CSS v4, shadcn/ui
- **Database ready** – Drizzle ORM with Neon PostgreSQL, migrations, and seed data
- **Fast DX** – Bun toolchain, Vite, Vitest, ESLint, Prettier, and pre-configured VS Code settings

React Starter Kit is proudly supported by these amazing sponsors:

[](https://reactstarter.com/s/1)&nbsp;&nbsp;[](https://reactstarter.com/s/2)&nbsp;&nbsp;[](https://reactstarter.com/s/3)

## Technology Stack

| Layer | Technologies |
| --- | --- |
| **Runtime** | [Cloudflare Workers](https://workers.cloudflare.com/) |
| **Frontend** | [React 19](https://react.dev/), [TanStack Router](https://tanstack.com/router), [Tailwind CSS v4](https://tailwindcss.com/), [shadcn/ui](https://ui.shadcn.com/), [Jotai](https://jotai.org/) |
| **Marketing** | [Astro](https://astro.build/) |
| **Backend** | [Hono](https://hono.dev/), [tRPC](https://trpc.io/), [Better Auth](https://www.better-auth.com/), [Stripe](https://stripe.com/) |
| **Database** | [Drizzle ORM](https://orm.drizzle.team/), [Neon PostgreSQL](https://get.neon.com/HD157BR) |
| **Toolchain** | [Bun](https://bun.sh/), [TypeScript](https://www.typescriptlang.org/) 6.0, [Vite](https://vitejs.dev/), [Vitest](https://vitest.dev/), [ESLint](https://eslint.org/), [Prettier](https://prettier.io/) |

## Monorepo Architecture

```
├── apps/
│   ├── web/          Astro marketing site (edge router, serves static + proxies to app/api)
│   ├── app/          React 19 SPA (TanStack Router, Jotai, Tailwind CSS v4)
│   ├── api/          Hono + tRPC API server (Better Auth, Cloudflare Workers)
│   └── email/        React Email templates
├── packages/
│   ├── ui/           shadcn/ui components (new-york style)
│   ├── core/         Shared types and utilities
│   └── ws-protocol/  WebSocket protocol with type-safe messaging
├── db/               Drizzle ORM schemas, migrations, and seed data
├── infra/            Terraform (Hyperdrive connection pools, R2 storage)
├── docs/             VitePress documentation
└── scripts/          Build automation and dev tools
```

Each app deploys independently to Cloudflare Workers. The web worker routes `/api/*` to the API worker and app routes to the app worker via service bindings.

## Prerequisites

- [Bun](https://bun.sh/) v1.3+ (replaces Node.js and npm)
- [VS Code](https://code.visualstudio.com/) with our [recommended extensions](.vscode/extensions.json)
- [React Developer Tools](https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi?hl=en) browser extension (recommended)
- [Cloudflare account](https://dash.cloudflare.com/sign-up) for deployment

## Quick Start

### 1. Create Your Project

[Generate a new repository](https://github.com/kriasoft/react-starter-kit/generate) from this template, then clone it locally:

```bash
git clone https://github.com/your-username/your-project-name.git
cd your-project-name
```

### 2. Install Dependencies

```bash
bun install
```

### 3. Configure Environment

This project follows [Vite env conventions](https://vite.dev/guide/env-and-mode#env-files):

- [`.env`](./.env) is committed and contains shared defaults/placeholders only (no real secrets)
- `.env.local` is git-ignored and should contain your real credentials
- `.env.local` values override `.env`

```bash
cp .env .env.local  # then replace placeholder values with real ones
```

Also check [`wrangler.jsonc`](./apps/api/wrangler.jsonc) for Worker configuration and bindings.

### 4. Start Development

```bash
# Launch all apps in development mode (web, api, and app)
bun dev

# Or, start specific apps individually
bun web:dev  # Marketing site
bun app:dev  # Main application
bun api:dev  # API server
```

### 5. Initialize Database

Ensure `DATABASE_URL` is configured in your `.env.local` file, then set up the schema:

```bash
bun db:push              # Push schema directly (quick dev setup)
bun db:seed              # Seed with sample data (optional)
bun db:studio            # Open database GUI
```

`db:push` is for local prototyping only. Staging and production apply migrations instead: `bun db:migrate:staging`, `bun db:migrate:production`.

| App            | URL                     |
| -------------- | ----------------------- |
| React app      | <http://localhost:5173> |
| Marketing site | <http://localhost:4321> |
| API server     | <http://localhost:8787> |

## Keep Your Project Updated

When you want to bring in newer React Starter Kit changes, ask your coding agent to run the `merge-seed` skill (`/merge-seed` in Claude Code or `$merge-seed` in Codex). It merges upstream changes while preserving your project's identity and configuration. Start with a clean working tree; the [Quick Start guide](https://reactstarter.com/getting-started/quick-start#keep-template-updates) explains the workflow and its safety boundary.

## Production Deployment

The short version. The [deployment guide](https://reactstarter.com/deployment/) covers each step in full.

### 1. Provision Infrastructure

Terraform creates the Hyperdrive configurations the API worker connects through:

```bash
bun infra:production apply
```

Paste the two IDs it prints into the `hyperdrive` block of `apps/api/wrangler.jsonc`.

### 2. Environment Setup

Configure your production secrets in Cloudflare Workers:

```bash
# Required – the API refuses to deploy without these
bun wrangler secret put BETTER_AUTH_SECRET --config apps/api/wrangler.jsonc --env=""
bun wrangler secret put RESEND_API_KEY --config apps/api/wrangler.jsonc --env=""

# Google sign-in (optional – email OTP and passkeys work without it)
bun wrangler secret put GOOGLE_CLIENT_ID --config apps/api/wrangler.jsonc --env=""
bun wrangler secret put GOOGLE_CLIENT_SECRET --config apps/api/wrangler.jsonc --env=""

# Stripe billing (optional – set all four to enable, or none; annual is extra)
bun wrangler secret put STRIPE_SECRET_KEY --config apps/api/wrangler.jsonc --env=""
bun wrangler secret put STRIPE_WEBHOOK_SECRET --config apps/api/wrangler.jsonc --env=""
bun wrangler secret put STRIPE_STARTER_PRICE_ID --config apps/api/wrangler.jsonc --env=""
bun wrangler secret put STRIPE_PRO_PRICE_ID --config apps/api/wrangler.jsonc --env=""
bun wrangler secret put STRIPE_PRO_ANNUAL_PRICE_ID --config apps/api/wrangler.jsonc --env="" # optional
```

All of these belong to the API worker, which is what `--config` selects – without it Wrangler has no worker to attach the secret to. Use `--env staging` for staging; production is the top-level config, selected explicitly with `--env=""`. Non-sensitive vars like `RESEND_EMAIL_FROM` go in `wrangler.jsonc` directly.

Set `RESEND_EMAIL_FROM` to an address on a domain you have verified with Resend. The default `onboarding@resend.dev` only delivers to your own inbox, and sign-in is email OTP – leave it and no one else can sign in.

### 3. Migrate the Production Database

```bash
bun db:migrate:production   # reads .env.production.local, and only that file
```

### 4. Build and Deploy

```bash
# Build every deployable workspace; Bun orders workspace dependencies
bun run build      # Build all deployable workspaces

# Deploy service-binding targets before the web router
bun api:deploy --env=""
bun app:deploy --env=""
bun web:deploy --env=""
```

## Backers

[](https://reactstarter.com/b/1)&nbsp;&nbsp;[](https://reactstarter.com/b/2)&nbsp;&nbsp;[](https://reactstarter.com/b/3)&nbsp;&nbsp;[](https://reactstarter.com/b/4)&nbsp;&nbsp;[](https://reactstarter.com/b/5)&nbsp;&nbsp;[](https://reactstarter.com/b/6)&nbsp;&nbsp;[](https://reactstarter.com/b/7)&nbsp;&nbsp;[](https://reactstarter.com/b/8)

## Contributors

[](https://reactstarter.com/c/1)&nbsp;&nbsp;[](https://reactstarter.com/c/2)&nbsp;&nbsp;[](https://reactstarter.com/c/3)&nbsp;&nbsp;[](https://reactstarter.com/c/4)&nbsp;&nbsp;[](https://reactstarter.com/c/5)&nbsp;&nbsp;[](https://reactstarter.com/c/6)&nbsp;&nbsp;[](https://reactstarter.com/c/7)&nbsp;&nbsp;[](https://reactstarter.com/c/8)&nbsp;&nbsp;[](https://reactstarter.com/c/9)&nbsp;&nbsp;[](https://reactstarter.com/c/10)&nbsp;&nbsp;[](https://reactstarter.com/c/11)&nbsp;&nbsp;[](https://reactstarter.com/c/12)&nbsp;&nbsp;[](https://reactstarter.com/c/13)

## Need Help?

**[Documentation](https://reactstarter.com/)** covers auth, database, billing, deployment, and more.

Our AI assistant is trained on this codebase – ask it anything on [ChatGPT](https://chatgpt.com/g/g-69564f0a23088191846aa4072bd9397d-react-starter-kit-assistant) or [Gemini](https://gemini.google.com/gem/1IXFElQ2UvvZY86iL6uZLeoC-r8mp-OB-?usp=sharing). Try these questions:

- [How do I add a new tRPC endpoint?](https://chatgpt.com/g/g-69564f0a23088191846aa4072bd9397d-react-starter-kit-assistant?prompt=How%20do%20I%20add%20a%20new%20tRPC%20endpoint%3F)
- [Help me create a database table](https://chatgpt.com/g/g-69564f0a23088191846aa4072bd9397d-react-starter-kit-assistant?prompt=Help%20me%20create%20a%20database%20table)
- [How does authentication work?](https://chatgpt.com/g/g-69564f0a23088191846aa4072bd9397d-react-starter-kit-assistant?prompt=How%20does%20authentication%20work%3F)
- [Explain the project structure](https://chatgpt.com/g/g-69564f0a23088191846aa4072bd9397d-react-starter-kit-assistant?prompt=Explain%20the%20project%20structure)
- [How do I deploy to Cloudflare?](https://chatgpt.com/g/g-69564f0a23088191846aa4072bd9397d-react-starter-kit-assistant?prompt=How%20do%20I%20deploy%20to%20Cloudflare%3F)
- [Add a new page with routing](https://chatgpt.com/g/g-69564f0a23088191846aa4072bd9397d-react-starter-kit-assistant?prompt=Add%20a%20new%20page%20with%20routing)
- [How do I send emails?](https://chatgpt.com/g/g-69564f0a23088191846aa4072bd9397d-react-starter-kit-assistant?prompt=How%20do%20I%20send%20emails%3F)

## Contributing

See the [Contributing Guide](.github/CONTRIBUTING.md) to get started. Check [good first issues](https://github.com/kriasoft/react-starter-kit/issues?q=label:"good+first+issue") or join [Discord](https://discord.gg/2nKEnKq) for discussion.

## License

Copyright © 2014-present Kriasoft. This source code is licensed under the MIT license found in the [LICENSE](https://github.com/kriasoft/react-starter-kit/blob/main/LICENSE) file.

---

<sup>Made with ♥ by Konstantin Tarkus ([@koistya](https://twitter.com/koistya), [blog](https://medium.com/@koistya)) and [contributors](https://github.com/kriasoft/react-starter-kit/graphs/contributors).</sup>

---

## File: db/README.md

# Database Layer

Database layer using [Drizzle ORM](https://orm.drizzle.team/) and PostgreSQL ([Neon](https://neon.tech/)) via Cloudflare Hyperdrive.

[Documentation](https://reactstarter.com/database/) | [Schema](https://reactstarter.com/database/schema) | [Migrations](https://reactstarter.com/database/migrations) | [Testing](https://reactstarter.com/testing)

## Structure

```bash
db/
├── schema/             # Table definitions and relations
├── migrations/         # Auto-generated migration files
├── seeds/              # Seed scripts (e.g., users)
├── scripts/            # DB utilities (seed/export)
├── drizzle.config.ts   # Drizzle configuration
├── testing.ts          # createTestDatabase() – PGlite for tests
└── package.json        # DB-only scripts and deps
```

## Environment

- In development, `DATABASE_URL` is loaded from the repo root in this order: `.env.<environment>.local` → `.env.local` → `.env`.
- Environment selection: `ENVIRONMENT` takes priority, otherwise `NODE_ENV=production|staging` maps directly to the same name; default is `dev`. There is no `test` environment – tests use PGlite and never resolve a `DATABASE_URL`.

Example `.env.dev.local` (at repo root):

```txt
DATABASE_URL=postgresql://user:password@host:5432/database
```

## Commands

From the repo root:

```bash
bun db:push       # Apply schema (drizzle-kit push)
bun db:generate   # Generate migration from schema changes
bun db:migrate    # Run pending migrations
bun db:studio     # Open Drizzle Studio
bun db:seed       # Run seed scripts
bun db:check      # Check generated migration history for conflicts
```

Append `:staging` or `:production` to target other environments. These read only `.env.<environment>.local`, override anything already exported, and fail if that file is missing:

```bash
bun db:migrate:staging
bun db:migrate:production
bun db:studio:production
bun db:export:production
```

`db:generate` and `db:push` have no remote variants – `generate` never touches a database, and `push` skips migration files, so it belongs to local prototyping only. `db:seed` stops at `:staging`; the seeds create test accounts.

## Typical Workflow

1. Update schema in `db/schema`, re-exporting any new file from `schema/index.ts` – that barrel is what Drizzle Kit reads.
2. Generate a migration: `bun db:generate --name <migration-name>`.
3. Apply locally: `bun db:migrate` (or `db:push` for schema sync).
4. Validate in Drizzle Studio: `bun db:studio`.
5. Apply to staging/production with the matching `:staging` or `:production` suffix.

## Importing Schemas

```typescript
import { schema, type Database } from "@repo/db";
import { user } from "@repo/db/schema/user";
import { organization, member } from "@repo/db/schema/organization";
import { createTestDatabase } from "@repo/db/testing";
```

`Database` is the schema-bound client type, independent of the driver – postgres-js in production, PGlite in tests.

## Testing

`createTestDatabase()` boots PGlite (Postgres in WebAssembly) and applies `migrations/`, so tests use a Postgres engine with no server to start:

```typescript
const { db, reset, close } = await createTestDatabase();

afterAll(close);
beforeEach(reset);
```

See [Testing](https://reactstarter.com/testing) for the full guide.

## ID Generation

Primary keys use application-generated prefixed CUID2 IDs (e.g. `usr_ght4k2jxm7pqbv01`) via `$defaultFn()`: `generateAuthId(model)` for Better Auth models and `generateId("xxx")` for domain tables. See `db/schema/id.ts` for the prefix map.

---

## File: docs/index.md

---
# https://vitepress.dev/reference/default-theme-home-page
layout: home

hero:
  name: "React Starter Kit"
  # text: "Production-ready monorepo for building fast web apps"
  tagline: Skip months of setup and ship your AI-powered SaaS fast. Authentication, database migrations, edge deployment, and cutting-edge React patterns all configured with industry best practices.
  actions:
    - theme: brand
      text: Getting Started
      link: /getting-started/
    - theme: alt
      text: View on GitHub
      link: https://github.com/kriasoft/react-starter-kit
    - theme: alt
      text: Ask ChatGPT
      link: https://chatgpt.com/g/g-69564f0a23088191846aa4072bd9397d-react-starter-kit-assistant
    - theme: alt
      text: Ask Gemini
      link: https://gemini.google.com/gem/1IXFElQ2UvvZY86iL6uZLeoC-r8mp-OB-?usp=sharing

features:
  - icon: 🤖
    title: AI-First Development
    details: Code with AI from day one – LLM instructions, tool configurations, and project context pre-built for Claude Code, Cursor, and Gemini CLI
  - icon: 🚀
    title: Edge-First Architecture
    details: Built for Cloudflare Workers with optimized performance, global distribution, and instant deployment
  - icon: ⚛️
    title: Modern React Stack
    details: React 19 with Vite & Astro, TanStack Router, Jotai state management, and shadcn/ui components with Tailwind CSS v4
  - icon: 🔐
    title: Auth + Billing Included
    details: Better Auth with social providers, passkeys, organizations, and Stripe subscriptions via hosted checkout
  - icon: 🏢
    title: Multi-Tenant Database
    details: Neon PostgreSQL with Drizzle ORM, pre-built multi-tenant schema with organizations, migrations, and type-safe queries
  - icon: ⚡
    title: Ship Faster
    details: Bun runtime for instant builds, hot reload, unified tooling, and comprehensive testing setup
---