Skip to content

This is a template for bootstrapping a Supabase project. Its a modern TypeScript stack that combines React, TanStack Router, Hono, and more.

Notifications You must be signed in to change notification settings

amal-chandran/supabase-start

Repository files navigation

Supabase Start

This is a template for bootstrapping a Supabase project. It's a modern TypeScript stack that combines React, TanStack Router, Hono, ORPC, and more.

Tech Stack

Frontend

  • React - UI library
  • TypeScript - Type safety and improved developer experience
  • Vite - Fast build tool and dev server
  • TanStack Router - File-based routing with full type safety
  • TanStack Query - Data fetching and state management
  • TailwindCSS - Utility-first CSS for rapid UI development
  • shadcn/ui - Reusable UI components built on Radix UI
  • Better-Auth - Authentication library
  • Supabase JS - Supabase client library

Mobile (Native)

  • Expo - React Native framework for cross-platform mobile development
  • Expo Router - File-based routing for React Native
  • React Native - Mobile UI framework
  • UniWind - TailwindCSS for React Native
  • Better-Auth Expo - Authentication for mobile apps

Backend

  • Hono - Lightweight, performant server framework
  • Node.js - Runtime environment
  • Better-Auth - Authentication server
  • ORPC - Type-safe RPC framework with OpenAPI support
  • TypeScript - Type safety

API Layer

  • ORPC - End-to-end type-safe RPC with automatic OpenAPI documentation
  • Zod - Schema validation and type inference

Database & ORM

  • PostgreSQL - Database engine
  • Supabase - PostgreSQL hosting and management
  • Drizzle ORM - TypeScript-first ORM for database operations
  • Drizzle Kit - Database migration and introspection tool

Background Jobs

  • Trigger.dev - Background job processing and task scheduling

DevOps & Tooling

  • Turborepo - Optimized monorepo build system
  • pnpm - Fast, disk space efficient package manager

Better Auth vs Supabase Auth

For a comprehensive feature-by-feature comparison between Better Auth and Supabase Auth, see COMPARISON.md.

Why I Made These Choices

This section explains the rationale behind the key technology decisions in this project.

Drizzle ORM

  • Schema as Code: Drizzle allows managing database schema as TypeScript code, providing version control, code review, and better collaboration on database changes.
  • Cross-Platform Compatibility: The same schema definitions can be used for transactions in Deno as well, providing flexibility across different runtime environments.
  • AI-Friendly: Drizzle's schema definitions provide full context to AI tools, making it easier to get accurate code suggestions and assistance.
  • Type Inference: Excellent TypeScript type inference ensures type safety throughout the application, reducing runtime errors and improving developer experience.

Better Auth

  • Plugin Ecosystem: Better Auth's extensive plugin system offers unparalleled customization and extensibility compared to integrated authentication solutions. This allows for easy integration of additional features without modifying core authentication logic.
  • OAuth Access Token Management: Better Auth handles OAuth access tokens as part of the authentication system itself, making it seamless to work with third-party services that require OAuth tokens.
  • Payment Integration: The Stripe plugin makes it straightforward to integrate payment providers, handling customer creation, subscription management, and webhook processing out of the box.
  • Passkey Support: If needed, we can easily integrate expo-passkey with Better Auth for modern WebAuthn-based authentication, providing a passwordless authentication option.
  • Expo Support: Better Auth includes native Expo support via @better-auth/expo, enabling seamless authentication in React Native applications.

ORPC

  • End-to-End Type Safety: ORPC provides full type safety from server to client, eliminating the need for manual API type definitions.
  • Automatic OpenAPI Documentation: ORPC automatically generates OpenAPI/Swagger documentation from your route definitions.
  • Multiple Transport Support: Supports both RPC-style calls and RESTful endpoints with the same type-safe interface.
  • Zod Integration: Built-in Zod schema validation ensures runtime type safety and automatic request/response validation.

Project Structure

