Configuration
Every optional subsystem is off until you set its flag. The app runs fully without any of them.
Subsystems
| Subsystem | Switch | Needs an account |
|---|---|---|
| Supabase | no flag — set 4 keys | No — self-hosted |
| GitHub OAuth login | no flag — set 2 keys | GitHub |
| Google OAuth login | no flag — set 2 keys | |
| Sentry error tracking | no flag — set 1 key | Sentry |
| BetterStack log forwarding | no flag — set 2 keys | BetterStack |
| Email notifications | NUXT_PUBLIC_NOTIFICATIONS_ENABLED | Resend |
| Feedback widget | NUXT_PUBLIC_FEEDBACK_ENABLED | No — self-hosted |
| Onboarding tour | NUXT_PUBLIC_TOUR_ENABLED | No — self-hosted |
| PostHog product analytics + feature flags | NUXT_PUBLIC_POSTHOG_ENABLED | PostHog |
| Billing | NUXT_PUBLIC_BILLING_ENABLED | Polar |
This table is generated from scripts/integrations.ts — the same manifest
pnpm setup and pnpm doctor read — so it cannot drift from what the code
actually does. Subsystems with no flag are switched on by the presence of their
keys. NUXT_PUBLIC_POSTHOG_SESSION_REPLAY is not a subsystem of its own; it is
an extra opt-in on top of PostHog.
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.