Contact Us

Site Feature Configuration

DOC-00090 reference implementor, developer

This reference covers the feature toggle surfaces in the site configuration system. For site identity, contact info, branding, and structural config, see Site Configuration (DOC-00002). For styling overrides (typography, fluid tokens, core styles), see Site Styling Configuration (DOC-00089).

Who this is for

  • Implementors enabling, disabling, or configuring site-level features for a client site
  • Developers understanding how feature toggles flow through the config system

Theme Mode

Nested under theme: ThemeConfig. Controls the theme switcher UI variant ('icon', 'select', or 'none') and first-visit default ('system', 'light', or 'dark').

FieldTypeDefaultDescription
themeSwitcherstring"icon"Switcher UI variant: 'icon', 'select', or 'none'
defaultThemestring"light"First-visit default: 'system', 'light', or 'dark'
themeColorLightstring"#ffffff"Hex color for <meta name="theme-color"> in light mode
themeColorDarkstring"#020617"Hex color for <meta name="theme-color"> in dark mode

themeColorLight and themeColorDark control the browser chrome color (mobile address bar, PWA title bar). Set these to match your --st-color-bg-canvas values if you override the default surface colors in your site-level token files.

BaseLayout also emits a <meta name="color-scheme"> tag automatically: "light dark" when the switcher is enabled, or the single active scheme when themeSwitcher is 'none'.

Theme preference persistence (localStorage key theme-preference) and FOUC prevention are runtime concerns handled by the theme component, not config fields.

Theme-Docs

Nested under themeDocs: ThemeDocsConfig. Controls whether the theme-docs system is active and its listing page behavior.

FieldTypeDefaultDescription
enabledbooleantrueWhether the theme-docs system generates routes
rootLabelstring"Documentation"Breadcrumb label for the theme-docs root
docsPerPagenumber24Docs per page on the theme-docs index

When enabled is false, no theme-docs routes, nav links, or build output are generated.

Article Listing

Configured in src/site/config/platform.config.ts and re-exported through siteConfig.articles. Controls pagination for article listing and taxonomy routes.

FieldTypeDefaultDescription
articlesPerPagenumber12Number of articles per page on listing, category, and tag routes

This value is the single source of truth for all article pagination — page-1 routes, page-2+ routes, taxonomy pagination, and validation scripts all derive from platformConfig.articles.

// src/site/config/platform.config.ts
export const platformConfig = {
  // ...
  articles: {
    ...DEFAULT_SITE_CONFIG.articles,
    articlesPerPage: 9,
  },
};

Analytics

Nested under analytics: AnalyticsConfig. Configures analytics providers, consent behavior, and custom third-party snippets.

Provider Configuration

FieldTypeDefaultDescription
googleTagManager.enabledbooleanfalseEnable GTM script injection
googleTagManager.idstring""GTM container ID (e.g., GTM-XXXXX)
googleAnalyticsGA4.enabledbooleanfalseEnable GA4 script injection
googleAnalyticsGA4.idstring""GA4 measurement ID (e.g., G-XXXXX)

GTM takes precedence — when both are enabled, only GTM loads (it typically manages GA4 as a tag).

FieldTypeDefaultDescription
consentRequiredbooleanfalseWhen true, scripts only load after user accepts consent
consent.messagestring(default text)Banner message text
consent.acceptLabelstring"Accept"Accept button label
consent.rejectLabelstring"Reject"Reject button label
consent.requiredOnlyLabelstring"Required Only"Required Only button label
consent.policyUrlstring"/privacy/"Link to privacy policy page in the banner
consent.policyLinkLabelstring"Privacy Policy"Visible text for the policy link
consent.expirationDaysnumber365Days before consent expires and re-prompt appears
consent.cookieClearingPatternsstring[]["_ga", "_gid", "_gat", "_gcl"]Cookie name prefixes cleared on consent revocation

