Skip to content

Latest commit

 

History

History
260 lines (180 loc) · 8.38 KB

File metadata and controls

260 lines (180 loc) · 8.38 KB

Tada Environment Configuration

This document explains how to configure Tada for different deployment scenarios.


Environment Overview

Tada supports three deployment modes:

Mode Use Case Cloud Features
Development Local development Off
Self-Hosted Your own server (Docker/CapRover) Optional
Cloud Multi-tenant SaaS deployment On

1. Development (Localhost)

For local development on your machine or in a dev container.

Database Path

All npm/bun scripts set DATABASE_URL explicitly in package.json:

{
  "dev": "DATABASE_URL=file:../data/db.sqlite nuxt dev",
  "db:migrate": "DATABASE_URL=file:../data/db.sqlite drizzle-kit migrate",
  "db:studio": "DATABASE_URL=file:../data/db.sqlite drizzle-kit studio"
}

Why ../data/ instead of ./data/?

The database is stored OUTSIDE the app/ directory to avoid Vite/Nuxt file watcher conflicts. See DATABASE_LOCATION_MIGRATION.md for details.

File Layout

/your-workspace/
├── data/
│   └── db.sqlite           # Development database (outside app/)
├── app/
│   ├── .env                # API keys, feature flags (NOT database path!)
│   ├── package.json        # Scripts set DATABASE_URL
│   └── ...

Configuration

.env (in app/ directory):

# NOTE: Do NOT set DATABASE_URL here for development!
# package.json scripts handle database path.

# Voice features
VOICE_ENABLED=true
VOICE_FREE_LIMIT=50
GROQ_API_KEY=your_key_here

Running

cd app
bun install
bun run dev          # Starts dev server at localhost:3000
bun run db:migrate   # Applies migrations to dev database

2. Self-Hosted (Production)

For deploying Tada on your own server using Docker or CapRover.

Database Path

The Dockerfile sets the database path:

ENV DATABASE_URL=file:/data/db.sqlite

You must mount a persistent volume to /data/ for data to survive container restarts.

Docker Compose Example

services:
  tada:
    build: .
    ports:
      - "3000:3000"
    volumes:
      - tada-data:/data
    environment:
      - APP_URL=https://tada.example.com
      # Optionally enable voice features:
      # - GROQ_API_KEY=your_key

volumes:
  tada-data:

CapRover Deployment

  1. Create app with persistent storage enabled
  2. Set persistent directory: Path in App = /data
  3. Deploy via caprover deploy or GitHub integration
  4. Migrations run automatically on container start

Environment Variables

There are two kinds of env vars in Docker/CapRover deployments:

  • Server-only — plain names (e.g. GROQ_API_KEY). Server code reads process.env directly at request time.
  • Browser-visible — must use NUXT_PUBLIC_ prefix (e.g. NUXT_PUBLIC_IS_CLOUD_MODE). These are the only way to pass config to the browser after the Docker image is built.

Server-Only (plain names)

Variable Required Default Purpose
DATABASE_URL No file:/data/db.sqlite Database path
NODE_ENV No production Environment mode
APP_URL Recommended http://localhost:3000 Public URL for emails/links
VOICE_ENABLED No true Enable voice input
GROQ_API_KEY No - Voice transcription (Groq Whisper)
OPENAI_API_KEY No - Voice transcription fallback

Browser-Visible (NUXT_PUBLIC_ prefix required in Docker)

Variable Required Default Purpose
NUXT_PUBLIC_IS_CLOUD_MODE No false Enables subscription UI, cookie consent
NUXT_PUBLIC_UMAMI_HOST No - Umami analytics script URL
NUXT_PUBLIC_UMAMI_WEBSITE_ID No - Umami website tracking ID

Why the prefix? Nuxt bakes runtimeConfig.public values into the build. In Docker, env vars aren't available at build time. The NUXT_PUBLIC_ prefix is Nuxt's mechanism to override those baked-in defaults at container startup. Server-only code doesn't have this limitation — it reads process.env at request time.

Analytics (Optional)

To enable Umami analytics, set both in your deployment config:

NUXT_PUBLIC_UMAMI_HOST=https://your-umami-instance.com/script.js
NUXT_PUBLIC_UMAMI_WEBSITE_ID=your-website-uuid

For local development with .env, use plain names instead:

UMAMI_HOST=https://your-umami-instance.com/script.js
UMAMI_WEBSITE_ID=your-website-uuid

This is optional and privacy-friendly — no data is collected unless you configure it.


3. Cloud Mode (SaaS)

For running Tada as a multi-tenant cloud service with billing and usage limits.

Enabling Cloud Mode

Cloud mode activates when either:

  • TADA_CLOUD_MODE=true, OR
  • STRIPE_SECRET_KEY is configured

Cloud-Specific Features

When cloud mode is enabled:

  • Cookie consent banner shown
  • Email verification required (with grace period)
  • Usage limits enforced (free tier: 1-year data retention)
  • Stripe billing integration available
  • Subscription UI in account settings

Environment Variables (Cloud)

Variable Purpose
TADA_CLOUD_MODE Enable cloud features (true/false)
STRIPE_SECRET_KEY Stripe API key for billing
STRIPE_WEBHOOK_SECRET Stripe webhook signature verification
STRIPE_PRICE_SEEDLING Stripe price ID for £1/year tier
STRIPE_PRICE_SAPLING Stripe price ID for £5/year tier
STRIPE_PRICE_OAK Stripe price ID for £12/year tier
STRIPE_PRICE_REDWOOD Stripe price ID for £25/year tier
STRIPE_PRICE_FOREST Stripe price ID for £50/year tier
TADA_REQUIRE_EMAIL_VERIFICATION Require verified email (true/false)
TADA_VERIFICATION_GRACE_DAYS Days before verification required (default: 7)
TADA_FREE_RETENTION_DAYS Data retention for free tier (default: 365)
SMTP_HOST, SMTP_PORT, etc. Email configuration for verification

Database Path Summary

Context DATABASE_URL Notes
bun run dev file:../data/db.sqlite Set by package.json
bun run db:migrate file:../data/db.sqlite Set by package.json
Docker container file:/data/db.sqlite Set in Dockerfile
CapRover file:/data/db.sqlite Different host volume per app

Key principle: Development uses ../data/ (outside app/ to avoid watchers). Production uses /data/ (container volume mount).


Troubleshooting

"no such column" errors

Migrations need to be applied:

cd app
bun run db:migrate

Wrong database location

Check the startup log for:

Database path: file:../data/db.sqlite (dev: true)

If it shows ./data/db.sqlite (without ..), you have an outdated config.

drizzle-kit uses wrong database

Always use the package.json script:

# ✅ Correct
bun run db:migrate

# ❌ Wrong - won't use correct DATABASE_URL
npx drizzle-kit migrate

Related Documentation


Last updated: March 2026