supabase-start/
├── apps/
│   ├── web/                    # Web frontend (React + Vite + TanStack Router)
│   │   ├── src/
│   │   │   ├── app/            # TanStack Router routes
│   │   │   ├── modules/       # Feature modules (auth, posts, etc.)
│   │   │   ├── shared/        # Shared components and utilities
│   │   │   └── main/          # App initialization
│   │   └── package.json
│   ├── backend/                # Backend server (Hono + ORPC)
│   │   ├── src/
│   │   │   └── app.ts         # Hono server setup with ORPC handlers
│   │   └── package.json
│   └── native/                 # Mobile app (Expo + React Native)
│       ├── app/                # Expo Router routes
│       ├── components/         # React Native components
│       └── package.json
├── packages/
│   ├── auth/                   # Authentication package (Better-Auth)
│   │   ├── src/
│   │   │   ├── better-auth.ts # Better-Auth configuration
│   │   │   └── jwt.config.ts  # JWT plugin configuration
│   │   └── package.json
│   ├── api/                    # API package (ORPC routers)
│   │   ├── src/
│   │   │   ├── routers/       # ORPC route definitions
│   │   │   ├── handlers/      # Route handlers
│   │   │   └── context.ts     # Request context creation
│   │   └── package.json
│   ├── platform/               # Platform package (Supabase + Drizzle)
│   │   ├── src/
│   │   │   ├── schema/        # Drizzle schema definitions
│   │   │   ├── drizzle.ts     # Drizzle database instance
│   │   │   └── database.types.ts # Generated database types
│   │   ├── supabase/
│   │   │   ├── migrations/    # Database migrations
│   │   │   └── signing_key.base # Base64 encoded signing key
│   │   ├── scripts/
│   │   │   └── generate-signing-key.ts
│   │   └── package.json
│   ├── trigger/                # Background jobs (Trigger.dev)
│   │   ├── src/
│   │   │   ├── tasks/         # Background task definitions
│   │   │   └── repository/    # Data access layer
│   │   └── package.json
│   └── config/                 # Shared TypeScript configuration
│       └── package.json
├── package.json                # Root package.json (monorepo config)
├── pnpm-workspace.yaml         # pnpm workspace configuration
└── turbo.json                  # Turborepo configuration

How to Setup

Prerequisites

  • Node.js (v18 or higher)
  • pnpm (v10 or higher) - Install with npm install -g pnpm
  • Supabase CLI (for local development) - Install with npm install -g supabase

