Environment Variables

Owlat uses environment variables to configure payments, email sending, authentication, and feature flags. Backend variables are set via the Convex...

Owlat uses environment variables to configure payments, email sending, authentication, and feature flags. Backend variables are set via the Convex dashboard; frontend variables live in .env files.

Where to Set Variables

Convex backend (all process.env references in apps/api/):

npx convex env set VAR_NAME value

Or set them in the Convex dashboard under your deployment's Settings > Environment Variables.

Nuxt frontend (apps/web/.env):

NUXT_PUBLIC_CONVEX_URL=https://your-deployment.convex.cloud
NUXT_PUBLIC_CONVEX_SITE_URL=https://your-deployment.convex.site
NUXT_PUBLIC_SITE_URL=http://localhost:3000

Payments (Stripe)

Prerequisites

  • A Stripe account
  • Four subscription products with monthly prices (one per plan tier)
  • Optionally, a metered price and billing meter for per-email charges

Required Variables

Set these in the Convex dashboard:

VariableDescription
BILLING_ENABLEDSet to true or 1 to enable the billing system. Disabled by default.
STRIPE_SECRET_KEYYour Stripe secret API key (starts with sk_). Required when billing is enabled.
STRIPE_WEBHOOK_SECRETStripe webhook signing secret (starts with whsec_). Required for processing Stripe webhook events.
STRIPE_PRICE_CONTACT_TIEREDStripe Price ID for the graduated tiered contact price
SITE_URLPublic site URL used for Stripe checkout redirect URLs. Defaults to http://localhost:3000.

Optional (Metered Email Billing)

VariableDescription
STRIPE_PRICE_EMAIL_METEREDStripe Price ID for metered email usage (per-email charges)
STRIPE_METER_IDStripe Billing Meter ID for reporting email usage events

Setup Steps

  1. Create a Stripe account at stripe.com and note your secret key from the API Keys page.
  2. Create a single product in Stripe with graduated tiered pricing for contacts. Copy the Price ID (starts with price_).
  3. (Optional) Create a metered price for per-email billing:
    • Create a product for email usage
    • Add a metered price (e.g., €0.25 per 1,000 emails)
    • Create a Billing Meter in Stripe and copy the Meter ID
  4. Set the environment variables in the Convex dashboard:
    npx convex env set BILLING_ENABLED true
    npx convex env set STRIPE_SECRET_KEY sk_live_...
    npx convex env set STRIPE_WEBHOOK_SECRET whsec_...
    npx convex env set STRIPE_PRICE_CONTACT_TIERED price_...
    

Contact Tiers (Graduated Pricing)

ContactsMonthly Price
0 – 10,000€8
10,001 – 40,000€20
40,001 – 500,000€100
500,001+€50 + €0.0001/contact

Email sending is billed at €0.25 per 1,000 emails when metered billing is configured.

Email Sending

Provider Selection

Owlat supports two email providers: AWS SES (default) and Resend. Set the EMAIL_PROVIDER variable in the Convex dashboard:

npx convex env set EMAIL_PROVIDER ses    # default
npx convex env set EMAIL_PROVIDER resend

AWS SES

VariableDescription
AWS_SES_REGIONAWS region for SES (e.g., eu-west-1, us-east-1). Required.
AWS_SES_ACCESS_KEY_IDIAM access key ID with SES permissions. Required.
AWS_SES_SECRET_ACCESS_KEYIAM secret access key. Required.

Setup Steps

  1. Create an IAM user in AWS with programmatic access and the AmazonSESFullAccess policy (or a scoped policy allowing ses:SendEmail and ses:SendRawEmail).
  2. Verify your sending domain in the SES console. SES requires domain verification before you can send emails.
  3. Request production access if your SES account is in sandbox mode. Sandbox mode limits sending to verified addresses only.
  4. Set the environment variables:
    npx convex env set EMAIL_PROVIDER ses
    npx convex env set AWS_SES_REGION eu-west-1
    npx convex env set AWS_SES_ACCESS_KEY_ID AKIA...
    npx convex env set AWS_SES_SECRET_ACCESS_KEY ...
    

Resend

