Development Setup

This guide covers installation, configuration, and getting the development environment running.

Prerequisites

Node.js Version

This project requires Node.js 24 or higher. We use mise for version management:

mise use node@24

Native Dependencies

This project uses native Node.js modules that require compilation:

  • sharp - Image processing library for @nuxt/image (IPX provider)
  • better-sqlite3 - SQLite3 bindings for Nuxt Content

Build scripts run automatically during pnpm install without requiring manual approval.

Troubleshooting Image Loading: - If images fail to load with 500 errors on /_ipx/ endpoints, ensure sharp is installed - Restart the dev server after installing sharp to load the native module - In CI environments, build tools (python3, make, g++) are automatically installed

Installation

Install all dependencies once (from root):

pnpm install

Environment Setup

API Configuration

The API requires environment variables. Create apps/api/.env based on .env.example:

# Supabase Configuration
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_KEY=your_supabase_key_here

# Supabase Service Role Key (REQUIRED for audit logging)
# Get this from: Supabase Dashboard → Settings → API → service_role key
# ⚠️ Keep this secret! Never expose to client-side code.
SUPABASE_SERVICE_ROLE_KEY=your_service_role_key_here

# API Configuration
PORT=3001

# Web Application URL (used for email redirects in auth flows)
# Production: https://meister-bill.com
# Development: http://localhost:3000 (or your dev URL)
WEB_URL=http://localhost:3000

Important: The SUPABASE_SERVICE_ROLE_KEY is required for automatic audit logging. See Audit Logging Setup for details.

Web Application Configuration

For the web application, you can control authentication visibility and analytics:

# To disable new user signups (useful for prelaunch/maintenance)
# WEB: Hides login/register buttons and shows newsletter CTA instead
# API: Blocks the /auth/signup endpoint (returns 403)
NUXT_PUBLIC_ENABLE_SIGNUPS=false  # For web app (requires NUXT_PUBLIC_ prefix)
ENABLE_SIGNUPS=false              # For API

# Umami Analytics (Privacy-friendly tracking)
# Set to false to disable tracking (useful for development)
NUXT_PUBLIC_UMAMI_ENABLED=true
NUXT_PUBLIC_UMAMI_WEBSITE_ID=your_umami_website_id
NUXT_PUBLIC_UMAMI_SCRIPT_URL=https://your-umami-instance.com/script.js

# Newsletter Service (Sender.net)
SENDER_API_KEY=your_sender_api_key_here

# Stripe Configuration (for payment links)
# Get your keys from: https://dashboard.stripe.com/test/apikeys
STRIPE_SECRET_KEY=sk_test_your_stripe_secret_key_here
# Webhook secret for verifying webhook signatures
# Get from: https://dashboard.stripe.com/test/webhooks
STRIPE_WEBHOOK_SECRET=whsec_your_webhook_secret_here
# Stripe Connect Client ID (for OAuth account linking)
# Get from: https://dashboard.stripe.com/settings/applications
STRIPE_CONNECT_CLIENT_ID=ca_your_client_id_here

Umami Analytics Setup

Configure Umami analytics using the environment variables shown above for privacy-friendly tracking.

See the Stripe Workflow documentation for complete setup instructions.

Development Services

Before starting development, run the required services:

docker-compose up -d  # Start mailpit (mail testing) and gotenberg (PDF generation)

Development Services: - Mailpit: Local SMTP/IMAP server for email testing - Web interface: http://localhost:8026/ - SMTP: localhost:1026 (configured in docker-compose.yml) - Use for testing invoice email sending and other email features - Gotenberg: PDF generation service - API: http://localhost:3003/ - Converts HTML templates to PDF for invoices - Required for invoice PDF generation

Running the Application

Start individual apps:

pnpm dev                              # Start both API and web in parallel
pnpm --filter @meisterbill/web dev    # Start web frontend only
pnpm --filter @meisterbill/api dev    # Start API backend only
pnpm --filter @meisterbill/app dev    # Start Ionic app
# Note: blogwriter app runs standalone via ts-node

Note: Both API and WEB have hot reloading. No need to restart after code changes.

See Also

See Also