@vernaillen/harmonic-saas
v0.7.1
Published
A production-ready Nuxt Layer providing core SaaS functionality - authentication, database management, internationalization, and more. Build your next SaaS application on a solid, extensible foundation.
Readme
Harmonic SaaS
A production-ready Nuxt Layer providing core SaaS functionality - authentication, database management, internationalization, and more. Build your next SaaS application on a solid, extensible foundation.
Features
✨ Authentication - Email/password, OAuth (GitHub, Google), magic links, passkeys 🗄️ Database - PostgreSQL with Drizzle ORM, extensible schema 🌍 Internationalization - Dutch & English, easy to add more languages 🎨 Modern UI - Nuxt UI with Tailwind CSS v4 📧 Email Integration - Resend for transactional emails 🧪 Testing - Comprehensive E2E tests with Playwright 🔒 Security - Email verification, password reset, account management 📦 Layer-based - Extend and customize without forking
Quick Start
Installation
# Install the layer
pnpm add @vernaillen/harmonic-saas
# Or with npm
npm install @vernaillen/harmonic-saasConfiguration
Add the layer to your nuxt.config.ts:
export default defineNuxtConfig({
extends: ['@vernaillen/harmonic-saas']
})Environment Setup
Create a .env file with required variables:
# Database
NUXT_DATABASE_URL=postgresql://user:password@localhost:5432/dbname
# Authentication (Better Auth)
NUXT_BETTER_AUTH_SECRET=your-secret-key
NUXT_BETTER_AUTH_URL=http://localhost:3000
# OAuth Providers (optional)
NUXT_GITHUB_CLIENT_ID=your-github-client-id
NUXT_GITHUB_CLIENT_SECRET=your-github-client-secret
NUXT_GOOGLE_CLIENT_ID=your-google-client-id
NUXT_GOOGLE_CLIENT_SECRET=your-google-client-secret
# Email (Resend or SMTP)
NUXT_RESEND_API_KEY=your-resend-api-key
[email protected]
NUXT_APP_NAME=Your App Name
# CORS Configuration (Production only)
# Comma-separated list of allowed origins for API access
# Capacitor app origins are always allowed automatically
ALLOWED_ORIGINS=https://yourdomain.com,https://app.yourdomain.comSee Email Integration Guide for detailed email setup.
Security Note: In production, CORS is restricted to origins listed in ALLOWED_ORIGINS plus Capacitor app origins. See CORS Configuration Guide for details.
Firebase Setup (Android/iOS)
If you're building mobile apps with Capacitor and using Firebase (for push notifications, etc.):
⚠️ IMPORTANT: The android/app/google-services.json file contains sensitive API keys and should NEVER be committed to version control.
- Download your
google-services.jsonfrom Firebase Console - Place it in
android/app/google-services.json(already in.gitignore) - See Firebase Setup Guide for detailed instructions
Database Setup
# Generate migrations
pnpm db:generate
# Run migrations
pnpm db:migrate
# Or push schema directly in development
pnpm db:pushDevelopment
# Start development server
pnpm dev
# Run tests
pnpm test
# Run E2E tests
pnpm test:e2e
# Lint code
pnpm lint
# Type check
pnpm typecheckTechnology Stack
- Framework: Nuxt 4 with Vue.js and TypeScript
- Database: PostgreSQL with Drizzle ORM
- Authentication: Better Auth
- UI: Nuxt UI with Tailwind CSS v4
- Email: Resend
- Testing: Vitest + Playwright
- Package Manager: pnpm
Architecture
Layer-Based Design
Harmonic SaaS is a Nuxt Layer - a reusable, composable foundation that you extend rather than fork. Your application inherits all the core functionality while maintaining full customization control.
your-app/
├── nuxt.config.ts # extends: ['@vernaillen/harmonic-saas']
├── app/
│ ├── pages/ # Your custom pages
│ └── components/ # Your custom components
└── server/
├── api/ # Your custom API routes
└── database/ # Extend the schemaExtending the Database Schema
// server/database/registerTables.ts
import { registerTables } from '@vernaillen/harmonic-saas/server/database'
import { myCustomTable } from './schema'
registerTables({
customTable: myCustomTable
})Protected Routes
Routes in /app/pages/dashboard/ are automatically protected. To make a page public:
<script setup lang="ts">
definePageMeta({ auth: false })
</script>Documentation
- 📖 Full Documentation - Comprehensive guides and references
- 🚀 E2E Testing Guide - Getting started with tests
- 📧 Email Integration - Email setup guide
- 🧑💻 CLAUDE.md - Developer onboarding and architecture
- 📝 CHANGELOG.md - Version history
Development Workflow
Working on the Layer
The .playground directory is your development environment for testing the layer:
# Start .playground development server
pnpm dev
# This boots the .playground directory which imports the layerTesting
# Unit tests
pnpm test
# E2E tests
pnpm test:e2e
# Test coverage
pnpm coverageSee Testing Documentation for detailed testing documentation.
Quality Assurance
# Run all checks before committing
pnpm lint # ESLint with stylistic rules
pnpm typecheck # TypeScript type checking
pnpm test # Run test suite
pnpm coverage # Ensure test coverageRelease Process
# Full release workflow
pnpm release # Lint + coverage + version bump + publishThis runs the complete release workflow including linting, testing, coverage checks, and publishing to NPM.
Project Structure
harmonic-saas/
├── app/ # Frontend application
│ ├── components/ # Vue components
│ ├── composables/ # Composable functions
│ ├── middleware/ # Route middleware
│ └── pages/ # Application pages
├── server/ # Backend API
│ ├── api/ # API routes
│ ├── database/ # Database schema & utilities
│ └── utils/ # Server utilities
├── emails/ # Email templates (Vue Email)
├── docs/ # Documentation site (Nuxt Content)
│ ├── content/en/ # English documentation
│ │ ├── guides/ # Setup guides
│ │ ├── testing/ # Testing documentation
│ │ └── reference/ # Reference materials
│ └── public/ # Static assets
├── test/ # Test suites
│ ├── e2e/ # Playwright E2E tests
│ └── unit/ # Vitest unit tests
├── i18n/ # Internationalization
│ └── locales/ # Language files
└── .playground/ # Development environmentContributing
Contributions are welcome! Please read our contributing guidelines and submit pull requests to our repository.
License
Links
Built with ❤️ using Nuxt 4 and Better Auth
