Skip to content

Landing content and branding overrides ​

Audience

This article is for GCM platform operators. Church admins should see the Website Builder branding article β€” that page is for their public site, this one is for the GCM marketing site at geniuschurchmanager.com.

The Landing and Branding tabs together control how the platform looks to a brand-new visitor: the marketing landing page, the login screen, the favicon in their browser tab, the logo in the sidebar of every signed-in workspace, the Open Graph image when somebody shares a link in Slack. All of this lives in two tables, edited from two tabs, and applies platform-wide the instant you save.

Landing content editor with hero section open

Two tabs, one purpose ​

  • Landing (/platform/landing) edits the per-locale text and images that render on the marketing landing page. Stored as overrides in landing_page_content; falls back to the i18n defaults baked into the bundle when no override exists.
  • Branding (/platform/branding) edits everything else: platform name, tagline, logo, favicon, footer company, support email, theme colours, social links, the Guided Tour toggle. Stored in the flat platform_settings key-value table.

The two tabs share one media library, scoped to the uploads/platform/ Supabase storage path. Images uploaded for the landing page (platform/landing/) are also visible to the Branding tab (platform/branding/) and the PWA tab (platform/pwa/), and vice versa β€” pick once, reuse anywhere.

Landing content overrides ​

The Landing tab lists nine sections of the marketing page, each as an accordion:

  1. Hero Section β€” top fold. Badge, headline, subheadline, CTA, "see pricing" link, optional illustration.
  2. Social Proof Bar β€” strip under the hero ("Trusted by 200+ churches").
  3. Problem Section β€” narrative block. Headline, description, quote, quote author, illustration.
  4. Features Grid β€” six product capabilities with title + description each.
  5. Scripture Interlude β€” verse + reference.
  6. How It Works β€” three-step explainer.
  7. More Features β€” bullet list. The items field is one item per line.
  8. Pricing Preview β€” teaser block.
  9. Final CTA β€” closing banner.

A locale dropdown in the card header switches between English, EspaΓ±ol, FranΓ§ais, PortuguΓͺs. Each locale is a separate set of overrides; switching does not lose unsaved edits in the original locale (per-locale state is independent).

How the prefill works ​

Every text input is pre-filled with the current effective text, not the override. That means:

  • If no override exists, the input shows the i18n default from src/i18n/locales/{en,es,fr,pt}.json.
  • If an override exists, the input shows the override value.
  • The status badge tells you which: overridden (purple) or unsaved (amber).

This way, when you tweak the headline from "Know Your Flock" to "Know Your Flock Better", you don't have to retype the whole string β€” you edit the visible text and the system detects the diff. Blanking the field and saving is the canonical way to reset to the i18n default; the row is deleted from landing_page_content so the bundle text shows through.

Saving ​

Three save scopes:

  • Field-level Save β€” appears next to a field once you have edits. Persists just that field.
  • Section-level Save β€” appears at the top of an accordion section when any of its fields are dirty. Persists all dirty fields in that section in one upsert.
  • Section-level Reset β€” appears when any of the section's fields are overridden. Deletes those rows so the i18n defaults come back.

Saves invalidate two query caches: landing-content-admin (this tab) and landing-content (the live marketing page). The change appears on geniuschurchmanager.com on the next render.

Image fields ​

The image fields (hero_image, problem_image, cta_image) use the shared StorageMediaLibraryDialog. Click Choose / upload to open the picker, which lets you upload a new file or pick from existing ones in uploads/platform/landing/, uploads/platform/branding/, or uploads/platform/pwa/.

The picker stores the path, not the URL β€” resolveStorageUrl turns it into a public URL at render time, so if you move the bucket later the references keep working. A small preview thumbnail and a "View full size" link sit next to the input.

Storage paths, not URLs

Pasting a full https://... URL into an image field works for the preview but bypasses the platform-wide URL resolver. Future bucket migrations will break it. Always pick from the library.

Branding tab ​

The Branding tab is laid out in five sections:

1. Platform Identity ​

  • Platform Name β€” shown on the login page and the browser tab title.
  • Tagline / Subtitle β€” shown under the platform name on the login page.
  • Logo β€” square. Recommended 512x512 PNG or SVG. Picker scopes to uploads/platform/branding/.
  • Favicon β€” small square. Recommended 32x32 or 64x64 ICO/PNG.
  • Footer company / URL / support email / copyright year β€” used in the marketing footer and in transactional emails.

2. Colors & Theme ​

Three colour pickers (primary, secondary, accent), each with a live hex input and a Live Preview swatch row at the bottom of the card. Changes apply globally via CSS variables β€” they affect the marketing site and the signed-in shell.

3. Marketing & SEO ​

Hero title / subtitle / CTA / CTA link, plus the OG image URL and meta description (capped at 160 chars with a live counter). These are the platform-wide defaults; the Landing tab's hero override beats them when present.

Facebook, Instagram, Twitter / X, YouTube, TikTok URLs. Empty fields are hidden in the rendered footer.

5. Feature Toggles ​

Currently one: Guided Tour. When on, new users get a step-by-step tour wizard on first login. The toggle writes to both platform_settings.guided_tour_enabled and platform_config.guided_tour_enabled to keep the two sources of truth aligned; if the mirror write fails, the toggle reverts and a toast tells you.

The "Save All" button ​

Branding edits do not save per-field β€” they batch in local state until you press Save All Branding Settings at the bottom. Saving:

  1. Upserts every changed row into platform_settings with the new value and a fresh updated_at.
  2. Invalidates the platform_branding_settings cache.
  3. Calls refetchBranding() on the BrandingContext so the in-page sidebar, header, and theme colours refresh without a hard reload.

If the save fails halfway, the local state is preserved so you can retry β€” the page does not reset.

What changes are audited ​

Branding and landing edits write to platform_audit_log with actions branding_settings_saved and landing_content_updated respectively. The before / after values are captured in metadata, so a future "who changed the hero copy three weeks ago" question has a clean answer in the Audit log.