← Back to Blog
developmenttechnology

Centralized Config: The siteConfig Pattern

One of the design patterns baked into this template is the centralized site configuration. Instead of scattering configuration across multiple files and environment variables, all site settings live in a single typed object.

The Problem

In a typical multi-app setup, configuration gets messy:

  • Analytics IDs in Astro.locals.runtime.env here, import.meta.env there
  • Site name hardcoded in multiple layouts
  • Contact info duplicated across forms and footers
  • SEO defaults inconsistent between pages

The Solution: @template/site-config

The packages/site-config/ workspace package exports a single typed siteConfig object:

export const siteConfig = {
  name: 'My Company',
  description: 'We build amazing things',
  analytics: {
    ga4Id: 'G-XXXXXXXXXX',
    gtmId: 'GTM-XXXXXXX',
    cloudflareToken: '...',
  },
  seo: {
    defaultTitle: 'My Company',
    defaultDescription: 'We build amazing things',
    defaultOgImage: '/og-default.png',
  },
  social: {
    twitter: '@mycompany',
    linkedin: 'company/mycompany',
  },
  contact: {
    email: 'hello@mycompany.com',
    phone: '+1 (555) 000-0000',
    address: '123 Main St, City, ST',
  },
};

How It Works

Every app imports siteConfig as a workspace dependency:

---
import { siteConfig } from '@template/site-config';
---

<title>{siteConfig.name}</title>

The pattern eliminates:

  • Duplicated configuration across apps
  • Inconsistent default values
  • Hardcoded strings scattered in layouts
  • import.meta.env calls for public config

Runtime vs Build Time

Public configuration (site name, analytics IDs) uses siteConfig at build time. Client-safe values are compiled into the static output. Private configuration (API keys, tokens) uses Astro.locals.runtime.env at runtime — never exposed to the client.

Adding New Config Fields

To add a new setting:

  1. Add the field to packages/site-config/src/types.ts
  2. Add the value to packages/site-config/src/index.ts
  3. Import and use siteConfig in any app

All three apps get the update automatically — no copy-paste, no drift.

Environment Variable Bridging

For values that come from environment variables (like analytics IDs that differ between preview and production), siteConfig can read from import.meta.env:

analytics: {
  ga4Id: import.meta.env.PUBLIC_GA4_ID || '',
}

This keeps the API surface consistent while allowing per-environment overrides.

The siteConfig pattern is one of the template's core architectural decisions. Use it for all shared configuration — your future self (and your team) will thank you.