Files
hope-events/SETTINGS.md
T
joshuaandClaude Opus 5.5 2b453b00e6 Add read-only admin impersonation
Admins (with 2FA) can view the site as a non-admin user for up to 30
minutes, with a required reason and a "Viewing as" banner. It is
strictly read-only: a guard mounted before every route refuses any
write made with an impersonation token, protect/optionalAuth check the
session is live, and GET handlers skip the price-refresh writes. Start,
end, reason and every page/API call (including blocked attempts) are
audited; optional email to the user.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CP62L9JxHomA36aYP1ekCe
2026-10-19 18:25:02 +02:00

7.1 KiB

Site Settings — Defaults Reference

Every setting below is stored as a row in the AppSetting key-value table and is editable at runtime via Admin → Site Settings (or, for the first few, the /setup wizard on a fresh install). None of them are required — this page documents exactly what happens when a given key has never been saved.

Settings changes take effect within 60 seconds everywhere (the backend's in-process settings cache TTL) without a server restart.

Organisation

Setting Default when unset Notes
org_name "Cross Code" Falls back to ORG_NAME env var first, then this hardcoded default (the platform vendor's name, used as a neutral placeholder — org_name is a required field in the setup wizard, so this fallback is practically unreachable once a site has been set up). Shown in the navbar, email headers/subjects, and WhatsApp messages.
org_tagline "Connecting community through events" Falls back to ORG_TAGLINE env var first. Shown under the org name in the email header.
org_email (blank) No fallback in most places. Exception: the Terms of Use / Privacy Policy pages default to privacy@example.com (an obvious placeholder) if unset — see the Legal section below.
org_phone / org_address (blank) No fallback — simply omitted wherever shown if unset.
app_base_url APP_BASE_URL or FRONTEND_URL env var, else http://localhost:3001 Used to build links in emails (password reset, ticket delivery, etc.). Should always be set in production.

Branding

Setting Default when unset Notes
primary_color Legacy accent_color value if present, else #4F46E5 (indigo) on the website / #1e3a5f (navy) in emails See Two different fallbacks below — this is the one setting with a genuine inconsistency worth knowing about. Drives buttons, links, nav highlights, and the email header/CTA.
secondary_color 210 40% 96.1% background / near-black text (light gray "wash", shadcn's stock theme) The Branding tab's color picker pre-fills #8B5CF6 as a suggested starting point, but that's only a UI default — if you never hit Save, the actual site uses the light-gray fallback, not violet.
accent_color 210 40% 96.1% background / near-black text (same light gray as Secondary) Same story as Secondary — the picker pre-fills #EC4899 (pink) as a suggestion only.
logo_url Bundled logo (frontend/src/app/church_logo.jpg) Shown in the navbar. This is still the original Hope Family Church artwork checked into the repo — swap the file (or upload a real logo via the Branding tab) before deploying for a different organisation.
favicon_url frontend/public/favicon.ico (the site's original generic favicon) Shown in the browser tab.

Two different fallbacks for primary_color

If primary_color has never been saved (no admin has ever used the new 3-color Branding tab) and there's no legacy accent_color value either, the website and outgoing emails currently disagree on what "no color" means:

  • Website (globals.css / tailwind.config.js static defaults): #4F46E5, a bright indigo.
  • Emails (backend/src/utils/email.js getOrg()): #1e3a5f, a dark navy — unless overridden by the EMAIL_HEADER_COLOR env var.

In practice this only matters on a brand-new install before the setup wizard or Branding tab has been saved even once — the wizard always writes primary_color, so this gap closes itself the moment setup completes.

Notifications

Setting Default when unset Notes
reg_notification_emails REGISTRATIONS_EMAIL env var, else (blank) If truly blank, no internal notification email is sent for new registrations/payments/donations — it's silently skipped, not an error.

Email delivery (SMTP)

Setting Default when unset Notes
smtp_host SMTP_HOST/EMAIL_HOST env var, else (blank) If blank, the app does not send real email — it uses nodemailer's jsonTransport, which just logs the would-be email to the console. This is the single biggest "nothing is configured" gotcha — ticket/payment/password-reset emails silently don't go anywhere until SMTP is set up.
smtp_port 587
smtp_secure false
smtp_user / smtp_pass (blank) Stored AES-256-GCM encrypted (key derived from JWT_SECRET).
smtp_from (blank) If blank, outgoing mail's From: address falls back to the literal no-reply@crosscode.local.
Setting Default when unset Notes
legal_operator_name "[operator details not yet configured]" Deliberately a generic, obviously-incomplete placeholder rather than any real person's or organisation's name. Unlike org_name, these legal fields are optional and can realistically stay unset on a live site — defaulting them to Cross Code's (or anyone else's) real identity would misrepresent who's legally responsible for that deployment.
legal_io_name "[not yet configured]" Same reasoning as legal_operator_name.
legal_io_email "io@example.com" Rendered as a mailto: link, so the placeholder stays a syntactically valid address on the IANA-reserved example.com domain rather than a bracketed non-email string that would break the link.
legal_website_url "example.com" Same reasoning — used to build an https:// link.
legal_effective_date "[not yet set]" Plain text only, no link — a bracketed placeholder is fine here.
notify_user_on_impersonation "false" When "true", a user is emailed (with the reason) whenever an admin views their account with Impersonate. Set under Site Settings → Legal → Support access.
consent_medical_retention_days 30 Youth events: medical and emergency details from parental consent forms are deleted this many days after the event ends (daily 09:00 job). The consent record itself — who agreed, when, to which text — is kept. Set under Site Settings → Legal.
org_email (as used on legal pages specifically) "privacy@example.com" Different fallback than org_email's general default (blank) — also rendered as a mailto: link, so it needs to stay a valid-looking address.

WhatsApp

Setting Default when unset Notes
WAWP_ACCESS_TOKEN / WAWP_INSTANCE_ID WAWP_ACCESS_TOKEN/WAWP_INSTANCE_ID env vars, else (blank) No hardcoded default — WhatsApp sending is simply unavailable until both are configured (Admin → Site Settings → WhatsApp).

Backups

Setting Default when unset Notes
backup_retain_count 14 How many nightly backups to keep on disk (oldest deleted beyond this count). Editable at Admin → Site Settings → Backups. See BACKUP_ENABLED (env var) to turn the nightly job off entirely.

Setup state

Setting Default when unset Notes
setup_complete false (treated as "not true") Controls whether /setup redirects to /login or runs the first-time wizard. Set to "true" automatically when the wizard finishes.