kriasoft/react-starter-kit: a Bun and Cloudflare Workers SaaS monorepo
Modern React starter kit with Bun, TypeScript, Tailwind CSS, tRPC, Stripe, and Cloudflare Workers. Production-ready monorepo for building fast web apps.
At a glance
- What is it?
- This template ships three Cloudflare Workers, tRPC, Drizzle ORM and Stripe billing in one repository. It suits teams already committed to Bun and Cloudflare, and it is a poor fit if you want a plain Vite SPA or a Node server.
- Who is it for?
- Adopt it if your team already builds on Bun and Cloudflare Workers and wants auth, billing and a typed API wired up before the first feature. Skip it if you need a single Node process, a plain Vite SPA, or a stack you can debug without reading a Terraform directory.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 2 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What kriasoft/react-starter-kit actually removes from a SaaS build
Most SaaS projects spend their first weeks on the same plumbing: an authentication flow, a subscription table, a typed API boundary, and a deploy target. This repository is a package of decisions about that plumbing rather than a component library. The README describes it as a full-stack monorepo template for building SaaS applications with React 19, tRPC, and Cloudflare Workers, and the workspace layout backs that up: apps/web, apps/app, apps/api, apps/email, plus packages/ui, packages/core and packages/ws-protocol.
The intended audience is narrow and specific. You need a Cloudflare account, Bun v1.4 or newer, and a willingness to run your API as a Worker rather than a long-lived Node process. In exchange you get Better Auth with email OTP, passkey, Google OAuth and organizations, Stripe subscriptions, and Drizzle ORM schemas already pointed at Neon PostgreSQL. A team that would otherwise spend a sprint wiring those together gets them as files to edit.
What it is not is a general-purpose React scaffold. The marketing site is Astro, the app is a React 19 SPA on TanStack Router, and the API is Hono plus tRPC. If you only wanted client-side routing and a build step, the three-worker topology is overhead you will pay for on every deploy.
Three Workers, one type contract: the architecture in the repository
The repository layout is the architecture. apps/web is an Astro marketing site that also acts as an edge router, serving static assets and proxying to the other two workers. apps/app is the React 19 single-page application. apps/api is the Hono and tRPC server. According to the README, the web worker routes /api/* to the API worker and app routes to the app worker through Cloudflare service bindings, so the browser talks to one hostname and the split stays server-side.
Type safety is the second structural idea. TypeScript, tRPC and Drizzle ORM form what the README calls a single type contract from database to UI. In practice that means a schema change in db/ propagates through the tRPC router into the React app at compile time, which is the main reason to accept tRPC instead of a REST layer with hand-written client types.
Supporting directories carry the rest. infra/ holds Terraform for Hyperdrive connection pools and R2 storage, db/ holds Drizzle schemas, migrations and seed data, and packages/ws-protocol defines a WebSocket protocol with type-safe messaging. The presence of Terraform is a signal about operational expectations: this template assumes you will manage Cloudflare resources as code, not by clicking through a dashboard.
Installing kriasoft/react-starter-kit and running it locally
The README's Quick Start begins by generating a new repository from the template on GitHub, then cloning your copy. Bun is the only package manager involved; the prerequisites list Bun v1.4 or newer as replacing Node.js and npm.
git clone https://github.com/your-username/your-project-name.git
cd your-project-name
bun installConfiguration follows Vite env conventions. .env is committed and holds shared defaults and placeholders only, while .env.local is git-ignored and should hold real credentials, overriding .env.
cp .env .env.localAfter replacing the placeholder values, one command starts all three apps. The README also lists per-app alternatives: bun web:dev for the marketing site, bun app:dev for the application, and bun api:dev for the API server.
bun devThe documented local URLs are http://localhost:5173 for the React app, http://localhost:4321 for the marketing site, and http://localhost:8787 for the API server. If those three respond, the workspace and the service wiring are intact.
The database step needs DATABASE_URL set in .env.local first. For local prototyping the README points at db:push, with db:seed for sample data and db:studio for a GUI.
bun db:push
bun db:seed
bun db:studioThe README is explicit that db:push is for local prototyping only. Staging and production apply migrations instead, through bun db:migrate:staging and bun db:migrate:production. Treat that boundary as real: schema pushes against a production database are the fastest way to lose data with this template.
The Cloudflare and Neon coupling is the real adoption cost
Every convenience here is also a dependency. The API runs on Cloudflare Workers, the database is Neon PostgreSQL reached through Drizzle, and infra/ contains Terraform for Hyperdrive connection pools and R2 storage. Move any one of those and you are rewriting rather than configuring. A team with an existing Postgres instance on another host, or an API that must run in a container, will spend more time removing pieces than the template saves.
The runtime constraint is the sharpest one. Workers are not a general Node environment, and the README's own escape hatch is telling: package.json includes api:build:docker, which builds a Docker image from apps/api/Dockerfile. That exists for the cases where the Worker model does not fit, and using it means you have left the deployment path the rest of the template assumes.
Upgrades are the second cost, and the README handles them unusually. Rather than a changelog you merge by hand, it points at a merge-seed skill, run as /merge-seed in Claude Code or $merge-seed in Codex, which merges upstream changes while preserving your project's identity and configuration. The README warns to start with a clean working tree and says the Quick Start guide explains the workflow and its safety boundary. That phrasing is a fair warning: an automated merge that preserves your configuration is exactly the operation you want to run on a clean branch and review before pushing.
Release history offers little guidance. The only releases listed are v0.4.0 from 2015-08-28 and earlier 2015 tags, which do not describe the current Bun and Cloudflare codebase. The last push to the repository was on 2026-09-14. Judge the project by the working tree, not by those tags.
How it compares with a plain Vite SPA and with Next.js
The closest alternative is a plain Vite plus React setup with a separate backend. Vite gives you a dev server and a build; you add routing, data fetching, auth and deployment yourself. That is less code to learn and far less to remove, and it does not tie you to Cloudflare. The difference in approach is where the type boundary lives: with a hand-rolled setup you own the client and server types separately, while this template derives them from the Drizzle schema through tRPC. If your team has never used tRPC, that derivation is the part worth prototyping before you commit.
Next.js is the other common comparison, and the split is architectural rather than stylistic. Next.js keeps rendering and API routes in one application, which means one deploy and one mental model. This template deliberately separates them into three Workers connected by service bindings, with an Astro site handling marketing. You get independent deploys and an edge runtime; you give up the single-process simplicity and, in most cases, the larger ecosystem of examples and hosting options.
The related searches that surface Laravel React starter kits describe a different product entirely. Those pair a PHP backend with a React frontend. This repository has no PHP component, and its backend is Hono on Workers. If you arrived looking for the Laravel starter kit, you are on the wrong page.
Licence, maintenance and what upgrading costs you
The repository is MIT licensed, which permits commercial use, modification and redistribution provided the copyright notice and permission notice are retained. That is a permissive licence with few obligations, but it is not legal advice, and shipping a product built on a template still means checking the licences of the dependencies you keep, including Better Auth, Stripe's SDKs and the shadcn/ui components under packages/ui.
Maintenance signals point to an active repository. It is not archived, and the last push was on 2026-09-14. The README also links a Discord server, a documentation site at reactstarter.com, and ChatGPT and Gemini assistants configured for the project, which suggests the maintainer expects questions from people who did not write the code.
The upgrade path is the part to plan for. Because the template is meant to be modified, your copy diverges from upstream immediately, and the merge-seed skill exists precisely because a git merge would otherwise fight your changes. Budget for that review each time you pull upstream work in. Teams that fork once and never merge again are effectively maintaining their own framework, which is a legitimate choice but should be a conscious one.
Editorial conclusion
Adopt it if your team already builds on Bun and Cloudflare Workers and wants auth, billing and a typed API wired up before the first feature. Skip it if you need a single Node process, a plain Vite SPA, or a stack you can debug without reading a Terraform directory. Before committing, clone the template, run bun install and bun dev, and confirm that your database provider and Stripe account fit the .env.local contract the repository defines.
Frequently asked questions
What is kriasoft/react-starter-kit?
It is a full-stack monorepo template for building SaaS applications, built on React 19, tRPC and Cloudflare Workers according to the README. It ships authentication, Stripe subscriptions, Drizzle ORM schemas and a Bun-based toolchain as starting files rather than as separate libraries to assemble.
How do I install kriasoft/react-starter-kit?
Generate a new repository from the template on GitHub, clone your copy, then run bun install. Copy .env to .env.local, replace the placeholder values with real credentials, and run bun dev to start the web, app and API processes.
Do I need Bun to use kriasoft/react-starter-kit?
Yes. The prerequisites list Bun v1.4 or newer as replacing Node.js and npm, and the root scripts in package.json are written as bun commands. There is no documented npm or pnpm path.
Can I deploy kriasoft/react-starter-kit somewhere other than Cloudflare?
The template is built around Cloudflare Workers, with service bindings connecting the web, app and API workers, and Terraform in infra/ for Hyperdrive and R2. package.json does include api:build:docker, which builds a Docker image from apps/api/Dockerfile, but the README does not document a non-Cloudflare deployment path.
How do I keep my project updated with upstream kriasoft/react-starter-kit changes?
The README directs you to the merge-seed skill, run as /merge-seed in Claude Code or $merge-seed in Codex, which merges upstream changes while preserving your project's identity and configuration. It says to start with a clean working tree and points at the Quick Start guide for the workflow and its safety boundary.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/kriasoft-react-starter-kit)