VariableDescription
RESEND_API_KEYResend API key. Required when using Resend. Also used for organization invitation emails.
RESEND_WEBHOOK_SECRETWebhook signing secret (format: whsec_<base64>). Required for delivery event tracking.

Setup Steps

  1. Create a Resend account at resend.com and add your sending domain.
  2. Generate an API key from the Resend dashboard.
  3. (Optional) Set up webhooks for delivery tracking:
    • In Resend, create a webhook pointing to your Convex site URL's webhook endpoint
    • Copy the webhook signing secret
  4. Set the environment variables:
    npx convex env set EMAIL_PROVIDER resend
    npx convex env set RESEND_API_KEY re_...
    npx convex env set RESEND_WEBHOOK_SECRET whsec_...
    

Common Email Configuration

These variables apply regardless of which provider you use:

VariableDescriptionDefault
DEFAULT_FROM_EMAILDefault sender email address for transactional emailsnoreply@example.com
DEFAULT_FROM_NAMEDefault sender display nameOwlat
DEFAULT_FROM_DOMAINDomain used for system emails (e.g., invitation emails). Prepended with noreply@.mail.owlat.app
CONVEX_SITE_URLYour Convex site URL. Used for tracking pixels and unsubscribe links in campaign emails.
UNSUBSCRIBE_SECRETSecret key for generating HMAC-signed unsubscribe tokens. Required.

Waitlist

The waitlist gates new signups behind admin approval. When enabled, new users land on a waiting screen until an admin approves them.

Variables

Convex dashboard:

VariableDescription
WAITLIST_ENABLEDSet to true to enable the waitlist. Disabled by default.
WAITLIST_AUTO_APPROVE_EMAILSComma-separated list of email addresses that skip the waitlist and are approved automatically.

Nuxt frontend (apps/web/.env):

VariableDescription
NUXT_PUBLIC_WAITLIST_ENABLEDSet to true to show waitlist UI in the frontend. Must match the backend setting.

Setup Steps

  1. Enable the waitlist on both sides:
    # Convex
    npx convex env set WAITLIST_ENABLED true
    
    # apps/web/.env
    NUXT_PUBLIC_WAITLIST_ENABLED=true
    
  2. Optionally, auto-approve specific emails (e.g., your team):
    npx convex env set WAITLIST_AUTO_APPROVE_EMAILS "admin@example.com,dev@example.com"
    

Analytics (PostHog)

Owlat integrates with PostHog for product analytics and error tracking. The integration is optional — everything works without it.

Variables

Convex dashboard:

VariableDescription
POSTHOG_API_KEYPostHog project API key (starts with phc_). Required to enable server-side tracking.
POSTHOG_HOSTPostHog instance URL. Defaults to https://eu.i.posthog.com (EU cloud).

Nuxt frontend (apps/web/.env):

VariableDescription
NUXT_PUBLIC_POSTHOG_API_KEYPostHog project API key. Required to enable client-side tracking.
NUXT_PUBLIC_POSTHOG_HOSTPostHog instance URL. Defaults to https://eu.i.posthog.com.

Setup Steps

  1. Create a PostHog project at posthog.com and copy the project API key.
  2. Add the organization group type in PostHog: go to Settings → Groups → add a group type called organization. This enables organization-level analytics.
  3. Set the environment variables:
    # Convex (server-side events)
    npx convex env set POSTHOG_API_KEY phc_...
    npx convex env set POSTHOG_HOST https://eu.i.posthog.com
    
    # apps/web/.env (client-side events)
    NUXT_PUBLIC_POSTHOG_API_KEY=phc_...
    NUXT_PUBLIC_POSTHOG_HOST=https://eu.i.posthog.com
    

Tracked Events

Client-side (automatic):

  • $pageview — SPA page navigations
  • $pageleave — page leave events
  • $exception — Vue errors and unhandled promise rejections
  • User identification and organization group association

Server-side (fire-and-forget from mutations):

  • campaign_created, campaign_sent
  • contact_created
  • automation_created, automation_activated, automation_paused
  • mailing_list_created

All server events include organizationId as a property and PostHog group.

Translations (AI)

Owlat supports AI-powered email template translations. OpenRouter is the primary provider; OpenAI is used as a fallback if OpenRouter is not configured.

