# React Starter Kit
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, Oxlint, Oxfmt, and pre-configured VS Code settings React Starter Kit is proudly supported by these amazing sponsors:      ## 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/) 7.0, [Vite](https://vitejs.dev/), [Vitest](https://vitest.dev/), [Oxlint](https://oxc.rs/docs/guide/usage/linter), [Oxfmt](https://oxc.rs/docs/guide/usage/formatter) | ## 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.4+ (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 | | | Marketing site | | | API server | | ## 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 # Builds, then deploys api -> app -> web (service-binding targets first) bun deploy:staging bun deploy:production ``` CI runs the same script, so a release from your machine and one from GitHub Actions cannot drift. ## Backers                ## Contributors                          ## 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. --- 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).