Setup Steps

  1. Clone the repository and install dependencies:

    git clone <repository-url>
    cd supabase-start
    pnpm install
  2. Generate signing key (inside platform package):

    cd packages/platform
    pnpm run generate:signing-key

    This will create signing_key.base and signing_key.json files in packages/platform/supabase/.

  3. Set up environment variables:

    • In packages/auth/, create a .env file (check for .env.example if available)
    • Add SUPABASE_SIGNING_KEY to packages/auth/.env:
      • Read the content from packages/platform/supabase/signing_key.base
      • Add it as: SUPABASE_SIGNING_KEY=<content-from-signing_key.base>
    • Add CORS_ORIGIN to packages/auth/.env (e.g., http://localhost:3001)
  4. Start Supabase local instance:

    cd packages/platform
    pnpm run dev

    This will start the local Supabase instance and display the API URL and anon/public key.

  5. Update environment variables:

    • In apps/web/.env, set VITE_SUPABASE_PUBLISHABLE_KEY to the anon/public key from step 4
    • Also update VITE_SUPABASE_URL with the API URL from step 4
    • In apps/backend/.env, set CORS_ORIGIN (e.g., http://localhost:3001)
  6. Reboot Supabase (after generating signing key):

    cd packages/platform
    pnpm run supabase:reset

    This stops and restarts the local Supabase instance to apply the new signing key.

  7. Start development servers:

    pnpm run dev

The web application will be available at http://localhost:3001 and the API/auth server will be running at http://localhost:3000.

Running Native App

To run the mobile app:

pnpm run dev:native
# or
cd apps/native
pnpm run dev

This will start the Expo development server. You can then:

  • Press i to open iOS simulator
  • Press a to open Android emulator
  • Scan QR code with Expo Go app on your device

Database Migrations

This project uses Drizzle ORM combined with Supabase for managing database migrations. This combination allows for easy migration management and database resets.

Generating Migrations

Option 1: Custom migration (for seed data or custom SQL):

cd packages/platform
pnpm run db:generate:custom --name=create-bucket

Option 2: Schema-based migration (recommended for schema changes):

  1. Update the schema files in packages/platform/src/schema/
  2. Generate migration from root:
    pnpm run db:generate
    Or from the platform package:
    cd packages/platform
    pnpm run db:generate

Applying Migrations

To apply migrations to the database:

pnpm run db:migrate

Or from the platform package:

cd packages/platform
pnpm run db:migrate

Database Studio

To open Drizzle Studio for database inspection:

pnpm run db:studio

Database Reset

To reset the database to a fresh state (useful during development):

cd packages/platform
pnpm run db:reset

This will drop all tables and reapply all migrations from scratch.

Available Scripts

Root Level

  • pnpm run dev - Start all applications in development mode
  • pnpm run build - Build all applications
  • pnpm run dev:web - Start only the web application
  • pnpm run dev:server - Start only the backend server
  • pnpm run dev:native - Start only the native mobile app
  • pnpm run check-types - Check TypeScript types across all apps
  • pnpm run db:generate - Generate database migrations from schema
  • pnpm run db:migrate - Apply database migrations
  • pnpm run db:push - Push schema changes directly to database (development only)
  • pnpm run db:studio - Open Drizzle Studio for database inspection

Platform Package (packages/platform)

  • pnpm run generate:signing-key - Generate JWT signing key for Supabase
  • pnpm run dev - Start Supabase local instance
  • pnpm run supabase:reset - Stop and restart Supabase local instance
  • pnpm run db:generate - Generate database migrations from schema
  • pnpm run db:generate:custom - Generate custom migration (for seed data or custom SQL)
  • pnpm run db:migrate - Apply database migrations
  • pnpm run db:reset - Reset database to fresh state
  • pnpm run db:studio - Open Drizzle Studio
  • pnpm run generate:database-types - Generate TypeScript types from database schema

Backend Package (apps/backend)

  • pnpm run dev - Start backend server in development mode
  • pnpm run build - Build backend server
  • pnpm run start - Start production server
  • pnpm run check-types - Check TypeScript types

Auth Package (packages/auth)

  • pnpm run check-types - Check TypeScript types
  • pnpm run auth:generate - Generate Better Auth schema types

Web Package (apps/web)

  • pnpm run dev - Start web app in development mode (port 3001)
  • pnpm run build - Build web app for production
  • pnpm run serve - Preview production build
  • pnpm run check-types - Check TypeScript types

Native Package (apps/native)

  • pnpm run dev - Start Expo development server
  • pnpm run start - Start Expo development server
  • pnpm run android - Run on Android emulator
  • pnpm run ios - Run on iOS simulator
  • pnpm run web - Run in web browser
  • pnpm run prebuild - Generate native projects

Deployment

Hosting on Vercel

This project is designed to be deployed on Vercel:

Deployment Steps

  1. Connect your repository to Vercel

  2. Configure build settings:

    • Root directory: Leave as default (or set to project root)
    • Build command: pnpm run build
    • Output directory: Set per app (e.g., apps/web/dist for web app)
    • Install command: pnpm install
  3. Set environment variables in Vercel:

    • Add all required environment variables from .env.example files
    • For production, use your production Supabase credentials
    • Ensure CORS_ORIGIN is set to your production frontend URL
  4. Deploy:

    • Vercel will automatically detect and deploy both the frontend and backend
    • The backend server (Hono) will be deployed as Vercel Functions
    • The web app (Vite) will be deployed as static assets with client-side routing
    • ORPC endpoints will be available at /rpc/* and OpenAPI docs at /api-reference/*

For more details, refer to:

About

This is a template for bootstrapping a Supabase project. Its a modern TypeScript stack that combines React, TanStack Router, Hono, and more.

Topics

Resources

Stars

Watchers

Forks

Languages