Package Exports
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (create-stackr) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
create-stackr
v0.5: Multi-microservice monorepo layout is the new default. Each project gets an isolated
auth/service plus one or more base services that can grow viastackr add service. Breaking change — see Upgrading from v0.4.
Scaffold production-ready multi-microservice monorepos with isolated Fastify services, BetterAuth, per-service Postgres + Redis, Docker Compose, and optional Expo / Next.js frontends per service.
Quick Start
# Create a fresh monorepo with auth + core
npx create-stackr@latest my-app --defaults
# Create a monorepo with extra base services pre-scaffolded
npx create-stackr@latest my-app --defaults --with-services scout,manage
# Months later, grow the monorepo from inside the project
cd my-app
stackr add service walletcreate-stackr ships two binaries:
| Binary | When to use |
|---|---|
create-stackr |
Initial scaffold — run once per project |
stackr |
Post-init operations (add service, migrations ack) — run from inside a generated project |
Features
- Multi-microservice monorepo - Isolated
auth/+ one or more base services, each with its own Postgres + Redis + backend container - Three auth middleware flavors -
standard(cookie forwarding),role-gated(requires a role),flexible(cookie or device session) - Grow your monorepo over time -
stackr add service <name>scaffolds a new service, wires it into docker-compose, and updates auth's additionalFields - React Native (Expo) - Cross-platform mobile development, per service
- Next.js Web App - App Router, per service
- Node.js Backend - Fastify + PostgreSQL + Redis, per service
- ORM Flexibility - Monorepo-wide choice of Prisma (default) or Drizzle ORM
- BetterAuth Authentication - Dedicated auth service with email/password + OAuth providers (Google, Apple, GitHub)
- SDK Integrations - RevenueCat, Adjust, Scate, per service
- Docker Compose - Marker-block regeneration preserves hand-written additions
stackr.config.jsonas source of truth - Durable on-disk contract describing the monorepo shape- Pending-migration sentinel - Auto-tracks schema changes and refuses further commands until the user runs the DB migration
Requirements
- Node.js: >= 18.0.0
- npm: >= 8.0.0 (or yarn/bun equivalent)
- Git: For repository initialization
- Docker: For backend development (optional but recommended)
Available Presets
Minimal
Basic fullstack app with essential features:
- Email/Password Authentication (BetterAuth)
- Session Management
- Tab Navigation
- PostgreSQL Database (Prisma or Drizzle)
- Docker Support
Full-Featured
All integrations and features included:
- 3-page Onboarding Flow
- Full Authentication (Email + Google + Apple OAuth)
- Email Verification & Password Reset
- Subscription Paywall
- Session Management
- Tab Navigation
- RevenueCat Integration
- Adjust Integration
- Scate Integration
- ATT (App Tracking Transparency)
- PostgreSQL (Prisma or Drizzle) + BullMQ Event Queue
- Docker Support
Analytics-Focused
Analytics SDKs with basic features:
- 2-page Onboarding Flow
- Email/Password Authentication
- Session Management
- Tab Navigation
- Adjust Integration
- Scate Integration
- ATT (App Tracking Transparency)
- PostgreSQL (Prisma or Drizzle) + BullMQ Event Queue
- Docker Support
CLI Usage
create-stackr — project init
# Interactive mode
npx create-stackr my-app
# With preset template
npx create-stackr my-app --template minimal
npx create-stackr my-app --template full-featured
npx create-stackr my-app --template analytics-focused
# With defaults (minimal preset, no prompts)
npx create-stackr my-app --defaults
# Multi-service at init time
npx create-stackr my-app --defaults --with-services scout,manage
# No auth service (backend-only stack with no forwarding middleware)
npx create-stackr my-app --no-auth --service-name api
# Show help
npx create-stackr --help
# Verbose output
npx create-stackr my-app --verbosestackr — post-init operations
Run from inside a generated project.
# Scaffold a new service (backend only)
stackr add service wallet
# Add a new service with a dedicated web frontend
stackr add service wallet --web
# Add a new service without running package manager install
stackr add service wallet --no-install
# Force compose regen when the managed marker blocks are missing
stackr add service wallet --force
# After running the DB migration printed in the next-steps output, clear
# the pending-migration sentinel so further stackr commands work:
stackr migrations ack authThe pending-migration flow
When stackr add service changes auth's schema (by adding a new
has<Service>Account additional field), the DB is out of sync with the
regenerated auth/backend/lib/auth.ts. Until a migration runs, any later
sign-in from the new service would silently fail.
To prevent that, stackr writes a pendingMigrations entry to
stackr.config.json and every subsequent stackr subcommand refuses
until you resolve it:
stackr add service wallet # writes pendingMigrations: [ ...auth ]
# → run the printed drizzle-kit / prisma command by hand
stackr migrations ack auth # clears the sentinel
stackr add service treasury # now allowedPass --force to stackr add service to stack a new pending migration
on top of existing ones. Use stackr migrations ack <service> once per
entry after running each migration.
What You Get
Mobile App (Expo)
- React Native with Expo Router
- TypeScript with strict mode
- Zustand state management
- File-based routing
- Native OAuth SDKs (Google, Apple)
- Ready for EAS Build
Web App (Next.js)
- Next.js 14+ with App Router
- TypeScript with strict mode
- Shared authentication with mobile
- Tailwind CSS styling
Backend
- Fastify REST API
- PostgreSQL with Prisma OR Drizzle ORM
- BetterAuth authentication
- OAuth providers (Google, Apple, GitHub)
- Docker development environment
- Optional BullMQ event queue
Optional Integrations
- RevenueCat (subscriptions)
- Adjust (attribution)
- Scate (engagement)
- ATT (iOS tracking transparency)
Generated Project Structure
my-app/
├── mobile/ # React Native (Expo) app
│ ├── app/ # Expo Router screens
│ ├── src/ # Components, services, utils
│ └── assets/ # Images, fonts
├── web/ # Next.js web app
│ ├── app/ # App Router pages
│ └── src/ # Components, services
├── backend/ # Node.js backend
│ ├── controllers/ # API routes
│ ├── domain/ # Business logic
│ ├── prisma/ # Prisma schema (if selected)
│ └── drizzle/ # Drizzle schema (if selected)
├── docker-compose.yml # Local development
└── scripts/ # Setup utilitiesGenerated Project Setup
After generating your project:
Backend Setup (Required First)
# Start services (PostgreSQL, Redis)
docker-compose up -d
# Install dependencies and setup database
cd backend
bun install
bun run db:migrate
bun run db:generate
bun start # or bun run dev for watch modeThe backend runs on http://localhost:8080.
Mobile App Setup
cd mobile
bun install
bun startPress i for iOS simulator or a for Android emulator.
Web App Setup
cd web
bun install
bun run devOpen http://localhost:3000 in your browser.
Verifying Everything Works
- Backend health:
curl http://localhost:8080/health - Database connection: Check backend logs for "Database connected"
- Web app: Visit
http://localhost:3000- should show home page - Mobile app: Should load without red error screen
- Auth flow: Register a test user on web, verify in database
Common Setup Issues
| Issue | Solution |
|---|---|
| "Port 8080 in use" | Stop other services or change PORT in backend .env |
| "Database connection refused" | Ensure Docker containers are running: docker ps |
| "Module not found" | Delete node_modules and reinstall with bun install |
| "CORS error" | Check CORS_ORIGINS includes your frontend URL |
| "Apple Sign In fails" | Apple requires HTTPS - use ngrok or test in production |
Database Commands (ORM-agnostic)
Both Prisma and Drizzle use the same npm scripts:
npm run db:generate # Generate ORM types
npm run db:push # Push schema changes
npm run db:migrate # Run migrations
npm run db:studio # Open visual database browserWeb Platform Details
Project Structure
web/
├── src/
│ ├── app/ # Next.js App Router
│ │ ├── (auth)/ # Auth pages (login, register, etc.)
│ │ ├── (app)/ # Protected app pages (dashboard, settings)
│ │ ├── auth/ # OAuth callback routes
│ │ ├── globals.css # Global styles with dark mode
│ │ └── layout.tsx # Root layout with providers
│ ├── components/
│ │ ├── ui/ # shadcn/ui components
│ │ ├── auth/ # Auth forms and buttons
│ │ ├── settings/ # Settings components
│ │ └── providers/ # Context providers
│ ├── lib/
│ │ ├── auth/ # Auth utilities and actions
│ │ └── utils.ts # Utility functions
│ └── store/ # Zustand stores
├── public/ # Static assets
├── next.config.ts # Next.js configuration
└── package.jsonEnvironment Variables
Create a .env file in the web/ directory:
# Public URL of the web app (used for OAuth callbacks)
NEXT_PUBLIC_APP_URL=http://localhost:3000
# Backend API URL (server-side only, used by server actions)
BACKEND_URL=http://localhost:8080Running the Web App
cd web
bun install
bun run devThe app runs on http://localhost:3000 by default.
Authentication on Web
The web platform uses cookie-based sessions (unlike mobile which uses token storage):
| Feature | Mobile | Web |
|---|---|---|
| Session Storage | AsyncStorage + Secure Store | HTTP-only Cookies |
| Token Refresh | Manual refresh | Automatic via cookies |
| OAuth Flow | Deep links + native SDKs | Browser redirects |
| CSRF Protection | Not needed | Built into Better Auth |
OAuth Configuration
For OAuth to work on web, ensure your OAuth providers have the correct redirect URIs pointing to the backend (Better Auth handles the OAuth callback):
Google Cloud Console:
http://localhost:8080/api/auth/callback/google (development)
https://api.yourdomain.com/auth/callback/google (production)Apple Developer Console:
Important: Apple Sign In requires HTTPS for redirect URIs. It will not work with
http://localhostin development. You must either:
- Use a tunneling service (ngrok, Cloudflare Tunnel) to get an HTTPS URL for the backend
- Test Apple Sign In only in production/staging environments with valid HTTPS
- Use the mobile app for Apple Sign In testing during development
https://api.yourdomain.com/auth/callback/apple (production only - HTTPS required)GitHub OAuth App:
http://localhost:8080/api/auth/callback/github (development)
https://api.yourdomain.com/auth/callback/github (production)CORS Configuration
The backend must allow web origins. In backend/.env:
# Comma-separated list of allowed origins
CORS_ORIGINS=http://localhost:3000,https://yourdomain.comDark Mode
The web app includes full dark mode support:
- Uses
next-themesfor theme management - Theme persists in localStorage
- Respects system preference by default
- Toggle via the
ThemeTogglecomponent
Deploying Web
Deploy to any Next.js hosting:
- Vercel (recommended):
vercel deploy - Netlify: Add
netlify.tomlconfiguration - Docker: Use the provided Dockerfile
- Node.js hosting: Run
bun run build && bun start
Remember to update environment variables for production:
NEXT_PUBLIC_APP_URL=https://yourdomain.com
BACKEND_URL=https://api.yourdomain.comDeployment
Mobile App
Use EAS Build for deployment:
cd mobile
npm install -g eas-cli
eas build --platform ios
eas build --platform androidBackend
Deploy to any Node.js hosting:
- Heroku
- Railway
- Render
- AWS/GCP/Azure
- Your own VPS
Configure environment variables from .env.example.
Development
# Install dependencies
npm install
# Build
npm run build
# Run tests
npm test
# Test with coverage
npm run test:coverage
# Run unit tests
npm run test:unit
# Run integration tests
npm run test:integration
# Run e2e tests
npm run test:e2e
# Lint code
npm run lint
# Format code
npm run format
# Type checking
npm run typecheckTroubleshooting
"Command not found: create-stackr"
Make sure npx is working:
npx --versionTry with explicit version:
npx create-stackr@latest my-app"EACCES: permission denied"
Don't use sudo with npx. If you get permission errors:
mkdir ~/.npm-global
npm config set prefix '~/.npm-global'
export PATH=~/.npm-global/bin:$PATHGenerated project TypeScript errors
Make sure you're using Node.js >= 18:
node --versionDocker issues
Ensure Docker is running:
docker --version
docker psWeb: Hydration mismatch errors
If you see "Hydration failed because the initial UI does not match" errors:
- Theme-related: Ensure
suppressHydrationWarningis on the<html>tag inlayout.tsx - Auth state: The
AuthHydratorcomponent handles this - don't access auth state in server components - Date/time rendering: Use
useEffectfor time-sensitive content
// Bad - causes hydration mismatch
const date = new Date().toLocaleDateString();
// Good - renders client-side only
const [date, setDate] = useState<string>();
useEffect(() => {
setDate(new Date().toLocaleDateString());
}, []);Web: OAuth callback fails
- Check redirect URI: Must exactly match what's configured in OAuth provider
- Check CORS: Backend must allow your web origin
- Check cookies: Ensure you're not blocking third-party cookies in development
- Apple Sign In: Remember that Apple requires HTTPS - won't work on localhost
Debug with:
# Check backend logs
docker logs backend-container
# Verify CORS headers
curl -I http://localhost:8080/api/auth/sessionWeb: Apple Sign In not working in development
Apple Sign In requires HTTPS redirect URIs and will not work with http://localhost. Options:
- Use ngrok or Cloudflare Tunnel: Create an HTTPS tunnel to your backend
ngrok http 8080 # Use the https://xxx.ngrok.io/api/auth/callback/apple URL as your redirect URI
- Skip Apple in dev: Test Apple Sign In only in staging/production environments
- Use mobile: Apple Sign In works in development on the mobile app via native SDKs
Web: Session not persisting
- Cookie settings: In development, cookies require
SameSite=LaxandSecure=false - Domain mismatch: Ensure frontend and backend are on the same domain (or properly configured for cross-domain)
- Check browser DevTools: Network tab -> Cookies to see if session cookie is being set
Web: 404 on refresh (deployed)
If routes work initially but 404 on refresh:
- Vercel: Should work out of the box
- Netlify: Install the
@netlify/plugin-nextjsplugin. Do NOT use SPA-style redirects - Next.js uses SSR:# netlify.toml [[plugins]] package = "@netlify/plugin-nextjs" - Self-hosted Node.js: Ensure you're running
next start(not serving static files) - Docker/Nginx: Use a reverse proxy to the Node.js server, not static file serving
Web: Build fails with module errors
# Clear Next.js cache
rm -rf web/.next
# Reinstall dependencies
rm -rf web/node_modules
bun installFAQ
Q: What's the difference between presets? A: Minimal has basic features, Full-Featured has everything including OAuth and all SDKs, Analytics-Focused has Adjust + Scate for attribution.
Q: Can I add features later? A: Yes, but it's easier to start with more features and remove what you don't need.
Q: Is this production-ready? A: The generated code is production-quality. Test thoroughly before deploying.
Q: What about web support? A: Yes! We support both Expo for mobile (iOS & Android) and Next.js for web. Both share the same backend and authentication.
Q: Which ORM should I choose? A: Prisma (default) is great for most projects with its auto-generated client and migrations. Drizzle is lighter-weight, SQL-first, and better for serverless environments. Both work identically with BetterAuth.
Q: What OAuth providers are supported? A: Google, Apple, and GitHub. Google and Apple have native SDK support on mobile with automatic browser fallback. GitHub uses browser-based OAuth only.
Q: Can I customize the templates? A: Not yet, but template customization is planned for future versions.
Q: Can I use the web app without mobile? A: Yes! During CLI setup, select "web" as your only platform. This generates just the web app and backend, without any mobile code.
Q: Why does web use cookies instead of tokens? A: Cookie-based sessions are more secure for web applications - they're HTTP-only (no JavaScript access), automatically included in requests, and protected against XSS attacks. Mobile apps use secure token storage because they don't have cookie support.
Q: Can I share authentication between web and mobile? A: Yes, both platforms authenticate against the same backend and share the same user database. However, sessions are separate - logging in on web doesn't log you in on mobile and vice versa.
Q: Why doesn't Apple Sign In work on localhost? A: Apple requires HTTPS for OAuth redirect URIs. Use ngrok or a similar tunneling service for local development, or test Apple Sign In in a staging environment with a valid SSL certificate.
Q: How do I add more pages to the web app?
A: Create new files in web/src/app/. For protected pages, put them in (app)/. For public pages, put them directly in app/. See the Next.js App Router docs.
Q: How do I customize the web design?
A: The web app uses Tailwind CSS and shadcn/ui components. Edit globals.css for color scheme changes, or modify individual components in src/components/ui/.
Q: Does the web app support SSR?
A: Yes, Next.js App Router uses React Server Components by default. Client components (marked with "use client") handle interactive features like forms and auth state.
Roadmap
Completed in v0.5.0
- Multi-microservice monorepo scaffolding (
auth/+ one or more base services) - Second CLI binary:
stackr add service <name>for post-init service scaffolding -
stackr.config.jsondurable source of truth written at generation time - Three auth middleware flavors (standard, role-gated, flexible) with HTTP forwarding
- Marker-block
docker-compose.ymlregeneration that preserves user edits - Pending-migration sentinel (
stackr migrations ack) for auth schema changes - Programmatic docker-compose + per-service env prefixing (
AUTH_DB_*,CORE_DB_*, …) - Root
package.jsonwithcreate-stackrpinned as a devDependency sonpx stackrworks inside generated projects
Completed in v0.4.0
- AI coding tool selection (Claude Code, Codex, Cursor, Windsurf)
- Architectural documentation (DESIGN.md, BEST_PRACTICES.md) in generated projects
- Backend repository/service layer separation
- React 19 patterns in web templates (useActionState)
- Docker naming, type safety, and DRY improvements
Completed in v0.3.0
- Two-Factor Authentication for mobile and web
- Enhanced security headers for Next.js
- Improved CLI UX for platform selection
- Better error handling and user feedback
- Improved documentation site
Completed in v0.2.0
- OAuth support (Google, Apple, GitHub)
- BetterAuth authentication framework
- Drizzle ORM as alternative to Prisma
- Next.js web app support
- Native OAuth SDKs with browser fallback
- Email verification & password reset
Upcoming
- v0.6.0:
stackr add auth(retroactively add auth to a--no-authproject),stackr migrate(automated DB migrations via docker or host mode), more SDK integrations (Firebase, Supabase) - v1.0.0: Stable API, production-ready
Technology Stack
CLI Framework
- Commander.js - Command-line interface framework
- Inquirer.js - Interactive prompts
- chalk - Terminal colors
- ora - Loading spinners
- boxen - Terminal boxes
- EJS - Template rendering
Generated Stack
- Expo - React Native mobile framework
- Next.js - React web framework
- Fastify - Node.js backend
- BetterAuth - Authentication framework
- Prisma - Type-safe ORM (default)
- Drizzle - SQL-first ORM (alternative)
- PostgreSQL - Database
- Redis - Caching & queues
Development
- TypeScript - Type safety
- Vitest - Testing framework
- ESLint - Linting
- Prettier - Code formatting
Project Status
Completed Features
- CLI framework using Commander.js
- Interactive prompts using Inquirer.js
- Input validation and error handling
- Three preset templates (Minimal, Full-Featured, Analytics-Focused)
- Custom configuration flow
- Comprehensive unit tests
- Type-safe configuration schema
- Package manager selection
- Template system using EJS
- File generation and copying
- Project scaffolding
- Conditional feature integration
- BetterAuth authentication integration
- OAuth providers (Google, Apple, GitHub)
- Native OAuth SDKs with browser fallback
- Drizzle ORM support as Prisma alternative
- Two-factor authentication (TOTP)
- Email verification & password reset
- Next.js web app support
Project structure
A minimal monorepo (auth + core) generated with v0.5 looks like:
my-app/
├── stackr.config.json # durable on-disk contract (source of truth)
├── docker-compose.yml # stackr managed marker blocks + your edits
├── docker-compose.prod.yml
├── .env / .env.example # per-service prefixed vars (AUTH_DB_*, CORE_DB_*, ...)
├── README.md / DESIGN.md / AGENTS.md
├── scripts/ # setup.sh, docker-dev.sh, docker-prod.sh
│
├── auth/ # BetterAuth server
│ └── backend/ # Fastify :8082
│
├── core/ # default base service (renameable)
│ ├── backend/ # Fastify :8080 — forwards cookies to auth
│ ├── web/ # optional Next.js per service
│ └── mobile/ # optional Expo per service
│
└── <extra-services>/ # added later via `stackr add service`
└── ... (same shape as core/)Non-auth services authenticate by forwarding cookies to auth's
/api/auth/get-session endpoint. Each service owns its own database,
Dockerfile, and prefixed env vars — there is no shared backend code.
Upgrading from v0.4
v0.5 is a hard breaking change. The default layout moved from a single
unified backend/ + mobile/ + web/ project to a multi-microservice
monorepo. Projects generated with v0.4 keep working as-is — stackr
does not attempt to migrate them automatically.
To adopt v0.5 for an existing project:
- Generate a fresh v0.5 project alongside your existing one:
npx create-stackr@latest my-app-v5 --defaults - Port domain code from your v0.4
backend/domainintomy-app-v5/core/backend/domain. - If your v0.4 project had multiple subsystems, split them across new
services with
stackr add service scout, etc. - Move your mobile / web code into
core/mobileandcore/web(or create a dedicated service for them).
Closest one-shot equivalent to v0.4's single-project output:
npx create-stackr@latest my-app --defaults --no-auth --service-name coreContributing
Contributions welcome! See CONTRIBUTING.md for guidelines.
Security
Generated applications include security headers by default:
- X-Content-Type-Options: Prevents MIME type sniffing
- X-Frame-Options: Prevents clickjacking attacks
- Referrer-Policy: Controls referrer information sent with requests
- Permissions-Policy: Restricts access to browser features
- Strict-Transport-Security: Enforces HTTPS connections (HSTS)
To customize security headers, edit next.config.ts in your web application.
See SECURITY.md for vulnerability reporting.
License
MIT © itharea