A modern multi-tenant SaaS application built with Next.js, featuring organization management, team collaboration, and role-based access control.
- π’ Multi-Tenant Architecture - Row-based multi-tenancy with organization isolation
- π₯ Team Management - Invite members, manage roles (Owner/Admin/Member)
- π Authentication - Google OAuth via NextAuth
- π§ Email Invitations - Team invitation emails via Resend
- π¨ Modern UI - Built with shadcn/ui and Tailwind CSS
- ποΈ Database - PostgreSQL with Prisma ORM
- Framework: Next.js 16 (App Router)
- Database: PostgreSQL + Prisma
- Authentication: NextAuth v5
- Email: Resend + React Email
- UI: shadcn/ui + Tailwind CSS
- Language: TypeScript
- Node.js 18+
- PostgreSQL 14+
- Google OAuth credentials
- Resend account (for email invitations)
git clone <your-repo-url>
cd navio
pnpm installCreate a .env.local file:
# Database
DATABASE_URL="postgresql://user:password@localhost:5432/navio"
# NextAuth
NEXTAUTH_URL="http://localhost:3000"
NEXTAUTH_SECRET="generate-with-openssl-rand-base64-32"
# Google OAuth
GOOGLE_CLIENT_ID="your-google-client-id"
GOOGLE_CLIENT_SECRET="your-google-client-secret"
# Resend (Email Service)
RESEND_API_KEY="re_your_resend_api_key"
# App URL (for email links)
NEXT_PUBLIC_APP_URL="http://localhost:3000"# Run migrations
npx prisma migrate dev
# Generate Prisma client
npx prisma generatepnpm devVisit http://localhost:3000
By default, emails are sent to delivered@resend.dev (visible in your Resend dashboard) to bypass domain verification requirements.
- Sign up at resend.com
- Create an API key
- Add to
.env.local:RESEND_API_KEY="re_your_api_key" NEXT_PUBLIC_APP_URL="http://localhost:3000"
To send emails to real recipients:
-
Verify Your Domain at resend.com/domains
- Add your domain (e.g.,
yourdomain.com) - Configure DNS records (SPF, DKIM, DMARC)
- Wait for verification
- Add your domain (e.g.,
-
Update Environment Variables:
RESEND_DOMAIN_VERIFIED=true NEXT_PUBLIC_APP_URL="https://yourdomain.com" -
Update Email From Address in
lib/email.ts:from: "Navio <noreply@yourdomain.com>";
- Go to Google Cloud Console
- Create a new project or select existing
- Enable Google+ API
- Create OAuth 2.0 credentials
- Add authorized redirect URIs:
- Development:
http://localhost:3000/api/auth/callback/google - Production:
https://yourdomain.com/api/auth/callback/google
- Development:
- Add authorized JavaScript origins:
- Development:
http://localhost:3000 - Production:
https://yourdomain.com
- Development:
navio/
βββ app/ # Next.js app directory
β βββ api/auth/ # NextAuth API routes
β βββ dashboard/ # Dashboard pages
β β βββ team/ # Team management
β β βββ settings/ # Organization settings
β βββ onboarding/ # User onboarding flow
β βββ login/ # Login page
βββ components/ # React components
β βββ ui/ # shadcn/ui components
β βββ app-sidebar.tsx # Main sidebar
βββ emails/ # Email templates
β βββ invitation-email.tsx
βββ lib/
β βββ actions/ # Server actions
β β βββ tenant.ts # Organization CRUD
β β βββ membership.ts # Team member management
β β βββ invitation.ts # Invitation management
β βββ email.ts # Email service
β βββ auth.ts # NextAuth configuration
β βββ db.ts # Prisma client
βββ prisma/
βββ schema.prisma # Database schema
- Row-based multi-tenancy using
tenantIdforeign keys - Organization switcher in sidebar
- Cookie-based active tenant selection
- Automatic tenant isolation in queries
Three roles with different permissions:
- Owner - Full control (delete org, manage all members)
- Admin - Manage members, send invitations
- Member - Read-only access
- Send email invitations to team members
- Set role (Member/Admin) for invitees
- 7-day expiration on invitations
- Resend and cancel functionality
- Automatic membership creation on acceptance
# Create a new migration
npx prisma migrate dev --name your_migration_name
# Reset database (WARNING: deletes all data)
npx prisma migrate resetnpx react-email devVisit http://localhost:3000 to preview emails.
pnpm build
pnpm start- Push to GitHub
- Import project in Vercel
- Add environment variables
- Deploy
DATABASE_URL="your-production-db-url"
NEXTAUTH_URL="https://yourdomain.com"
NEXTAUTH_SECRET="your-production-secret"
GOOGLE_CLIENT_ID="your-google-client-id"
GOOGLE_CLIENT_SECRET="your-google-client-secret"
RESEND_API_KEY="your-resend-api-key"
RESEND_DOMAIN_VERIFIED=true
NEXT_PUBLIC_APP_URL="https://yourdomain.com"MIT
For issues and questions, please open an issue on GitHub.