The consent.policyUrl and forms.privacyPolicyUrl are independent settings that typically point to the same page. consent.policyUrl drives the banner’s policy link; forms.privacyPolicyUrl drives consent checkbox links on forms.

Custom Snippets

The customSnippets array supports non-Google tracking and marketing scripts, consent-gated with the same rules as GTM/GA4:

customSnippets: [
  { id: "hotjar", src: "https://static.hotjar.com/c/hotjar-XXXXX.js", location: "head" },
  { id: "inline-pixel", content: "console.log('pixel loaded')", location: "body-end" },
],
FieldTypeDescription
idstringUnique identifier for deduplication
srcstring (optional)External script URL (mutually exclusive with content)
contentstring (optional)Inline script content (mutually exclusive with src)
location"head" | "body-end"Where the script is injected in the document

Each entry requires exactly one of src or content. Duplicate id values are logged as warnings; only the first matching entry injects per page load.

For consent states, script injection lifecycle, event taxonomy, and trackEvent() usage, see Analytics & Consent.

Scroll-to-Top

FieldTypeDefaultNotes
scrollToTopbooleantrueEnables the fixed scroll-to-top button on all layouts except Blank.
scrollToTopPosition"start" | "end""end"Horizontal position of the button (start = left, end = right).

Per-page opt-out is available via the hideScrollToTop: true frontmatter field (articles and docs collections). See Interactive Components for the ScrollToTop component reference.

Configured in src/site/config/platform.config.ts and re-exported through siteConfig.lightbox. Controls which content collections enable lightbox by default.

FieldTypeDefaultNotes
lightbox.collectionsPartial<Record<"articles" | "pages", boolean>>{ articles: true }Per-collection lightbox defaults. Omitted = false.

Individual pages can override via the lightbox frontmatter field (true/false). When omitted, the collection default applies. Resolution order: frontmatter → collection default → false.

// src/site/config/platform.config.ts
export const platformConfig = {
  // ...
  lightbox: {
    ...DEFAULT_SITE_CONFIG.lightbox,
    collections: { articles: true, pages: true },
  },
};

See Image Lightbox (DOC-00088) for the full component reference.

Environment Variables

The project uses Astro/Vite environment variables via import.meta.env. No process.env is used.

Build-Mode Flags

  • import.meta.env.DEVtrue during development, false in production builds. Controls: draft content visibility (drafts shown in dev only), analytics script injection (disabled in dev), form submission behavior (console logging in dev).
  • import.meta.env.PROD — Inverse of DEV.

Service Keys

VariablePurposeRequiredUsed in
TURNSTILE_SITE_KEYCloudflare Turnstile public key for CAPTCHAFor formsCaptchaField.astro (client-side)
TURNSTILE_SECRET_KEYCloudflare Turnstile secret for server verificationFor formsturnstile.ts (server-side)
POSTMARK_API_KEYPostmark transactional email API keyFor formsnewsletter-provider.ts, email-provider.ts
POSTMARK_FROM_EMAILSender email addressFor formsemail-provider.ts
CONTACT_EMAIL_TORecipient email for contact formsFor formsemail-provider.ts

Fallback Cascade

Environment variable → site config override (e.g., siteConfig.forms.contactEmailTo in src/site/config/site.ts — SITE-OWNED) → hardcoded default.

Dev-Mode Behavior

When service keys are absent, forms degrade gracefully:

  • Turnstile verification is bypassed.
  • Email submissions log to console instead of sending.

Note: Never commit real service keys to the repository. Use .env files (gitignored) or your hosting platform’s environment variable configuration.

REQ-00226 implemented Lightbox enablement shall resolve through a three-level configuration hierarchy: content frontmatter override, collection default, system default (false), allowing per-page, per-collection, and system-wide control.

Search

Search across pages and articles. Use arrow keys to navigate results.

Search across pages and articles.

Loading search...

Search is unavailable. Please try again later.

    No results for ""

    Try different keywords or fewer words.