Skip to content

Website Rebuild Log

Document type: Website Rebuild — change log Last updated: 2026-06-03 Live at:

  • Production: kayasync.com — v1.1.1, shipped 2026-06-03 (tag-triggered deploys via git tag v*)
  • Staging: test.kayasync.com (noindexed, auto-deploys on push to main)

A running log of what has been built and shipped on the public website (kayasync.com / test.kayasync.com), in chronological order. The Copy Deck defines what the site says; this page records what the site looks like and how it's structured.

All copy on the public site stays at Level 1 disclosure per NKA's brief — no architecture detail, no internal mechanism names, no banned terms.


2026-05-23 — Wave A: Bricolage Modernist design refresh

After the first NKA remediation pass, the site read as "any 2025 dark fintech site" — generic Inter / Space Grotesk typography, glowing radial orbs as the only background, repeated card grids, off-the-shelf icons. Wave A replaced the foundation with a distinctive, operational visual system.

Aesthetic direction locked: Bricolage Modernist. Swiss-influenced grid with brand warmth — think Stripe / Linear / Vercel rigor, but with route-handoff visuals and warmer accent colours that ground the site in Kaya Sync's domain. Chosen over Editorial / Warm Paper and Documentary Field after a side-by-side comparison.

What changed

LayerFromTo
Display typeSpace GroteskBricolage Grotesque (variable, 500–800)
Mono accentnoneJetBrains Mono for timestamps, IDs, operational labels
Body typeInterInter (kept — workhorse)
Dark surface#05070d (cool blue-ink)#0b0d12 (deeper, warmer)
Background atmosphereTwo animated radial-blur orbs (orange + teal)Swiss dot-grid plate + brand-gradient scroll-triggered route line under nav
Brand accentsflat orange + teal+ data accents (#4ec38a green, #d99a3a amber) used sparingly in artefact cards only
HeroSingle centred columnAsymmetric 7/12 + 5/12 layout with a custom RouteBand artefact on the right
Section eyebrowsPlain text-brand-orangeMono micro-caps with rule line

New components shipped

  • RouteBand.astro — the hero's right-column artefact. Five labelled handoff stops on a brand-gradient route, mono timestamps, "Live" pulse indicator, CAPACITY · HANDOFFS · EVIDENCE footer. Tells the visitor what the product is before they read a word.
  • EvidenceCard.astro — small mock receipt-style block showing HANDOFF · 12:34, anonymised route, signed-off mark. Lives in the Field Reality section.
  • CoordinationCard.astroRequest → Match → Confirm stack with mono timestamps and color-coded status pills. Lives in the How It Works snippet.
  • StatBand.astro — full-width band between Problem and How It Works with three high-level figures (16 ECOWAS countries · 1 controlled pilot in preparation · 8 founding team members). Numbers count up on scroll into view.
  • motion.ts — tiny IntersectionObserver helper, no deps, respects prefers-reduced-motion.

Rebuilt sections

  • /how-it-works — 5 steps now render as a vertical journey rail. A continuous orange→teal route line connects 5 station dots, each step has a mono header (01 ── REQUEST · 08:14 [OPEN]) and a colour-coded status pill (OPEN / CAPTURED / ACTIVE / RESOLVED / VERIFIED).
  • /technology — first tried a heavy "ops dashboard" treatment (sparklines, mock metrics, terminal-style header). Pulled back at NKA review to a clean 2-column list: brand icon + title + paragraph. Reads quiet and breathes.
  • /team — first tried a "personnel manifest" treatment (mono IDs, function classifiers, signature footer). Pulled back at NKA review to a clean grid: brand-tinted initials block + name + role + bio. No card chrome.
  • Footer split into 4 columns: brand block · Company (How It Works, Business Model, Technology, Team) · Partners (Pilot, Settlement, Government, Operators, Investors) · Reach us. Headings in mono micro-caps.
  • Nav uses the real /img/logo.jpg image at top-left (matches footer treatment), and the scroll-triggered underline now carries the brand-orange → brand-teal gradient.

Behaviour preserved

  • ClientRouter view transitions
  • Light/dark theme persistence across navigation (astro:before-swap)
  • PUBLIC_IS_TEST noindex on staging
  • Form pipeline via Resend (/api/lead)
  • All Level-1 banned terms still return zero matches in deployed HTML

Fixes shipped alongside

  • OG previews were 404-ing because public/og/*.png was never generated — pointed BaseLayout default at /img/logo.jpg so every social share resolves
  • FieldReality section (with EvidenceCard) was orphaned — slotted into the homepage between AudienceGrid and CloudUseCase

Commits

SHAMessage
4d75dfeRemediate site per NKA brief for Google Cloud reapplication
2ae52bcWave A design rethink: Bricolage Modernist foundation
fb836d6Fix OG image 404s and slot FieldReality into homepage

2026-05-27 — v1.0.1: production cutover to kayasync.com

NKA signed off on the deployed test build. Production deploy infrastructure added and kayasync.com flipped from the legacy "Coming Soon" placeholder to the new Wave A site.

What changed

  • Tag-triggered prod workflow (.github/workflows/deploy-prod.yml): pushes to main continue to auto-deploy test.kayasync.com; only git push origin v* triggers a production deploy. Gives every shipped version a named git tag (rollback = re-tag at an older SHA and push).
  • Separate prod Worker (kayasync-website-prod) bound to both kayasync.com and www.kayasync.com via Cloudflare Workers Custom Domains. The test Worker (kayasync-website-test) is untouched on test.kayasync.com.
  • Build patch step in prod workflow: after npm run build, the workflow uses jq to overwrite name and routes in the Astro-generated dist/server/wrangler.json (Cloudflare's wrangler env blocks don't survive the @astrojs/cloudflare adapter's config-redirect, so an in-place patch is the cleanest fix).
  • PUBLIC_IS_TEST not set for the prod build → no <meta name="robots" content="noindex,nofollow">, so Google can crawl.
  • OG images still falling back to /img/logo.jpg (per-page OG cards still pending in Wave B).

Two false starts before the actual ship

  1. v1.0.0 attempt #1 failed because the workflow used wrangler deploy --config wrangler.prod.jsonc, which disabled the Astro adapter's virtual-entry resolution (@astrojs/cloudflare/entrypoints/server).
  2. v1.0.0 attempt #2 (after switching to --env prod) deployed successfully but silently bound to test.kayasync.com again — @astrojs/cloudflare doesn't materialise env-specific overrides into the generated wrangler.json (it only lists them in definedEnvironments), so --env prod had nothing to apply.
  3. v1.0.0 attempt #3 (with the jq-patch approach) failed at the custom-domain binding step: Hostname 'kayasync.com' already has externally managed DNS records (A, CNAME, etc). Delete them first or try a different hostname. Existing DNS records from the old "Coming Soon" placeholder were intercepting the apex.
  4. v1.0.1 — DNS cleared manually in the Cloudflare dashboard, re-tagged at the same fix commit, deployed cleanly.

Smoke checks (post-deploy, 2026-05-27)

  • kayasync.com and www.kayasync.com → 200
  • All 12 routes (/, /how-it-works/, /business-model/, /team/, /technology/, /pilot-partners/, /government/, /settlement-partners/, /operators/, /investors/, /privacy/, /terms/) → 200
  • Title: Kaya Sync | From Anywhere, to Everywhere (not the legacy "Coming Soon")
  • Canonical: https://kayasync.com/
  • Robots meta: absent (production-correct)
  • Fonts loaded: Bricolage Grotesque + Inter + JetBrains Mono
  • Wave A content markers present: route-band__frame, stat-band__num, cd-card__head, /img/logo.jpg
  • Banned-term grep on the deployed home HTML: zero matches

Commits

SHATagMessage
c4461ecv1.0.1Fix prod deploy: patch generated wrangler.json in workflow
f474ee0Switch prod deploy to wrangler environments (didn't work, kept commit for history)
76fdffcAdd tag-triggered production deploy to kayasync.com

How to ship the next version

bash
# normal work on main keeps auto-deploying to test
git push origin main

# when test is approved, promote to prod
git tag v1.0.2          # bump patch / minor / major as appropriate
git push origin v1.0.2  # triggers .github/workflows/deploy-prod.yml

2026-06-03 — v1.1.0: NKA round-2 form remediation

NKA flagged ahead of the Google Cloud reapplication that all partnership forms were failing on prod and that several field-level issues needed fixing. Resolved in two passes.

Priority 1 (resolved out-of-band before code)

All partnership forms on prod returned 500 "Server is not configured (no API key found)". Root cause: the v1.0.1 prod deploy created a fresh kayasync-website-prod Worker that had no RESEND_API_KEY secret — Cloudflare Worker secrets are per-worker and the test worker's secret didn't carry over. Fix: npx wrangler secret put RESEND_API_KEY --name kayasync-website-prod with the existing Resend key, run with a temporary CLOUDFLARE_API_TOKEN. Live the moment it was set, no redeploy needed.

Smoke-tested all 5 forms on prod, all 200, all 5 lead emails confirmed received.

Priority 2 (shipped as v1.1.0)

ItemWhere
Full global country list on partnership formsInvestor, Enterprise, Government, Settlement
African-only country dropdown on Operator (new field)Operator
Phone field accepts country code (dial-code dropdown + phone input, combined to one value on submit)All non-Operator forms
Operator phone unchanged (explicit NKA exception)Operator
"PAYG devices" added to Partnership interestSettlement
Volume label adds "(Kg)"Enterprise
"Main Route" relabelled "Corridor", converted from free text to a select with the 10 Techiman corridors + "Other"Operator
"Other → free text" reveal pattern (paired input revealed when select = Other; merged back into parent field as "Other: <text>" on submit)Universal — Enterprise (sector + interest_area), Settlement (institution_type), Operator (vehicle + corridor)
Fallback support contact (cto@kayasync.com) retained in FormShell error pathAll forms

New / changed files

  • New: src/lib/countries.ts — generated from restcountries.com, exports countries (250+), africa (54), dialCodes (name → E.164 code map)
  • Changed: FormField.astro (new props phoneWithCountryCode, revealOtherAs), FormShell.astro (JS combines code+phone and folds Other-reveal on submit), api/lead.ts (server-side no-JS fallback for both combining patterns), InvestorForm.astro, EnterpriseForm.astro, GovernmentForm.astro, SettlementForm.astro, OperatorForm.astro

Decisions taken under the brief

  • Other-reveal pattern applied universally — NKA's note listed "Sector → Other reveals free text" under the Operator form, but Operator has no Sector field. Interpreted intent as the pattern, applied wherever a select has "Other" rather than adding a literal Sector field to Operator.
  • Volume (Kg) applied to Enterprise only — NKA listed it under Operator but only Enterprise has the volume field. Operator users are drivers, not shippers.
  • Phone country code via separate dial-code dropdown + tel input — chosen over single tel-with-pattern (too easy to skip) and country-driven auto-fill (more JS surface, edge-case prone). Combined to one phone_or_whatsapp value on submit so the API and email format stay unchanged.

Verification

End-to-end smoke tests on both test.kayasync.com and kayasync.com exercising every NKA item (Operator corridor reveal, Investor phone-code split, Enterprise Other-sector + Volume(Kg), Settlement PAYG, Government global country). All 10 returned 200 and landed in cto@kayasync.com inbox.

Commits

SHATagMessage
85afa3fv1.1.0Forms: NKA round-2 remediation (countries, phone codes, corridors, PAYG)

2026-06-03 — v1.1.1: make /privacy/ and /terms/ indexable (Google-readiness audit close-out)

After v1.1.0 shipped, NKA's earlier Google-readiness memo (five technical gates that must be closed before the Google for Startups Cloud reapplication) was re-read and audited gate-by-gate. Four of the five gates were already closed by work shipped through v1.1.0; one real code issue was found and fixed in this release; the rest is on Evanson (Google Search Console + email deliverability tests).

Gate audit summary

GateStatus going inAction
Google indexing freshness✅ Production serves clean contentNone on our side. Evanson: set up GSC, submit sitemap, request indexing for the 8 priority URLs
Sitemap / canonical / staging treatment✅ All clean (sitemap-0.xml has only prod URLs, every priority URL canonical-tagged at apex, test still noindexed)None
Form routing tested end-to-end✅ Done in v1.1.0 (10 smoke emails delivered to cto@ + kobby.andah@)None
Published email deliverability (hello@, privacy@, legal@)✅ MX + SPF configured (Google Workspace); ⚠️ functional test needs Evanson to send actual messagesNone on code side
Production metadata + social previews✅ All 8 priority URLs have correct title / description / OG image / Twitter cardNone (Wave B can later swap in per-page OG cards)

The one real fix in this release

/privacy/ and /terms/ had noindex={true} hardcoded on their BaseLayout call — leftover from the early-draft phase when the policies weren't finalised. NKA explicitly listed both as priority diligence URLs that need to be indexed. Removed the prop from both pages; the test environment still applies noindex automatically via PUBLIC_IS_TEST=true (the shouldNoIndex = noindex || isTestEnv logic in BaseLayout.astro), so test-env behaviour is unchanged.

Versioning note

This was tagged v1.0.3 initially, then re-tagged as v1.1.1 (same commit, cleaner semver — v1.0.3 would have been a step backwards after v1.1.0). The v1.0.3 tag was deleted both locally and on origin to keep the audit trail clean.

Commits

SHATagMessage
4447777v1.1.1Make /privacy/ and /terms/ indexable

Verification (post-deploy)

bash
curl -sL https://kayasync.com/privacy/ | grep -E '<meta name="robots"'  # expect EMPTY
curl -sL https://kayasync.com/terms/   | grep -E '<meta name="robots"'  # expect EMPTY
curl -sL https://test.kayasync.com/privacy/ | grep -E '<meta name="robots"'  # expect noindex,nofollow

All three confirmed in this state on 2026-06-03.

Still on Evanson (no code, blocks Google reapplication)

  1. Google Search Console: add property → verify (DNS TXT or Workspace) → submit https://kayasync.com/sitemap-index.xml → URL Inspection → Request Indexing for each of the 8 priority URLs.
  2. Email deliverability: send self-tests to hello@kayasync.com, privacy@kayasync.com, legal@kayasync.com. Set up as Workspace aliases on cto@ if any bounce.
  3. (Optional) add a DMARC TXT record for outbound deliverability hygiene. Not blocking for Google.

Once GSC has crawled and emails are confirmed deliverable, Google for Startups Cloud reapplication can be submitted.


What's next (not yet shipped)

  • Wave B — custom illustrations. 5–6 spot illustrations to replace generic icons in the key narrative slots (hero, problem, how-it-works steps, field reality, settlement, team). Drafted as Gemini prompts, integrated as inline SVG.
  • Per-page OG images. Replace the logo-as-fallback with proper per-page OG cards that match the new visual system. Drop them into public/og/ and restore the per-page ogImage props.
  • Brand mark refresh. Out of scope for Wave A; revisit if Wave B alone doesn't lift the visual signal enough.

Cross-references

Kaya Sync Internal Documentation