Six site improvements picked from a "what could be better" review, plus a Jest test suite covering the two areas with the trickiest money-handling history in this project (early-bird pricing tranches, donation-leg accounting): - "Add to calendar" .ics download on event pages and in confirmation emails - sitemap.xml, robots.txt, and Open Graph/Twitter metadata for public pages - Sentry error monitoring (backend + frontend), a no-op until SENTRY_DSN is set - Nightly local pg_dump backups with a Site Settings tab to browse/trigger/download - Admin audit trail for refunds, donations, manual registrations, event and settings changes, and staff-initiated cancellations - Jest tests reproducing and guarding against the 1.8.0 tranche-pricing bug and the 1.4.2 donation-balance-inflation bug Wallet passes (Google/Apple) were scoped out of this round — Apple Wallet needs a paid Apple Developer account the project doesn't have yet, and the user preferred shipping both together later rather than Google alone now. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
88 lines
6.6 KiB
Markdown
88 lines
6.6 KiB
Markdown
# 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](#two-different-fallbacks-for-primary_color) 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`. |
|
|
|
|
## Legal (Terms of Use / Privacy Policy)
|
|
|
|
| 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. |
|
|
| `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. |
|