β οΈ Status: This project is currently in active development. Features and APIs may change.
- About the Project
- β¨ Features
- π οΈ Technologies Used
- π How to Run
- π Internationalization
- π¨ UI/UX
- π Authentication
- πΎ Database & Backend
- π¦ Project Structure
- π οΈ Available Scripts
- π Code Conventions
- π Deployment
- π€ Contributing
- π Bug Reports
- π License
SaaS Seed is a modern, production-ready starter template designed specifically for building micro SaaS applications. Built on top of Next.js 16 and Supabase, this starter provides all the essential features and infrastructure that a micro SaaS needs to get up and running quickly.
This project is currently in active development and includes:
- π Complete authentication system with Better Auth (stateless)
- π€ User management with Supabase Auth
- π³ Payment processing with Stripe (subscriptions and trials)
- π Internationalization (i18n) support
- π¨ Modern UI/UX with Shadcn/UI components
- π Dashboard with analytics and data visualization
- π₯ Team management features
- π Notifications and toast system
- π Dark mode support
- π± Fully responsive design
- β‘ Type-safe with TypeScript
- π― Production-ready architecture
Perfect for entrepreneurs and developers who want to focus on building their product features instead of setting up infrastructure from scratch.
- β‘ Next.js 16 - React framework with advanced features
- βοΈ React 19 - JavaScript library for building interfaces
- π TypeScript - JavaScript superset with static typing
- π¨ Tailwind CSS - Utility-first CSS framework
- π Radix UI - Accessible primitive components
- πͺ Shadcn/UI - High-quality UI components built with Radix UI and Tailwind CSS
- π next-themes - Light/dark theme support
- β¨ tw-animate-css - CSS animations
- π Sonner - Toast notification system
- π React Hook Form - Form management
- β Zod - Schema validation
- π @hookform/resolvers - Validator integration
- π Better Auth - Complete authentication solution
- πͺ js-cookie - Cookie management
- π Supabase - Open source Firebase alternative with PostgreSQL (Auth only)
- π§ Resend - Email API for transactional emails
- π³ Stripe - Payment processing and subscription management
- π i18next - Internationalization framework
- πΊοΈ zod-i18n-map - Internationalized validation
- π¦ pnpm - Fast and efficient package manager
- πΆ Husky - Git hooks
- π ESLint - Code linting
- π Prettier - Code formatting
- π commitlint - Commit message linting
- Clone the repository
git clone [repository-url]- Install dependencies
pnpm install- Set up environment variables
Copy the env.example.txt file to .env.local:
cp env.example.txt .env.localOr create .env.local manually using env.example.txt as a reference.
Then update the values in .env.local with your actual credentials:
# Better Auth (Required)
BETTER_AUTH_SECRET=your_secret_key_min_32_characters
BETTER_AUTH_URL=http://localhost:3000
# Google OAuth (Required)
GOOGLE_CLIENT_ID=your_google_client_id
GOOGLE_CLIENT_SECRET=your_google_client_secret
# Supabase Auth (Required)
NEXT_PUBLIC_SUPABASE_URL=https://[project-ref].supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=your_supabase_anon_key
SUPABASE_SERVICE_ROLE_KEY=your_supabase_service_role_key
# Stripe (Required)
STRIPE_SECRET_KEY=sk_test_your_stripe_secret_key
STRIPE_DEFAULT_PRICE_ID=price_your_default_price_id
# Resend (Required)
RESEND_API_KEY=re_your_resend_api_key
RESEND_FROM_EMAIL=noreply@yourdomain.com
# API URL (Required)
NEXT_PUBLIC_API_URL=http://localhost:3000Important:
- Generate
BETTER_AUTH_SECRETwith:openssl rand -base64 32 - Get Supabase credentials from: Supabase Dashboard > Settings > API
- Get Stripe credentials from: Stripe Dashboard > Developers > API keys
- Get
STRIPE_DEFAULT_PRICE_IDfrom: Stripe Dashboard > Products > Your Product > Pricing - Get Resend API key from: Resend Dashboard > API Keys
- Run the development server
pnpm dev- For production build
pnpm build- To start in production
pnpm startThe project uses a custom i18n strategy based on JSON dictionaries and route segments for complete multi-language support.
- Route-based localization - URLs include locale (
/en/dashboard,/pt/dashboard) - JSON dictionaries - Translation files organized by namespace in
src/locales/ - Zod i18n integration - Form validation messages automatically translated
- Cookie persistence - Language preference stored in
NEXT_LOCALEcookie - Type-safe translations - Full TypeScript support for all dictionaries
- Lazy loading - Translations loaded only when needed
- English (en)
- Portuguese (pt)
Server Components:
const dict = await getDictionary(locale);
return <h1>{dict.dashboard.title}</h1>;Client Components:
<AuthForm translation={dict} mode="sign-in" />See ADR-007: Internationalization Strategy for detailed implementation.
- Custom design system based on Tailwind CSS and Shadcn/UI
- Reusable and accessible components from Shadcn/UI library
- Light/dark theme support with next-themes
- Smooth and responsive animations with tw-animate-css
- Responsive layout for all devices
- Consistent design language across the application
- High-quality, accessible UI components
- Modern and clean interface design
- β User Authentication - Complete auth system with magic links and Google OAuth
- β Team Management - Multi-user support with role-based access control
- β Dashboard - Analytics dashboard with charts and metrics
- β Internationalization - Multi-language support (PT/EN)
- β Theme System - Light/dark mode with system preference detection
- β Responsive Design - Mobile-first, works on all devices
- β Type Safety - Full TypeScript coverage
- β Component Library - Pre-built, accessible UI components following shadcn/ui patterns
- β Supabase Auth Integration - User management and authentication via Supabase Auth
- β Stripe Integration - Payment processing, subscriptions, and trial management
- β Email Service - Transactional emails with Resend (magic links, notifications)
- β Environment Validation - Type-safe environment variables with Zod
- β API Routes - Serverless API endpoints
- β Route Protection - Proxy-based authentication (Next.js 16)
- Robust authentication system with Better Auth
- Support for multiple authentication providers (magic links, Google OAuth)
- Stateless session management - Sessions stored in encrypted cookies (JWE)
- Cookie cache - 7-day session duration with automatic refresh
- Automatic user sync - Users are automatically synced to Supabase Auth and Stripe
- Trial subscriptions - New users automatically get a 14-day free trial
- Secure session management with encrypted cookies
- Route protection for authenticated areas
- Proxy-based authentication flow (Next.js 16)
- Magic link authentication (passwordless)
- No database required for Better Auth (stateless mode)
When a user signs in (via magic link or OAuth), the following happens automatically:
- Better Auth - Creates/validates session in encrypted cookies
- Supabase Auth - User is synced to
auth.userstable - Stripe - Customer is created/updated in Stripe
- Subscription - Trial subscription is created (14 days) if it doesn't exist
- Metadata - User metadata is updated with Stripe customer ID and subscription info
All of this happens automatically via the after hook in Better Auth configuration.
- User Management - User accounts stored in Supabase Auth (
auth.users) - User Metadata - Payment and subscription data stored in
user_metadata - Service Role Key - Required for server-side user management operations
- Type-safe API - Full TypeScript support for Supabase operations
- Customer Management - Automatic customer creation/update on user sign-up
- Subscription Management - Trial subscriptions with automatic creation
- Payment Processing - Ready for payment method collection and billing
- Webhook Support - Webhook handlers for subscription events
# Link to your Supabase project
pnpm db:link
# Create a new migration (for Supabase database schema changes)
pnpm db:migration:new
# Push migrations to database
pnpm db:pushNote: These scripts are for Supabase database migrations (if you need custom tables). Better Auth runs in stateless mode and doesn't require database migrations.
/
βββ proxy.ts # Proxy for authentication and i18n (Next.js 16)
βββ src/
βββ app/ # Next.js pages and layouts
β βββ api/ # API routes
β β βββ auth/ # Better Auth API routes
β β βββ webhooks/ # Webhook handlers (Stripe)
β β βββ ... # Other API routes
β βββ [lang]/ # Internationalized routes
βββ components/ # Reusable components
β βββ container/ # Layout components and forms
β βββ features/ # Feature components
β βββ providers/ # Context providers
β βββ ui/ # UI components (Shadcn/UI)
βββ hooks/ # Custom hooks
βββ lib/ # Utilities and configurations
β βββ auth/ # Better Auth configuration
β βββ ... # Other utilities
βββ locales/ # Translation files
βββ models/ # TypeScript models
β βββ constants/ # Constants
β βββ emails/ # Email templates
β βββ enums/ # Enums
β βββ interfaces/ # TypeScript interfaces
β β βββ components/ # Component interfaces
β β βββ services/ # Service interfaces
β βββ mocks/ # Mock data
β βββ schemas/ # Zod schemas
β βββ types/ # TypeScript types
βββ services/ # Services and APIs
β βββ auth/ # Authentication services (Supabase sync)
β βββ payment/ # Payment services (Stripe)
β βββ ... # Other services
βββ server/ # Server-side utilities
βββ actions.ts # Server actions
βββ resend.ts # Resend email client
βββ stripe.ts # Stripe client
βββ supabase.ts # Supabase clients (anon + admin)
The proxy handles (Next.js 16):
- π Route protection for authenticated routes
- π Authentication redirects
- π Internationalization routing
- π― Public route access
Key features:
- Protects
/dashboard/*routes - Redirects authenticated users from auth pages
- Redirects unauthenticated users to sign-in
- Handles locale detection and routing
- Supports multiple languages (pt, en)
- Runs on Node.js runtime
For custom components that don't depend on Shadcn/UI updates, it's necessary to create specific interfaces:
src/
βββ models/
β βββ interfaces/
β β βββ component-name.ts # Interface for the component
β β βββ ...
β βββ ...
Example of interface structure:
// src/models/interfaces/component-name.ts
import { ReactNode } from "react";
export interface ComponentNameProps {
children?: ReactNode;
className?: string;
// Other component-specific props
}Benefits of this approach:
- Clear separation between Shadcn/UI components and custom components
- Better maintainability and scalability
- Facilitates documentation and code understanding
- Allows independent evolution of custom components
pnpm dev- Starts the development serverpnpm build- Creates production buildpnpm start- Starts the production server
pnpm lint- Runs ESLint and fixes issuespnpm format- Formats code with Prettier
pnpm test:e2e- Run E2E tests with Playwrightpnpm test:e2e:ui- Run E2E tests with UIpnpm test:e2e:headed- Run E2E tests in headed modepnpm test:e2e:debug- Run E2E tests in debug modepnpm test:e2e:report- Show test report
pnpm db:link- Link to Supabase projectpnpm db:migration:new- Create new migrationpnpm db:push- Push migrations to database
pnpm auth:generate- Generate Better Auth types
pnpm prepare- Sets up git hooks (Husky)
- ESLint - Code linting with Next.js config
- Prettier - Automatic code formatting
- TypeScript - Full type safety across the codebase
- Conventional Commits - Standardized commit messages
The project uses a hybrid state management approach:
| State Type | Solution | Usage | Persistence |
|---|---|---|---|
| Server State | React Query (TanStack Query) | API calls, subscriptions | In-memory cache |
| UI State | Zustand | Modals, loading states | No |
| User Preferences | Zustand + persist | Locale, sidebar state | localStorage |
| Form State | React Hook Form | Form inputs | No |
| Theme | next-themes | Light/dark mode | localStorage |
| Session | Better Auth | Authentication | Cookie |
Example:
// UI Store
const { isOpen, open, close } = useCommandDialog();
// User Preferences (persisted)
const { locale, setLocale } = useLocale();See ADR-008: State Management for details.
- Shadcn/UI Components - Located in
src/components/ui/ - Custom Components - Located in
src/components/containers/andsrc/components/features/ - Component Interfaces - Defined in
src/models/interfaces/components/ - Type Safety - All components have TypeScript interfaces
- Upstash Redis - Distributed cache and rate limiting
- Sliding Window Algorithm - For rate limiting
- Fail Open Strategy - Application continues if Redis fails
- Rate Limit Configurations:
- STRICT: 10 req/min (Resend API)
- MODERATE: 30 req/min (Checkout, Subscription)
- RELAXED: 100 req/min (Webhooks)
See ADR-004: Caching & Rate Limiting for details.
- Sentry - Error tracking and performance monitoring
- Session Replay - For debugging user sessions
- Core Web Vitals - Performance metrics (LCP, FID, CLS, INP, TTFB)
- Source Maps - Readable stack traces in production
- Privacy-First - Text masking and media blocking in replays
See ADR-006: Monitoring for details.
- Tailwind CSS v4 - Utility-first CSS framework
- Shadcn/UI - Component library built on Radix UI
- CSS Variables - For theming (light/dark mode)
- Class Variance Authority (CVA) - Component variants
- Responsive Design - Mobile-first approach
See ADR-005: Styling for details.
The application can be deployed to various platforms. For micro SaaS applications, we recommend:
- Connect your GitHub repository to Vercel
- Configure environment variables (see
.env.example) - Deploy with automatic preview deployments
- Set up custom domain (optional)
- Supabase Auth is used for user management
- Configure Supabase credentials in environment variables
- Set up Supabase project and get API keys from dashboard
- Optional: Set up database migrations if you need custom tables
Make sure to set all required environment variables in your deployment platform:
# Better Auth
BETTER_AUTH_SECRET=your_production_secret
BETTER_AUTH_URL=https://your-domain.com
# Google OAuth
GOOGLE_CLIENT_ID=your_production_google_client_id
GOOGLE_CLIENT_SECRET=your_production_google_client_secret
# Supabase Auth
NEXT_PUBLIC_SUPABASE_URL=https://[project-ref].supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=your_production_supabase_anon_key
SUPABASE_SERVICE_ROLE_KEY=your_production_supabase_service_role_key
# Stripe
STRIPE_SECRET_KEY=sk_live_your_production_stripe_secret_key
STRIPE_DEFAULT_PRICE_ID=price_your_production_price_id
# Resend
RESEND_API_KEY=re_your_production_resend_api_key
RESEND_FROM_EMAIL=noreply@yourdomain.com
# API
NEXT_PUBLIC_API_URL=https://your-domain.com- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'feat: add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
- Follow the conventional commits format
- Update documentation as needed
- Ensure all checks pass
Please use the GitHub issue tracker to report bugs. Include:
- Clear description of the issue
- Steps to reproduce
- Expected behavior
- Screenshots if applicable
This project is actively in development. While it provides a solid foundation for building micro SaaS applications, please note:
- π Features may be added, removed, or changed
- π Some features may have bugs or incomplete implementations
- π Documentation may be incomplete
- π§ Breaking changes may occur in future versions
We recommend:
- β Star the repository to stay updated
- π Report bugs and issues
- π‘ Suggest features and improvements
- π€ Contribute to make it better
The project includes E2E testing infrastructure with Playwright.
- Playwright - End-to-end testing framework
- Test Coverage - Authentication and checkout flows
- Global Setup - Test environment configuration
- Test Reports - HTML reports with screenshots
pnpm test:e2e # Run E2E tests
pnpm test:e2e:ui # Run E2E tests with UI
pnpm test:e2e:headed # Run E2E tests in headed mode
pnpm test:e2e:debug # Run E2E tests in debug mode
pnpm test:e2e:report # Show test reporte2e/
βββ auth.spec.ts # Authentication tests
βββ checkout.spec.ts # Payment flow tests
βββ global.setup.ts # Test environment setup
- Unit Tests - Vitest for utility functions and business logic
- Integration Tests - API route testing with mocked services
- Component Tests - React Testing Library for UI components
This project documents all major architectural decisions in ADR format. See docs/adr/ for complete documentation.
| ADR | Decision | Status |
|---|---|---|
| 001 | Authentication with Better Auth | β Accepted |
| 002 | Supabase as Database | β Accepted |
| 003 | Stripe for Payments | β Accepted |
| 004 | Upstash Redis for Cache | β Accepted |
| 005 | Tailwind CSS + shadcn/ui | β Accepted |
| 006 | Sentry for Monitoring | β Accepted |
| 007 | Internationalization Strategy | β Accepted |
| 008 | State Management | β Accepted |
See ADR README for more information.
Complete API documentation is available in docs/API.md.
/api/auth/[...all]- Better Auth endpoints/api/checkout- Stripe checkout session/api/subscription- User subscription data/api/resend- Transactional emails/api/webhooks/stripe- Stripe webhook handler/api/health- Health check
All endpoints include:
- Rate limiting
- Input validation
- Error handling
- Type-safe responses
- Encrypted Sessions - JWE cookies for stateless auth
- Input Validation - Zod schemas for all inputs
- HTML Sanitization - XSS protection
- Rate Limiting - Redis-based sliding window
- Security Headers - CSP, HSTS, X-Frame-Options
- Environment Validation - Type-safe env variables
This project is licensed under the MIT License - see the LICENSE file for details.
Built with β€οΈ for the micro SaaS community