Documentation

Developer Guide

This guide explains how the Soames site is built, how to run it locally, and how changes reach production. Soames is a headless WordPress setup: WordPress is the content backend, and a static Astro front end is built from it and served on a CDN. There is no PHP running on the public site — only pre-rendered HTML, CSS, and JavaScript.

Architecture at a glance

  • WordPress (headless CMS) — authors content and exposes it over the WPGraphQL API. Not publicly browsed; it only serves data at build time.
  • Astro front end — at build time it fetches content from WordPress and generates a fully static site.
  • Netlify — builds the Astro site and hosts the static output.
  • Cloudflare — sits in front of Netlify for DNS and TLS.

Flow: WordPress → WPGraphQL → Astro build (Netlify) → static HTML → Cloudflare → visitor.

Repositories and packages

  • soames-astro-theme — the shared Astro theme, published to npm. It provides the Astro integration, page routes, React components, the shortcode parser, the WordPress data layer, and the component-override (“shadow”) resolver.
  • soames-site — the site instance. It consumes soames-astro-theme as a versioned npm dependency and holds site-specific configuration and overrides. This is what deploys to production.
  • soames-wordpress-plugin — the companion WordPress plugin. It registers the docs content type, the Soames settings screens, a REST settings endpoint, GraphQL fields for the hero header settings, and the automatic rebuild-on-publish behavior.

The WordPress backend

Content is fetched over WPGraphQL. The Soames plugin adds the pieces the front end relies on:

  • Docs — a self-registered docs custom post type. The /docs/ landing is a card grid; individual articles render in prose with a docs sidebar. (This article is a docs entry.)
  • Soames Settings — site assets (logo, favicon, company name, contact blurb), the front-end URL, the page that drives the /docs/ hero, and the rebuild hook (see below).
  • Hero fields — four per-page meta fields drive the hero header: heroTitle, heroCaption, heroBackgroundImage, and overlayOpacity, all exposed on Page and Post. Each resolves to null when unset and the theme owns the fallbacks: the title falls back to the post title, the background image to the featured image and then a placeholder, and the opacity to 0.6. The caption has no fallback — unset means no caption is rendered. A page’s title and excerpt are therefore reserved for the document title and meta description, not the hero.

Running it locally

Work in the soames-site repository.

  1. Use Node 22 (an .nvmrc is provided; run nvm use). Older Node versions are too old for Astro.
  2. Create a .env file with the WordPress endpoints (see .env.example; use HTTPS so the static output has no mixed-content references):
    WORDPRESS_GRAPHQL_URL=https://your-wordpress-host/graphql
    WORDPRESS_BASE_URL=https://your-wordpress-host
  3. Install and run:
    npm install
    npm run dev     # http://localhost:4321
  4. Production build locally:
    npm run build   # outputs to dist/
    npm run preview

Customizing the theme (component overrides)

Astro has no built-in component shadowing, so the theme provides it with a resolver. Theme files are imported as @theme/<path>; a site overrides any of them by creating a file at the matching path under src/overrides/.

src/overrides/components/Footer.tsx   → replaces the theme's components/Footer.tsx
src/overrides/layouts/Base.astro      → replaces the theme's layouts/Base.astro
src/overrides/styles/…                → site-specific styles

This is whole-file replacement, resolved at build time, with no change at the import site — the direct successor to Gatsby component shadowing.

Publishing content → automatic rebuild

Because the site is static, content changes only appear after a rebuild. The Soames plugin triggers one automatically:

  • Publishing, updating, or unpublishing a post, page, or doc schedules a rebuild.
  • Rapid edits are coalesced into a single build that runs after your changes settle, so the build always reflects the final content.
  • The change is typically live about a minute after you publish.
  • A manual Deploy now button (Soames Settings) forces a rebuild — useful after changing menus or Site Assets.

Deploy pipeline

  • Continuous deployment: Netlify is connected to the soames-site repository and rebuilds on every push to main. Build settings live in netlify.toml (build command, publish directory dist, Node 22). The WordPress endpoints are provided as Netlify build environment variables.
  • Content rebuilds: in addition to code pushes, WordPress publishing triggers a build via a Netlify build hook (above).
  • DNS & TLS: the domain is served through Cloudflare in front of Netlify, with full end-to-end HTTPS.

Updating the theme

soames-site depends on a published version of soames-astro-theme. To ship a theme change:

  1. Merge the theme change and bump its version.
  2. Push a version tag (e.g. v0.1.1) — CI publishes the package to npm.
  3. In soames-site, update the dependency to the new version and push; Netlify rebuilds with the updated theme.

For quick local theme iteration without publishing, temporarily link the theme (e.g. npm link or a local file dependency) instead of the npm version.

Gotchas

  • GraphQL and the WAF: some WordPress installs’ web application firewall blocks GraphQL requests whose first field is pages or posts. The data layer aliases the root field (for example wpPages: pages) to avoid this; keep that pattern when adding queries.
  • Use HTTPS for the WordPress endpoint so image and asset URLs in the static output are HTTPS (no mixed-content warnings on the live site).
  • Node version: always build and run with Node 22.
  • Deploy the plugin whole: ship all plugin files together — a partial update can leave the editor and server sides out of sync.