Problem
Apps served via Vercel rewrites (e.g. /us/watca, /us/taxsim) render their own UI — they don't get policyengine-app-v2's header/footer. This means:
- Inconsistent header/footer between the main site and rewrite-proxied apps
- We use rewrites (not iframes) for SEO — search engines can index the content under
policyengine.org
- But the trade-off is losing the shared shell
Proposed solution
Extract the header and footer into the existing @policyengine/design-system package (or a new @policyengine/shell package) so any app can import and render the same header/footer.
Scope of work
Components to extract (~900 lines across 10 components)
Header (7 components):
HomeHeader.tsx — root header with nav items
HeaderContent.tsx — layout container
HeaderLogo.tsx — logo + home link
DesktopNavigation.tsx — desktop nav menu
NavItem.tsx — individual nav item with dropdown support
CountrySelector.tsx — country/region switcher
MobileMenu.tsx — mobile hamburger menu (Sheet/Drawer)
Footer (2 components):
Footer.tsx — links, social icons, copyright
FooterSubscribe.tsx — newsletter subscription form (Mailchimp)
Optional:
GiveCalcBanner.tsx — seasonal promotional banner
Dependencies to decouple
| Dependency |
Used by |
Replacement |
useCurrentCountry() (React Router useParams) |
Header, Footer, CountrySelector |
countryId prop |
useWebsitePath() (AppContext) |
HeaderLogo, nav items |
Plain <a> tags with absolute URLs |
useNavigate() / useLocation() (React Router) |
NavItem, CountrySelector |
onNavigate / onCountryChange callbacks |
Link (React Router) |
HeaderLogo, NavItem |
Plain <a> tags |
trackContactClicked / trackNewsletterSignup |
Footer, FooterSubscribe |
Optional callback props |
submitToMailchimp() |
FooterSubscribe |
Keep (uses jsonp, no app deps) |
Dependencies to keep as-is
@policyengine/design-system tokens (colors, spacing, typography) — already in the package
@tabler/icons-react — add as peer dep
- shadcn/ui primitives (Button, Input, DropdownMenu, Sheet, etc.) — need to either bundle or add as peer deps
jsonp — for Mailchimp subscription
Proposed component API
// Consumer usage in any app
import { Header, Footer } from '@policyengine/design-system';
<Header
countryId="us"
countries={['us', 'uk']}
onCountryChange={(id) => { /* update URL */ }}
navItems={[
{ label: 'Research', href: '/us/research' },
{ label: 'About', href: '/us/team' },
]}
/>
<Footer
countryId="us"
onNewsletterSuccess={(msg) => { /* analytics */ }}
/>
Repos affected
- policyengine-app-v2 — extract components, update imports
- working-americans-tax-cut-act-one (watca) — install package, add header/footer
- Any future rewrite-proxied apps — same pattern
Related
Problem
Apps served via Vercel rewrites (e.g.
/us/watca,/us/taxsim) render their own UI — they don't get policyengine-app-v2's header/footer. This means:policyengine.orgProposed solution
Extract the header and footer into the existing
@policyengine/design-systempackage (or a new@policyengine/shellpackage) so any app can import and render the same header/footer.Scope of work
Components to extract (~900 lines across 10 components)
Header (7 components):
HomeHeader.tsx— root header with nav itemsHeaderContent.tsx— layout containerHeaderLogo.tsx— logo + home linkDesktopNavigation.tsx— desktop nav menuNavItem.tsx— individual nav item with dropdown supportCountrySelector.tsx— country/region switcherMobileMenu.tsx— mobile hamburger menu (Sheet/Drawer)Footer (2 components):
Footer.tsx— links, social icons, copyrightFooterSubscribe.tsx— newsletter subscription form (Mailchimp)Optional:
GiveCalcBanner.tsx— seasonal promotional bannerDependencies to decouple
useCurrentCountry()(React RouteruseParams)countryIdpropuseWebsitePath()(AppContext)<a>tags with absolute URLsuseNavigate()/useLocation()(React Router)onNavigate/onCountryChangecallbacksLink(React Router)<a>tagstrackContactClicked/trackNewsletterSignupsubmitToMailchimp()jsonp, no app deps)Dependencies to keep as-is
@policyengine/design-systemtokens (colors, spacing, typography) — already in the package@tabler/icons-react— add as peer depjsonp— for Mailchimp subscriptionProposed component API
Repos affected
Related
<a>tags for rewrite-proxied app links)