FAQ
Frequently asked questions about Unstack Pro
Common questions and answers about Unstack Pro.
Unstack Pro ships in two editions that differ in where the data lives and where Better Auth runs. Answers that depend on which one you have are behind the switcher below — the choice is remembered across every page in these docs.
Better Auth runs inside Next.js and talks to PostgreSQL through Drizzle ORM. One environment surface, one process, SQL migrations.
Better Auth runs inside Convex. Two environment surfaces, two processes, and schema pushed rather than migrated.
General
What is Unstack Pro?
Unstack Pro is a production-ready Next.js template with authentication, organizations, and admin panel fully configured. It's designed to save you 100-200+ hours of development time by providing all the foundational features a SaaS application needs.
Who is Unstack Pro for?
- Indie hackers building their first SaaS
- Startups that need to ship fast
- Developers who want to focus on product, not auth
- Teams building B2B applications with organization support
- Anyone who doesn't want to build auth from scratch
What tech stack does it use?
Everything except the data layer is shared:
| Technology | Purpose |
|---|---|
| Next.js 16 | React framework with App Router |
| React 19 | UI library |
| Tailwind CSS | Styling |
| Shadcn/ui | UI components |
| React Email + Resend | Transactional emails |
| Autumn | Billing |
| Biome | Linting and formatting |
| TypeScript | Type safety |
| Technology | Purpose |
|---|---|
| PostgreSQL | Database |
| Drizzle ORM | Schema, queries and migrations |
pg (node-postgres) | Database driver — no vendor lock-in |
| Better Auth | Authentication, running inside Next.js |
| Technology | Purpose |
|---|---|
| Convex | Real-time database and backend |
| Better Auth | Authentication, running inside Convex via kitcn |
Is it open source?
Unstack Pro is a premium template. You purchase a license to access the private repository, and then you own the code to use in your projects.
Can I use it for multiple projects?
Check your license terms. Typically, you can use the template for multiple personal or client projects, but cannot redistribute it.
Setup
How long does setup take?
Most developers are up and running in 10-15 minutes. The auth system is already configured - you just need to:
- Clone the repository
- Install dependencies
- Create a PostgreSQL database and a Resend account
- Configure
.env.local - Apply the migrations with
bun run db:migrate - Run the development server
- Clone the repository
- Install dependencies
- Set up Convex and Resend accounts
- Configure environment variables in
.env.localand on the Convex deployment - Run the development server alongside
bun convex dev
Do I need to know the data layer?
Some familiarity helps once you start adding your own features — the auth side is already built either way.
You'll want working knowledge of SQL and Drizzle
ORM. Your tables go in
lib/db/schema.ts, reads live in Server Components via lib/server/*, and
writes are server actions in actions/*. Schema changes are generated and
applied with drizzle-kit.
You'll want basic Convex knowledge — how to write queries and mutations, and how
indexes work. The Convex documentation is excellent
for the basics. Your tables go in convex/schema.ts and your functions in
convex/.
Do I need to know Better Auth?
No. Authentication is already configured. You only need to understand Better Auth if you want to customize auth flows.
What accounts do I need?
| Service | Required | Purpose |
|---|---|---|
| A PostgreSQL database | Yes | Data storage — any provider |
| Resend | Yes | Email sending |
| Autumn | Optional | Billing (can be removed) |
| Vercel | Recommended | Deployment |
| Sentry | Optional | Error monitoring |
| Service | Required | Purpose |
|---|---|---|
| Convex | Yes | Database and backend |
| Resend | Yes | Email sending |
| Autumn | Optional | Billing (can be removed) |
| Vercel | Recommended | Deployment |
| Sentry | Optional | Error monitoring |
Can I use a different database?
Any PostgreSQL will do. The app connects with pg (node-postgres), not a
vendor-specific driver, so Neon and Supabase are convenient suggestions rather
than requirements — a Postgres you run yourself works the same. Moving to a
different engine would mean swapping the Drizzle dialect and regenerating
every migration.
This edition is built specifically for Convex and relies on its real-time features, so switching databases would require significant modifications. If you want SQL, use the Postgres edition instead.
Can I use a different email provider?
Yes, but you'd need to modify the email sending code. Resend + React Email is the recommended and pre-configured option.
Authentication
What authentication methods are supported?
- Email/password with verification
- OTP (one-time password) via email
- Passkeys (WebAuthn) for passwordless auth
- Two-factor authentication (TOTP)
- OAuth providers (can be added)
Is email verification required?
Yes. Users must verify their email address before they can sign in. This ensures valid email addresses and improves security.
Can I disable email verification?
You could modify the Better Auth configuration, but it's not recommended. Email verification is a security best practice.
Can I add social login (Google, GitHub, etc.)?
Yes! Better Auth supports many OAuth providers. See the Customization Guide for instructions.
How do passkeys work?
Passkeys use biometric authentication (Face ID, Touch ID, Windows Hello) or security keys. Users register a passkey from their account settings and can then sign in without a password.
Requirements:
- HTTPS in production (localhost works for development)
- Modern browser with WebAuthn support
PASSKEY_RP_IDmust match your domain
How does 2FA work?
Users can enable two-factor authentication from their security settings:
- Enable 2FA (requires password confirmation)
- Scan QR code with authenticator app
- Verify with a code
- Save 12 backup codes for recovery
When signing in with 2FA enabled, users enter their email/password, then are prompted for a TOTP code.
What happens if a user loses access to their 2FA?
Users can use one of their 12 backup codes to sign in. Each backup code works once. If they've used all backup codes, they'll need admin assistance to disable 2FA on their account.
Organizations
What is the organization system?
Organizations provide multi-tenant support for B2B applications. Each organization:
- Has its own members
- Has roles and permissions
- Can have teams
- Has its own billing (via Autumn)
What roles are available?
Default roles:
| Role | Permissions |
|---|---|
| Owner | Full control, can delete organization |
| Admin | Manage members and settings |
| Member | Basic access and collaboration |
You can also create custom roles with specific permissions.
Can users belong to multiple organizations?
Yes. Users can be members of multiple organizations and switch between them.
How does organization billing work?
Organizations use per-seat pricing through Autumn. Each member added to an organization counts as a seat. Organizations must be on the Pro plan to add members beyond the owner.
Can I remove organization billing?
Yes. See the Billing documentation for instructions on removing Autumn integration.
Admin Panel
Who can access the admin panel?
Only users with the admin role can access /admin.
How do I create the first admin?
Register a normal account first, then promote it by hand — there is no bootstrap flow, and no environment variable that grants the role.
Set the role column on your row in the user table, then refresh your
browser:
update "user" set role = 'admin' where email = 'you@example.com';Open the Convex dashboard, go to the user table in the data browser, edit your
row's role field to admin, then refresh your browser.
What can admins do?
- View all users
- Create users
- Change user passwords
- Verify emails manually
- Set user roles
- Ban/unban users
- Revoke user sessions
- Impersonate users (for support)
Are admin actions logged?
Admin actions are not currently audited. The audit system tracks user authentication and account events, but not admin panel activities.
Can I impersonate any user?
Admins can impersonate regular users but cannot impersonate other admins (safety feature).
Billing
Is Autumn required?
Autumn is required for organization billing features. If you don't need billing, you can remove Autumn entirely.
How does per-seat pricing work?
Each organization member counts as a seat. When you add a member, the seat count increases and billing adjusts automatically. When you remove a member, the seat count decreases.
Can I use Stripe instead?
Unstack Pro is configured for Autumn. Using Stripe would require replacing the billing integration code.
What happens if payment fails?
The organization owner is notified. Depending on your Autumn configuration, the subscription may enter a grace period or be canceled.
Deployment
Where can I deploy?
Vercel is recommended and documented. Other platforms that support Next.js should also work:
- Vercel (recommended)
- Netlify
- Railway
- Self-hosted
Do I need separate environments for dev and production?
Yes, and never point production at your development data.
Two databases: your local DATABASE_URL and a separate production one. There is
no second deployment environment to manage — Better Auth runs inside Next.js, so
the only thing that changes between environments is the set of variables your
host provides.
Two Convex deployments — a development one and a production one — each with its
own environment variables. bun convex dev targets the former;
bunx convex deploy and --prod target the latter.
How do I handle environment variables in production?
One surface: your hosting platform's dashboard (for example Vercel Environment
Variables). Everything the app reads — DATABASE_URL, BETTER_AUTH_SECRET,
RESEND_API_KEY and the rest — lives there.
Two surfaces: your hosting platform's dashboard for the Next.js side, and the
Convex production deployment for everything Better Auth reads, set with
bunx convex env set NAME "value" --prod.
Do I need HTTPS?
For production, yes. HTTPS is required for:
- Passkey authentication
- Secure cookies
- OAuth callbacks
- General security
Customization
Can I change the UI/branding?
Yes. Customize:
- Colors in
styles/globals.css - Logo and favicon in
public/ - Site metadata in
config/site.ts - Fonts in
config/fonts.ts
Can I add my own features?
Absolutely. Routes go in app/ and components in components/, in both
editions. Where the data side goes depends on yours:
- Database tables in
lib/db/schema.ts, applied withbun run db:generateandbun run db:migrate - Reads in
lib/server/, called from Server Components - Writes as server actions in
actions/
- Database tables in
convex/schema.ts - Queries, mutations and actions in
convex/
Can I modify the auth flow?
Yes, but be careful. The auth system is complex and interconnected. Test thoroughly after any changes.
Can I remove features I don't need?
Yes. Common removals:
- Billing (Autumn)
- Error monitoring (Sentry)
- Passkeys
- Teams
- Custom roles
See Customization Guide.
Security
Is the template secure?
Yes. Unstack Pro implements security best practices:
- Password hashing (bcrypt)
- HIBP password breach detection
- Secure session management
- CSRF protection
- httpOnly cookies
- Email verification
- 2FA support
- Audit logging
Is data encrypted?
- Passwords are hashed (not stored in plain text)
- TOTP secrets are encrypted
- Sessions use secure tokens
Encryption at rest is a property of where the data lives:
Your database provider's responsibility. Most managed Postgres services encrypt
at rest by default; check yours, and use sslmode=require so the connection is
encrypted in transit too.
Convex encrypts data at rest for you.
How are sessions managed?
Sessions are managed by Better Auth with httpOnly cookies. Sessions can be viewed and revoked from account settings or by admins.
Is there rate limiting?
Basic rate limiting is in place. For production, consider adding additional rate limiting with Upstash Redis or similar.
Troubleshooting
Auth isn't working
Most common causes:
NEXT_PUBLIC_APP_URLdoesn't match the URL you're actually on- Cookies blocked by the browser, or missing HTTPS in production
BETTER_AUTH_SECRETchanged, invalidating every existing session
DATABASE_URLis unset or unreachable- Pending migrations in
drizzle/were never applied, so an auth table or column the code expects doesn't exist
- Convex isn't running (
bun convex dev) BETTER_AUTH_SECRETorJWKSis missing on the Convex deployment, orJWKSwas not regenerated afterBETTER_AUTH_SECRETchanged
Emails aren't sending
Check:
RESEND_API_KEYis correctEMAIL_FROMuses a verified domain- In test mode, recipient must be verified
- Check Resend dashboard for errors
Database connection fails
Verify:
DATABASE_URLis set in.env.localand reachable from where you're running- The connection string carries
?sslmode=requireif your provider needs it - The provider's connection limit isn't exhausted
Verify:
- Convex is running (
bun convex dev) CONVEX_DEPLOYMENT,NEXT_PUBLIC_CONVEX_URLandNEXT_PUBLIC_CONVEX_SITE_URLall name the same deployment- The deployment exists in the Convex dashboard
See the full Troubleshooting Guide for more solutions.
Support
Where can I get help?
- Check this documentation
- Review the Troubleshooting Guide
- Search the codebase for examples
- Check library documentation:
- Convex Docs
- kitcn — the Better Auth + Convex integration
Can I request features?
Feature requests can be submitted through the appropriate channels provided with your purchase.
How do I report bugs?
Report bugs with:
- Steps to reproduce
- Expected behavior
- Actual behavior
- Error messages
- Environment details
Updates
Will I get updates?
Yes. On purchase you're invited to the template repository, so your own git credentials can fetch it. You pull ongoing fixes and features into your project with a single command.
The Postgres-edition template repository is not published yet; the Convex edition is the one distributed today.
The repository is unstack-pro/nextjs-convex.
How do I update?
Run the template-sync script from your repo root:
bun scripts/sync-template.tsIt fetches the template, previews the changelog, creates a sync branch, merges,
then pushes and opens a pull request against your default branch. See the full
Template Updates guide for flags (--check-only, --no-pr,
--auto-merge) and conflict resolution. Review the changelog in the PR for any
breaking changes before merging.
Will updates break my customizations?
Updates are designed to be non-breaking when possible. Keep your customizations separate from core files to make updates easier.
Still have questions? Check the documentation sections for more detailed information on specific topics.