VariableDescription
OPENROUTER_API_KEYOpenRouter API key for AI translations (primary).
OPENAI_API_KEYOpenAI API key for AI translations (fallback if OpenRouter is not set).

Set in the Convex dashboard:

npx convex env set OPENROUTER_API_KEY sk-or-...
# or, as fallback:
npx convex env set OPENAI_API_KEY sk-...

Authentication

VariableDescriptionDefault
BETTER_AUTH_SECRETSecret key for BetterAuth session signing. Required.
SITE_URLPublic site URL for auth redirects and callbacks.http://localhost:3000

Set BETTER_AUTH_SECRET in the Convex dashboard. Use a long, random string:

npx convex env set BETTER_AUTH_SECRET $(openssl rand -base64 32)

Nuxt Frontend

These go in apps/web/.env:

VariableDescription
NUXT_PUBLIC_CONVEX_URLYour Convex deployment URL (e.g., https://your-deployment.convex.cloud)
NUXT_PUBLIC_CONVEX_SITE_URLYour Convex site URL (e.g., https://your-deployment.convex.site). Used for auth proxy.
NUXT_PUBLIC_SITE_URLPublic site URL. Must match SITE_URL set in Convex.
NUXT_PUBLIC_WAITLIST_ENABLEDSet to true to show waitlist UI (see Waitlist)

Complete Reference

All environment variables in one table:

VariableWhereRequiredDefaultPurpose
BILLING_ENABLEDConvexNoDisabledEnable the billing system
STRIPE_SECRET_KEYConvexIf billingStripe API secret key
STRIPE_WEBHOOK_SECRETConvexIf billingStripe webhook signing secret
STRIPE_PRICE_CONTACT_TIEREDConvexIf billingPrice ID for graduated tiered contact pricing
STRIPE_PRICE_EMAIL_METEREDConvexNoPrice ID for metered email usage
STRIPE_METER_IDConvexNoStripe Billing Meter ID
SITE_URLConvexYeshttp://localhost:3000Public site URL for redirects
EMAIL_PROVIDERConvexNosesEmail provider (ses or resend)
AWS_SES_REGIONConvexIf SESAWS region for SES
AWS_SES_ACCESS_KEY_IDConvexIf SESAWS IAM access key
AWS_SES_SECRET_ACCESS_KEYConvexIf SESAWS IAM secret key
RESEND_API_KEYConvexIf ResendResend API key
RESEND_WEBHOOK_SECRETConvexNoResend webhook signing secret
DEFAULT_FROM_EMAILConvexNonoreply@example.comDefault sender email
DEFAULT_FROM_NAMEConvexNoOwlatDefault sender name
DEFAULT_FROM_DOMAINConvexNomail.owlat.appDomain for system emails
CONVEX_SITE_URLConvexYesConvex site URL for tracking/unsubscribe
UNSUBSCRIBE_SECRETConvexYesHMAC secret for unsubscribe tokens
BETTER_AUTH_SECRETConvexYesSession signing secret
WAITLIST_ENABLEDConvexNoDisabledEnable waitlist gating
WAITLIST_AUTO_APPROVE_EMAILSConvexNoEmails to auto-approve
NUXT_PUBLIC_CONVEX_URLNuxt .envYesConvex deployment URL
NUXT_PUBLIC_CONVEX_SITE_URLNuxt .envYesConvex site URL for auth
NUXT_PUBLIC_SITE_URLNuxt .envYesPublic site URL
NUXT_PUBLIC_WAITLIST_ENABLEDNuxt .envNoDisabledShow waitlist UI
OPENROUTER_API_KEYConvexNoAI translations (primary provider)
OPENAI_API_KEYConvexNoAI translations (fallback provider)
POSTHOG_API_KEYConvexNoPostHog project API key (server-side)
POSTHOG_HOSTConvexNohttps://eu.i.posthog.comPostHog instance URL (server-side)
NUXT_PUBLIC_POSTHOG_API_KEYNuxt .envNoPostHog project API key (client-side)
NUXT_PUBLIC_POSTHOG_HOSTNuxt .envNohttps://eu.i.posthog.comPostHog instance URL (client-side)