@danoweibo/create-fastnext
v1.0.1
Published
Scaffold a production-ready turborepo with BetterAuth, Drizzle, Postgres, Next.js, React Native (Expo) and Fastify
Downloads
256
Maintainers
Readme
create-fastnext
A CLI tool to scaffold a production-ready full-stack turborepo monorepo with authentication, database, and multi-platform support — all wired up and ready to go.
npx @danoweibo/create-fastnext my-app
# or
pnpm dlx @danoweibo/create-fastnext my-appWhat you get
A turborepo monorepo with 5 apps and 5 shared packages, fully configured with auth, database, linting, and typed environment variables out of the box.
Apps
| App | Framework | Port | Purpose |
| ------------- | ------------------------- | ---- | ----------------------------------------------- |
| apps/web | Next.js 16 (Pages Router) | 5000 | Consumer web app — sign in, sign up, dashboard |
| apps/admin | Next.js 16 (App Router) | 5100 | Admin dashboard — role-gated, admin-only access |
| apps/app | Vite + React | 5200 | Lightweight generic app |
| apps/mobile | Expo 55 + React Native | 8081 | Mobile app — iOS and Android |
| apps/server | Fastify 5 | 8080 | API server — auth handler + protected routes |
Packages
| Package | Purpose |
| ---------------- | ----------------------------------------------------- |
| @{name}/auth | Shared Better Auth configuration with Drizzle adapter |
| @{name}/db | Drizzle ORM schema + Supabase-ready migrations |
| @{name}/env | Type-safe environment variables per app (t3-env) |
| @{name}/ui | Shared shadcn/ui component library (Tailwind 4) |
| @{name}/config | Shared TypeScript base configuration |
Stack
Core
- Monorepo — Turborepo + pnpm workspaces
- Language — TypeScript throughout
- Linting & Formatting — Biome (replaces ESLint + Prettier)
Backend
- Server — Fastify 5
- Auth — Better Auth with email/password, username, admin plugin, bearer token, and Expo support
- Database — Drizzle ORM + PostgreSQL (Supabase)
- Env validation — t3-env with Zod
Frontend (Web)
- Framework — Next.js 16
- Styling — Tailwind CSS 4 + shadcn/ui
- Forms — TanStack Form + Zod validation
- Themes — next-themes (dark/light mode)
Frontend (Mobile)
- Framework — Expo 55 + React Native
- Styling — Tailwind CSS 4 via Uniwind
- Components — heroui-native
- Variants — tailwind-variants
- Auth storage — expo-secure-store
Auth features
Better Auth is pre-configured across all platforms with the following out of the box:
- Email + password sign in and sign up
- Username support with normalization, min/max length, reserved name list, and display name validation
- Admin plugin — role-based access, user banning with custom message
- Bearer token — for mobile API requests (React Native doesn't use browser cookies)
- Expo plugin — deep link auth for React Native with secure token storage
- Trusted origins — all app URLs pre-configured for local and production
- Cross-domain cookies —
sameSite: none,secure: truefor Vercel → Render setup
Role system
Two roles are supported out of the box: user (default) and admin.
apps/admin— only allows sign in for users withrole: "admin". Non-admin accounts are detected after sign-in and redirected to the consumer app.apps/web+apps/mobile— accessible by all authenticated users regardless of role.
To promote a user to admin, run directly on the database:
UPDATE "user" SET "role" = 'admin' WHERE "email" = '[email protected]';API routes
The server ships with three tiers of test routes that demonstrate the auth-gating pattern:
| Route | Auth | Role | Used by |
| ------------------------------ | -------- | ---------- | ------------------------- |
| GET /api/test/items | None | Public | apps/app, apps/mobile |
| POST /api/testuser/create | Required | Any user | apps/web, apps/mobile |
| GET /api/testuser/read | Required | Any user | apps/web, apps/mobile |
| PUT /api/testuser/update | Required | Any user | apps/web, apps/mobile |
| DELETE /api/testuser/delete | Required | Any user | apps/web, apps/mobile |
| POST /api/testadmin/create | Required | Admin only | apps/admin |
| GET /api/testadmin/read | Required | Admin only | apps/admin |
| PUT /api/testadmin/update | Required | Admin only | apps/admin |
| DELETE /api/testadmin/delete | Required | Admin only | apps/admin |
These are wired up with working UI in each app — create, read, update, delete with live responses displayed. Replace them with your real business logic.
Getting started
Prerequisites
- Node.js 18+
- pnpm 11+
- A Supabase project
Scaffold
pnpm create fastnext my-app
cd my-appThe CLI will ask:
- Initialize a git repository? (default: Yes)
- Install dependencies with pnpm? (default: Yes)
Database setup
- Open your Supabase project → SQL Editor
- Run the schema from
packages/db/src/schema/auth.ts(or use the generated SQL in Supabase) - Copy your Supabase connection string (Transaction pooler recommended) and update
apps/server/.env:
DATABASE_URL=postgresql://postgres.[ref]:[password]@aws-0-[region].pooler.supabase.com:6543/postgresEnvironment variables
Each app has a pre-populated .env for local development and .env.production for deployment. The only values you need to fill in locally are:
apps/server/.env
BETTER_AUTH_SECRET=<auto-generated by CLI>
BETTER_AUTH_URL=http://localhost:8080
CORS_ORIGIN=http://localhost:5000,http://localhost:5100,http://localhost:5200
DATABASE_URL=your-supabase-connection-stringapps/admin/.env
NEXT_PUBLIC_SERVER_URL=http://localhost:8080
NEXT_PUBLIC_ENTRY_URL=http://localhost:5000apps/web/.env
NEXT_PUBLIC_SERVER_URL=http://localhost:8080apps/mobile/.env
EXPO_PUBLIC_SERVER_URL=http://<your-local-ip>:8080Note: Mobile can't use
localhost— use your machine's local IP address (ipconfigon Windows,ifconfigon Mac/Linux).
apps/app/.env
VITE_SERVER_URL=http://localhost:8080Start developing
pnpm dev:admin # admin + server
pnpm dev:web # web + server
pnpm dev:mobile # mobile + server (Expo)
pnpm dev:api # server only
pnpm dev:admin+core # admin + web + server
pnpm dev:core+ticket # web + app + server
pnpm dev:app # mobile only (no server)Deployment
Recommended setup
| App | Platform |
| ------------- | -------------------------------- |
| apps/server | Render |
| apps/admin | Vercel |
| apps/web | Vercel |
| apps/app | Vercel |
| Database | Supabase |
| Mobile | Expo EAS |
Important: Vercel and Render are on different domains. The template uses Next.js rewrites (
/api/*→ Render) to avoid cross-domain cookie issues. This is pre-configured inapps/admin/next.config.tsandapps/web/next.config.ts.
Render (server)
Set these environment variables in your Render service:
BETTER_AUTH_SECRET=<your-secret>
BETTER_AUTH_URL=https://<your-render-service>.onrender.com
CORS_ORIGIN=https://<your-web>.vercel.app,https://<your-admin>.vercel.app,https://<your-app>.vercel.app
DATABASE_URL=<your-supabase-connection-string>
NODE_ENV=productionVercel (admin, web, app)
Set these in each Vercel project's environment variables:
Admin:
NEXT_PUBLIC_SERVER_URL=https://<your-render-service>.onrender.com
NEXT_PUBLIC_ENTRY_URL=https://<your-web>.vercel.appWeb:
NEXT_PUBLIC_SERVER_URL=https://<your-render-service>.onrender.comApp:
VITE_SERVER_URL=https://<your-render-service>.onrender.comCustom domain tip: If you own a domain (e.g.
myapp.com), point all services at subdomains (api.myapp.com,app.myapp.com,admin.myapp.com). Setdomain: ".myapp.com"in the Better Auth cookie config and the rewrite workaround becomes unnecessary.
Development scripts
| Script | What it runs |
| ---------------------- | ------------------------------------------------------------------ |
| pnpm dev | All apps (via Turborepo) |
| pnpm dev:admin | apps/admin + apps/server |
| pnpm dev:web | apps/web + apps/server |
| pnpm dev:ticket | apps/app + apps/server |
| pnpm dev:mobile | apps/mobile + apps/server |
| pnpm dev:admin+core | apps/admin + apps/web + apps/server |
| pnpm dev:core+ticket | apps/web + apps/app + apps/server |
| pnpm dev:api | apps/server only |
| pnpm dev:app | apps/mobile only |
| pnpm build | Build all apps |
| pnpm check-types | Type check all packages |
| pnpm check | Biome check + auto-fix (safe) |
| pnpm lint:fix | Biome check + auto-fix (including unsafe — sorts Tailwind classes) |
| pnpm db:push | Push schema changes to database |
| pnpm db:studio | Open Drizzle Studio |
| pnpm db:generate | Generate migrations |
| pnpm db:migrate | Run migrations |
Project structure
my-app/
├── apps/
│ ├── admin/ # Next.js App Router — admin portal
│ ├── web/ # Next.js Pages Router — consumer web
│ ├── mobile/ # Expo — iOS + Android
│ ├── app/ # Vite — ticket/public app
│ └── server/ # Fastify — API + auth
├── packages/
│ ├── auth/ # Better Auth config (shared)
│ ├── db/ # Drizzle schema + migrations
│ ├── env/ # t3-env per app
│ ├── ui/ # shadcn/ui component library
│ └── config/ # Shared tsconfig
├── biome.json # Linting + formatting (root)
├── turbo.json # Turborepo pipeline
└── pnpm-workspace.yamlLinting
Biome is configured at the root and covers all apps and packages. It replaces both ESLint and Prettier.
pnpm check # fix safe issues
pnpm lint:fix # fix everything including Tailwind class sortingTailwind class sorting uses Biome's useSortedClasses rule (nursery) — it won't auto-apply on save, only via lint:fix.
License
MIT
