A production-ready monorepo template for building full-stack applications with React Native, Next.js, and Hono. Cloudflare Workers deployment is preconfigured through vinext and Wrangler without replacing the normal Next.js and Node development/deployment paths.
- Mobile App: React Native with Expo SDK 56 development builds and New Architecture enabled
- Web App: Next.js 16 with App Router, React Server Components, tRPC, auth, and an optional vinext Workers build
- Secondary Server: Portable Hono database example and health service
- Hosting: Cloudflare Workers with Wrangler and one GitHub Actions deployment pipeline
- Type Safety: End-to-end type safety with TypeScript and tRPC
- Monorepo Management: Turborepo with pnpm workspaces for optimized builds
- Better Auth: Complete authentication system with:
- Email/password authentication
- Phone number authentication via Twilio OTP
- Google OAuth integration
- Email verification
- Password reset flows
- Firebase Integration: Native push notifications, token registration, and App Check
- Mobile: NativeWind v5 with theme provider
- Web: Tailwind CSS v4 with Shadcn/ui
- Database: Prisma v7 ORM with PostgreSQL/Supabase
- Server State: TanStack Query (React Query) via tRPC
- Client State: Zustand for local state management
- Web Payments: Direct Stripe subscriptions managed by Better Auth
- Mobile Subscriptions: RevenueCat over App Store and Play Billing
- Independent Billing: Stripe and RevenueCat remain separate while backend routes accept either verified entitlement
- Analytics: PostHog for product analytics
- Error Tracking: Sentry for monitoring
- Type Safety: Shared TypeScript configurations
- Code Quality: Type-aware Oxlint, Prettier, Husky pre-commit hooks
- Push Notifications: Firebase Cloud Messaging
- Permissions: Camera, notifications, location handling
- Device Info: Platform-specific utilities
- App Store Ready: EAS Build & Submit configured
.
βββ apps/
β βββ native/ # Expo React Native app
β β βββ app/ # App screens and navigation
β β βββ assets/ # Images and static files
β β βββ config/ # Firebase credentials
β β βββ eas.json # EAS Build configuration
β βββ server/ # Portable Hono database example and health server
β β βββ src/ # Server source code
β βββ web/ # Next.js web app
β βββ app/ # App Router pages
β βββ components/ # React components
βββ packages/
β βββ api/ # tRPC router definitions
β βββ auth/ # Better Auth configuration
β βββ db/ # Prisma schema and client
β βββ shared/ # Shared utilities and types
βββ tooling/
β βββ prettier/ # Shared Prettier config
β βββ typescript/ # Shared TypeScript configs
β βββ vitest/ # Shared Vitest config
βββ .oxlintrc.json # Shared Oxlint rules
βββ .env.example # Environment variables template
βββ CLAUDE.md # AI assistant instructions
βββ package.json # Root workspace configuration
βββ pnpm-workspace.yaml # pnpm workspace definition
βββ turbo.json # Turborepo pipeline config
Before you begin, ensure you have the following installed:
- Node.js: >=22.14.0 (Download)
- pnpm: >=9.6.0 (Installation Guide)
- Xcode: 26.4+
- Android Studio: Latest version with Android SDK 26+
# Clone the repository
gh repo clone ayush-goyal/universal-template
cd universal-template
# Install dependencies
pnpm install# Copy environment variables template
cp .env.example .env
# Configure your .env file- Create iOS app in Firebase Console
- Download
GoogleService-Info.plist - Place at
apps/native/config/GoogleService-Info.plist
- Create Android app in Firebase Console
- Download
google-services.json - Place at
apps/native/config/google-services.json
# Run migrations
pnpm --filter @acme/db db:migrate
# Open Prisma Studio (optional)
pnpm --filter @acme/db db:studioStripe is always registered with Better Auth, so configure its secret and webhook keys before starting the web application.
- In Stripe, create one Pro product with monthly and annual recurring prices.
- Set the price lookup keys to
pro_monthlyandpro_annual. - Add
STRIPE_SECRET_KEYandSTRIPE_WEBHOOK_SECRETto the root.env. - Point the Stripe webhook to
https://your-domain.com/api/auth/stripe/webhook. - Enable
checkout.session.completed,customer.subscription.created,customer.subscription.updated, andcustomer.subscription.deleted. - Configure the Stripe Customer Portal and tax registrations. Checkout always enables Stripe Automatic Tax.
Better Auth owns Stripe Checkout, Portal, webhook verification, and the subscription table. The
application reads that synchronized table for access; it does not call Stripe on every request.
- Add iOS and Android apps to one RevenueCat project.
- Create an entitlement with lookup key
pro. - Attach the App Store and Play Store monthly/annual products to that entitlement and the current offering.
- Add the public SDK keys as
EXPO_PUBLIC_REVENUECAT_IOS_API_KEYandEXPO_PUBLIC_REVENUECAT_ANDROID_API_KEY. - Create a RevenueCat v2 secret key with
customer_information:subscriptions:read, then addREVENUECAT_SECRET_API_KEYandREVENUECAT_PROJECT_ID. - Add a RevenueCat webhook at
https://your-domain.com/api/webhooks/revenuecat. Configure an Authorization header and put the exact value inREVENUECAT_WEBHOOK_AUTH. - Keep RevenueCat's default transfer behavior unless your product requires purchases to remain permanently attached to the original application account.
RevenueCat remains native-only. The SDK can create an anonymous customer before sign-in and later
link it to a Better Auth user with Purchases.logIn; CustomerInfo is the native entitlement
source. For Pro backend authorization, RevenueCat webhooks trigger a current-state API fetch
and update only a minimal RevenueCatEntitlement cache. Billing management remains independent:
native never reads Stripe billing state, web billing UI never reads RevenueCat, and no provider is
called on every application request.
For real purchase testing, use Stripe test mode and a RevenueCat-enabled Expo development build with App Store sandbox and Google Play license-test accounts. Expo Go cannot complete real store purchases.
# Run all apps in development mode
pnpm dev
# Or run specific apps
pnpm --filter @acme/native dev # Mobile app
pnpm --filter @acme/web dev # Web app
pnpm --filter @acme/server dev # API server
# For Android physical device
pnpm --filter @acme/native adbThe repository has one workflow, .github/workflows/deploy.yml. Pull requests run checks and
build both Workers. A push to main deploys the Hono and vinext Workers.
GitHub only needs Cloudflare deployment credentials:
- Repository variable:
CLOUDFLARE_ACCOUNT_ID - Actions secret:
CLOUDFLARE_API_TOKEN
Configure application secrets directly on the corresponding Worker in Cloudflare. Wrangler
preserves existing secrets during deployments. At minimum, set DATABASE_DIRECT_URL on both
Workers; the Workerd client uses Prisma Postgres' serverless HTTP/WebSocket adapter rather than a
TCP connection. Normal Node development continues to use the pooled DATABASE_URL.
Set the Better Auth, Stripe, Resend, Google OAuth, Twilio, OpenAI, RevenueCat, and Sentry values
from .env.example on acme-web as the enabled features require them.
pnpm --filter @acme/server exec wrangler secret put DATABASE_DIRECT_URL
pnpm --filter @acme/server exec wrangler secret put ALLOWED_ORIGINS
pnpm --filter @acme/web exec wrangler secret put DATABASE_DIRECT_URL
pnpm --filter @acme/web exec wrangler secret put SITE_URLProduction schema migrations remain an explicit operation:
pnpm --filter @acme/db db:migrate:prodWrangler deploys acme-web and acme-server to their workers.dev URLs by default. Add custom
domains in Cloudflare and update the web Worker's SITE_URL, OAuth callbacks, Stripe webhooks,
and RevenueCat webhooks before production use.
Cloudflare is preconfigured, not mandatory. The default dev, build, and start scripts still
use ordinary Next.js and Node, so the web app can deploy to Vercel or another Next.js host and the
Hono app can run on any supported Node/container host. Only *:cloudflare scripts select vinext,
workerd-specific Prisma output, and Wrangler.
Useful local commands:
# Normal local development stays on Next.js and Node.
pnpm dev
# Cloudflare-only checks and previews are opt-in.
pnpm --filter @acme/web build:cloudflare
pnpm --filter @acme/web preview:cloudflare
pnpm --filter @acme/server build:cloudflare
pnpm --filter @acme/server dev:cloudflare# Install dependencies
pnpm install
# Type checking
pnpm typecheck
# Linting
pnpm lint
# Format code
pnpm format
# Clean all build artifacts
pnpm clean# Run migrations
cd packages/db && pnpm db:migrate
# Deploy migrations (production)
cd packages/db && pnpm db:migrate:prodAll packages use the @acme/ namespace. To rename:
- Find and replace
@acme/with@your-company/ - Update all
package.jsonfiles - Update import statements
- Turborepo Documentation
- Expo Documentation
- Next.js Documentation
- Better Auth Documentation
- Prisma Documentation
- tRPC Documentation
- NativeWind Documentation
- Cloudflare Workers Documentation
- vinext Documentation
- Hono Documentation
This project is licensed under the MIT License - see the LICENSE file for details.
- Inspired by create-t3-turbo
- Built with tools from the JavaScript ecosystem