Full-stack React app template: React Router 7 (framework mode), Vite+ toolchain, Hono server with streaming SSR, Drizzle ORM + SQLite, Better Auth (Google / GitHub OAuth), and Paraglide i18n with optional locale in the URL.
| Area | Notes |
|---|---|
| Server | Hono-based Node server (react-router-hono-server), centralized SQLite + middleware |
| i18n | Paraglide, locale switcher, URL strategy (/:locale?/…) |
| Data | Todos CRUD with Drizzle + SQLite |
| Auth | Better Auth, OAuth buttons, login route, session on home |
| Tooling | Commitlint; pnpm for app scripts; Vite+ (vp) for check / test (see AGENTS.md) |
- 🚀 Streaming SSR and data APIs (loaders / actions)
- ⚡️ HMR in development (Vite)
- 🌐 i18n (Paraglide) —
en,de,ja,zh - 🔐 Sign-in with Google / GitHub (optional; env-driven)
- 🗃️ SQLite via Drizzle (todos + auth tables)
- 🎨 Tailwind CSS v4
- 🔒 TypeScript, Zod-validated server env
- 📖 React Router docs
- Node.js
>= 20.6.0(fornode --env-fileused by productionstart) - Vite+ CLI —
vp(see AGENTS.md / CLAUDE.md) - pnpm
10.32.1(declared inpackage.jsonaspackageManager)
pnpm installCopy the example env and fill in values:
cp .env.example .env| Variable | Purpose |
|---|---|
DATABASE_URL |
SQLite file path (default dev.db) |
BETTER_AUTH_SECRET |
Required — min 32 chars; e.g. openssl rand -base64 32 |
BETTER_AUTH_URL |
App origin (dev: http://localhost:5173) |
GOOGLE_* / GITHUB_* |
Optional OAuth client id/secret |
Apply migrations (creates auth + todos schema):
pnpm run db:migrateOther Drizzle scripts (see package.json):
| Script | Description |
|---|---|
pnpm run db:generate |
Generate migrations from schema |
pnpm run db:push |
Push schema (dev) |
pnpm run db:studio |
Drizzle Studio |
pnpm run db:drop |
Drop migration helper (drizzle-kit) |
pnpm run auth:secret # generate a secret via Better Auth CLI
pnpm run auth:generate # regenerate `app/db/auth.ts` from configpnpm run devApp: http://localhost:5173 (Vite default). Routes use an optional locale prefix, e.g. /, /en, /login, /en/todos.
The dev script is defined in Scripts.
vp check # format, lint, TypeScript
vp test # tests (Vitest via Vite+)pnpm run typecheckpnpm run build
pnpm run startSet BETTER_AUTH_URL to your real origin and provide secrets / OAuth credentials as needed.
What build and start run is listed in Scripts (start loads .env via Node’s --env-file).
These are defined in package.json. Run with pnpm run <name> (for example pnpm run dev).
| Script | Command |
|---|---|
build |
react-router build |
dev |
react-router dev |
start |
node --env-file=.env ./build/server/index.js |
typecheck |
react-router typegen && tsc |
prepare |
vp config |
- Runtime:
react/react-dom19,react-router7,@react-router/node/@react-router/serve - Server:
hono,react-router-hono-server - Auth:
better-auth - DB:
drizzle-orm,better-sqlite3 - Validation:
zodv4 - Dev:
@react-router/dev,drizzle-kit,@inlang/paraglide-js,@tailwindcss/vite,tailwindcssv4 - Build:
vitevia@voidzero-dev/vite-plus-core,vite-plus
A Dockerfile is present; it currently assumes npm and package-lock.json. This repo uses pnpm — adjust the Dockerfile to pnpm install / pnpm run build / pnpm run start (and copy pnpm-lock.yaml) if you deploy with Docker.
Generic flow:
docker build -t my-app .
docker run -p 3000:3000 --env-file .env my-appPass the same env vars as in .env.example for auth and DB path.
Ship package.json, lockfile, build/ output, and run pnpm run start (or inject the same vars your host provides instead of a file).
Tailwind CSS is preconfigured; you can swap or extend as you like.
Built with React Router and Vite+.