Global Expat Advisors is the second brand of the Online Taxman group, serving international entrepreneurs, high-earning Americans abroad, and cross-border families who need integrated tax, structuring, and residency planning. I rebuilt the original dated, slow WordPress site first — a big aesthetic and performance improvement — and then led its migration onto a modern static-first stack. That second phase started by standing up a shared-code monorepo so GEA could be built on an existing component library and design system rather than from zero.
Global Expat Advisors
The second brand in the Online Taxman group. After rebuilding the slow WordPress site, I migrated it onto an Astro and Svelte stack by initiating a shared-code monorepo first, so the new site could reuse proven components and design tokens rather than starting over.

Global Expat Advisors
Live
Introduction

The Challenge
Global Expat Advisors originally ran as a dated WordPress site that looked its age and performed poorly, serving international entrepreneurs and high-earning Americans abroad. After the first rebuild's success, the team committed to migrating GEA onto the same modern static-first stack proven with Online Taxman, but standing up a second brand raised a decision: rebuild from scratch or invest in a shared-component system that could serve multiple brands.
The Outcome
GEA went live in production on the shared stack, proving that a second brand could be stood up on an existing component library, design-token system, and quality contract with theme overrides rather than a parallel codebase.
Tech Stack
Frontend
- Astro
- Svelte
- SCSS
- CSS
- Zag.js
- Usercentrics
- reCAPTCHA
- TanStack Form
- HTML
Language
- TypeScript
- GraphQL
- JavaScript
- Node.js
Backend
- WordPress
- Cloudflare Turnstile
- Turso
- OpenAI
Database
- libSQL
- SQLite
DevOps
- pnpm
- Netlify
- Husky
- Knip
- GitHub Actions
Tooling
- Google Tag Manager
- Calendly
- ESLint
- Stylelint
- Prettier
- Vitest
- Cursor
- Claude
- GitHub Copilot
- Astro 7 static-first pages with Svelte 5 islands hydrated only where genuine interactivity is needed — forms, dialogs, accordions, and search. GEA is one of two deployable sites in the workspace, alongside Online Taxman.
- A pnpm workspace monorepo (
sites/gea,sites/onlinetaxman, plus@repo/shared,@repo/design-tokens,@repo/eslint-config,@repo/stylelint-config,@repo/tsconfig). Each site owns its ownsrc/,public/,netlify/, Astro config, redirects, and env contract; no deployable app code lives at the root. - TypeScript in strict mode (no
any) across pages, page-data contracts, loaders, and shared exports. - SCSS Modules for all component styling, consuming neutral CSS custom properties emitted by
@repo/design-tokens, with a GEA-owned theme layer (src/styles/variables.css) mapping--theme-*inputs to the brand. - Zag.js headless state machines back the accessible interactive primitives (accordion, dialog, combobox, select, steps, menu, popover) used by shared components.
- WordPress content pulled over GraphQL through shared loaders for GEA's blog, categories, and author pages.
- Deployed on Netlify with site-owned
netlify.tomland functions; Google Tag Manager and Usercentrics consent handle analytics and privacy, and Calendly powers discovery-call scheduling. - Quality tooling: ESLint, Stylelint, Prettier, Vitest, Husky pre-commit, Knip, and GitHub Actions CI.

Key Implementation Details
Phase one: the WordPress rebuild
- The original GEA site was a dated WordPress build that looked its age and performed poorly.
- I rebuilt it end to end, delivering a substantially better-looking and considerably faster site — the version that carried the brand until the platform migration.
Phase two: the monorepo as step one, not cleanup
- Rather than scaffolding a second standalone Astro app, I initiated the pnpm workspace monorepo first, extracting Online Taxman's proven components, icons, utilities, WordPress helpers, and TypeScript contracts into
@repo/shared. - Design tokens moved into their own
@repo/design-tokenspackage with a documented ownership contract: neutral tokens upstream, brand decisions in each site's theme layer, and hard rules against shared code importing site style paths. - Boundary enforcement is automated —
style:boundaries:checkplus a design-token reference checker that rejects undefined custom properties and retired token names. - The design system itself is the work of my design partner Laurel; I own the monorepo architecture and the engineering that makes it consumable by two brands.
Theme-layer overrides instead of forks
- GEA reuses shared heroes, cards, steps, accordions, CTA blocks, headers, and footers, then varies them through site-owned
--theme-*inputs: dark surface tokens, brand typography and radii, button font tokens, and per-theme heading and eyebrow styling. - Where a shared component genuinely couldn't express a GEA need neutrally, the rule was site-local composition rather than coupling shared code to one brand — keeping the library honest for a third and fourth site.
- Site-private palette constants (
--gea-*) are permitted for one-off art direction but banned from@repo/sharedand from the other site.
Page data as the single source of truth
- Every route has a mirrored entry under
src/data/pages/, so copy, section composition, SEO metadata, and routing live in typed data files rather than inline in.astroroutes. - GEA's data directory is organised into
site/,site-shell/,content/,marketing/, andpages/, which keeps navigation, legal pages, service pages, and team/authority content editable without touching layout code.
Forms, anti-abuse, and lead capture
- GEA has site-owned Astro Actions for newsletter and discovery-call workflows, built on the shared form backend rather than a per-site reimplementation.
- Anti-bot coverage runs through a captcha provider abstraction supporting Cloudflare Turnstile and reCAPTCHA, with rate limiting, hostname fail-open handling, and Bouncer email validation.
- The newsletter form is progressively enhanced so it still submits without client JavaScript, and submission logging uses Turso/libSQL via Netlify functions.
CI and AI-assisted development workflow
- GitHub Actions CI detects affected workspaces and runs only the relevant shared/GEA/Online Taxman quality gates and Vitest suites, so a GEA-only change doesn't pay for a full-monorepo run.
- A second workflow runs an OpenAI-backed PR review that loads path-scoped repository rules (forms, content loaders, page data, schema, WordPress GraphQL) and a component inventory, then scores changes against a merge threshold.
- The repo carries a first-class agent surface —
.agents/rulesand.agents/skillsas canonical, with thin mirrors for Copilot, Cursor, and Claude — plus an.ai/tasksarchive documenting the decision trail for every migration slice.
What I Contributed
- Rebuilt the original dated, slow WordPress site end-to-end, delivering a substantially better-looking and considerably faster site that carried the brand until the platform migration.
- Initiated the pnpm workspace monorepo as step one of the modern-stack build, extracting proven components, design tokens, and typed contracts from Online Taxman into shared packages so GEA could be built on reuse rather than from zero.
- Built GEA's public surface on the shared foundation: service pages, blog/content loading, legal and resources pages, form workflows, and Netlify functions, with brand differentiation expressed through a site-owned theme layer rather than forking shared code.
- Engineered theme-layer overrides consuming neutral design tokens via
--theme-*inputs for dark surface tokens, brand typography, radii, button styling, and per-theme heading design, enabling two brands to share one component library with zero coupling to either.
Outcome
-
Shared components, fixes, and improvements now land on both GEA and Online Taxman at once under one enforced set of architectural and styling boundaries, materially lowering the long-term maintenance burden across both brands.
GEA is live in production on the shared stack, and it's the proof that the shared-system bet paid off: a second brand was stood up on an existing component library, design-token system, and quality contract, with brand differences expressed as theme overrides rather than a parallel codebase. The practical wins are speed of standing up brand two and a materially lower long-term maintenance burden — fixes and improvements to shared components now land on both sites at once, under one enforced set of architectural and styling boundaries.