Infrastructure & Operations

Category: operations Sources: digital-home-standup skill output, live production verification (2026-08-09, re-verified 2026-08-11), digital-home-manifest.json (trace-backend repo) Confidence: high Last Updated: 2026-08-11


Where things actually run, and where their secrets live. Written after a folder rename nearly broke the production build because none of this was recorded anywhere — this article exists so that never happens again.

The two repos

Trace's digital home is split across two separate git repositories with separate histories, deploy targets, and secrets:

This repo (brand-wiki) trace-backend
Contains digital-home/frontend/ (the public site) + the entire brand wiki The CRM: pipeline, email sequences, funnel analytics, Cal.com bookings, AI content pipeline
Location This monorepo C:\Users\gmasc\dev\trace-backend, pushed to glenmascall/trace-backend (private)
Deploys as Cloudflare Pages project brand-wiki (confusing name — it is the frontend deploy, not the wiki) Cloudflare Worker trace-backend
Deploy config Root directory digital-home/frontend, output _site, build npm ci && npm run build, production branch master, auto-deploy on wrangler deploy; also runs a scheduled GitHub Action every 10 minutes to tick the email engine
Live at tracetechnical.co.uk https://trace-backend.glen-6bf.workers.dev

The backend is deliberately kept separate — own git history, own deploy target, own secrets. See digital-home-manifest.json in the trace-backend repo for the full installed/verified/pending state; a future session picking up backend work should start there.

Database

Supabase project trace-digital-home, ref bmoxvsntomudxggonfqe, region eu-west-2 (London).

Where secrets live

Secret type Where
Site build variables (SUPABASE_URL, SUPABASE_ANON_KEY) Cloudflare Pages → project brand-wiki → environment variables, as plain text, not "secrets" — Cloudflare does not expose Pages secrets to the build step, only plain-text variables. Needed on both Production and Preview. Without them the build logs a warning and Field Notes renders as its empty state.
Worker secrets (capture key, etc.) wrangler secret against the trace-backend Worker
CRM capture keys backend_settings table

What's live (verified 2026-08-09)

  • Every form on the site files leads into the CRM — tagged, filed into the pipeline, with a deal auto-created in GBP. Verified in production: {ok:true,emailed:true,captured:true,degraded:false}
  • Field Notes mailing list capturing with a recorded consent trail (single opt-in; see functions/api/subscribe.js and Website)
  • Cal.com bookings syncing — verified with a signed delivery accepted and a forged one rejected
  • Email engine ticking every 10 minutes via GitHub Actions
  • brand_context seeded from this wiki — 17 rows, ~71k characters, refreshed by the compile-brain skill
  • DMARC live with a reporting address
  • Pages build variables are set on Production — confirmed indirectly on 2026-08-11 because Field Notes and Guides render live from Supabase (six Field Notes, four Guides); without the variables the build would fall back to its empty state
  • New Trace logo system deployed (Trace Technical wordmark + Guiding Progress mark); sitemap.xml live (22 URLs); robots.txt returns 200 and opens the site to search (Allow: /)
  • crm_safe_mode is ON — every email send is simulated. Nothing reaches a prospect until this is switched off by hand in /crm/settings. Read a simulated send before switching it off.

Still to wire (none of these block launch)

Item What it needs
Deploy hook for published notes Create in Cloudflare Pages → Settings → Deploy Hooks (branch master), then a backend code change to call it on publish — the backend currently has no deploy-hook support at all. Until wired, a newly published note only appears on the site after the next deploy.
RESEND_WEBHOOK_SECRET No Resend webhook exists yet, so bounces/opens/clicks are not ingested
CRM → Resend Audience sync Subscribers land in the CRM; Broadcasts sends to a Resend Audience. Manual export/import for now — automate once the list grows
Double opt-in for Field Notes Current sign-up is single opt-in with a recorded consent trail (defensible under UK GDPR/PECR). Double opt-in is stronger; needs a token, a confirm endpoint, and an email

To review before full go-live

  • crm_safe_mode is still ON (see What's live). This is the real gate for outbound email: leads are captured and deals created, but every send is simulated until it is switched off by hand in /crm/settings. Read a simulated send before switching it off.
  • Allow AI crawlers (decided 2026-08-11; action in the Cloudflare dashboard). The site is to be open to AI crawlers for AI-search visibility. The block is Cloudflare's Managed robots.txt, not the repo robots.txt (which is already Allow: /), so it is removed in the Cloudflare dashboard: zone tracetechnical.co.uk → AI Crawl Control / Manage robots.txt (and any Block-AI-bots managed rule) → disable, so the injected Disallow for ClaudeBot, GPTBot, Google-Extended, CCBot, Bytespider, Amazonbot, Applebot-Extended and meta-externalagent, and the ai-train=no signal, are dropped. No repo change needed.
  • llms.txt is absent (404). Now that the site is opening to AI crawlers, worth adding.
  • Canonical host is www; apex 301s to www (live, verified 2026-08-11). The whole site canonicalises to www.tracetechnical.co.uk (site.url in eleventy.config.js, the injected canonical, og:url, JSON-LD and all 22 sitemap URLs). The apex→www 301 runs from digital-home/frontend/functions/_middleware.js: a Pages _redirects rule cannot match on hostname, so the middleware handles it (www and /api/* pass through via next()). Verified tracetechnical.co.uk → 301 → www.tracetechnical.co.uk. (Flipping canonical to the bare apex instead would be a larger change: site.url, the canonical injection, article.njk schema, robots.txt, plus a www→apex redirect.)

How to send a newsletter

  1. /crm/leads → filter tag newsletter → export
  2. Resend → Audiences → create Field Notes → import
  3. Resend → Broadcasts → New → pick that audience
  4. Write it, from hello@tracetechnical.co.uk
  5. Test send to yourself, check on a phone
  6. Send

Resend adds and honours the unsubscribe link on Broadcasts automatically. Don't use the CRM's sequences for this — those are for timed per-person sequences, not one-to-many sends, and safe mode is on regardless.

Write the first newsletter yourself, not AI-drafted. brand_context is strong enough for a good AI draft, but the first thing a list ever receives sets the expectation for everything after, and Trace's positioning is explicitly anti-filler.

Known upstream faults (BraveBrand starter, not Trace-specific)

Both patched locally — flagging here so a future rebuild or starter upgrade doesn't silently reintroduce them.

  1. All money renders in USD regardless of configured currency. The `` token correctly reaches opportunities.currency, but every fmtMoney call site in /crm and /crm/pipeline omits the argument, so the 'USD' default renders instead. Affects every non-USD install. Patched locally to GBP.
  2. Next 16 breaks the starter silently. It now defaults next build to Turbopack, which OpenNext cannot run on Cloudflare. The build succeeds and the Worker deploys and reports success, then every route 500s with a ChunkLoadError. Fixed by pinning --webpack in open-next.config.ts — don't let this flag get tidied away.

Related Articles