Getting Started

Configuration

Every subsystem, its flag, and what it costs to turn on.

Every optional subsystem is off until you set its flag. The app runs fully without any of them.

Subsystems

SubsystemFlagNeeds
Notifications + emailNUXT_PUBLIC_NOTIFICATIONS_ENABLEDResend key, webhook secret
Feedback widgetNUXT_PUBLIC_FEEDBACK_ENABLEDnothing (self-hosted)
Onboarding tourNUXT_PUBLIC_TOUR_ENABLEDnothing
Analytics + flagsNUXT_PUBLIC_POSTHOG_ENABLEDPostHog key
Session replayNUXT_PUBLIC_POSTHOG_SESSION_REPLAYPostHog enabled
Error trackingNUXT_PUBLIC_SENTRY_DSNSentry DSN

Notifications

A database trigger fans a new note out to the tenant's admins as notifications rows. The in-app feed and bell render them; a Supabase database webhook mirrors each row to email through Resend.

To wire the email half, add a Supabase webhook on notifications INSERT that POSTs to /api/hooks/notification-email with your secret header.

Social login

Enable [auth.external.github] or [auth.external.google] in supabase/config.toml, set the client id/secret, and restart local Supabase. The login page buttons are already wired.

Email templates

supabase/templates/*.html are generated, not source. Edit scripts/gen-auth-templates.ts and run pnpm gen:auth-templates.

Auth mail is rendered by GoTrue rather than by the app, so it has to exist as standalone files — but they come from the same shell the app's own transactional mail uses. A unit test compares the committed HTML against the generator, so hand-edits and forgotten regenerations fail on pre-commit instead of shipping a mismatched password-reset email.

Feature flags without PostHog

useFeatureFlag(key, fallback) returns a reactive flag that degrades to fallback when PostHog is disabled. Gated UI therefore works on a bare clone — you never have to stand up an analytics account to develop against a flag.