Homepage Brand Routing¶
Overview¶
A single OktaPT-FE codebase serves three distinct marketing experiences at /:
- Otera Health (
oterahealth.com) — full US clinic-buyer homepage - OKTA Health (
oktahealth.ru) — Russian-market clinic-buyer homepage - Custom tenants (12 clinic-branded deployments like
knosispt.oterahealth.com,stroma.oktahealth.ru) — minimal tenant-branded login gateway
Each deployment gets its own Next.js build with its own NEXT_PUBLIC_BRAND_NAME env var, so the root route resolves to a different top-level component per brand. Unused branches are tree-shaken out of each bundle.
Every other page (login, dashboards, onboarding, clinic-solutions, etc.) is shared across all brands.
Brand Resolution¶
Two independent mechanisms.
Build-time switch (pages/index.tsx)¶
NEXT_PUBLIC_BRAND_NAME is inlined by Webpack at build time. pages/index.tsx is a three-way switch:
if (process.env.NEXT_PUBLIC_BRAND_NAME === "OTERA") return <OteraHomePage />;
if (process.env.NEXT_PUBLIC_BRAND_NAME === "OKTA") return <OktaHomePage />;
return <CustomTenantHomePage />;
Because the env var is a compile-time constant in each deployment, the inactive branches are never loaded by that build.
Runtime hostname detection (lib/brand/parentBrand.ts)¶
CustomTenantHomePage renders for 12 different clinic brands. Each needs a "Learn more about [parent brand]" link back to the right marketing site — but the build itself has no way to know whether a given custom tenant lives on OTERA or OKTA infra.
detectParentBrandFromHostname() resolves this at runtime from window.location.hostname:
*.oktahealth.ruor*.oktahealth.com→ OKTA (https://oktahealth.ru)*.oterahealth.com→ OTERA (https://oterahealth.com)- Anything else (fully custom domain) → OTERA (default)
SSR renders the OTERA fallback so the server markup is stable; the real hostname is re-evaluated in a useEffect on the client.
OteraHomePage¶
Full 12-section Athelas-style clinic-buyer homepage. US market, vision-led narrative ("less screen time, more hands-on care"). Every product claim references a shipped feature.
Sections, in order:
OteraHero— gradient hero with demo CTAOteraTrustBar— tenant logo stripOteraScreenTimeProblem— problem framingOteraProductModules— 6 product cards (HEP, RTM, messaging, analytics, etc.)OteraForOwners— clinic-owner persona sectionOteraForTherapists— therapist persona sectionOteraRtmDeepDive— embeds the sharedRtmCalculatorwith live CMS 2025 rate mathOteraAiEngine— AI positioningOteraTestimonials— named clinic quotesOteraHowItWorks— onboarding flowOteraFAQOteraDemoCTA— full-width closer with demo calendar link
OktaHomePage¶
Stripped-down Russian-market variant. 8 sections. RTM/billing content is omitted entirely — CPT codes don't apply in Russia. Testimonials are omitted because the named quotes we have are US clinics. No how-it-works section yet.
All copy is sourced from public/locales/{en,ru}/clinic-home.json via next-i18next.
CustomTenantHomePage¶
Single-screen login gateway for non-flagship tenants. Renders for any deployment whose NEXT_PUBLIC_BRAND_NAME isn't OTERA or OKTA — currently 12 clinics (STROMA, KNOSISPT, JAGPT, MEDIFITRU, MSUPDSZN, TOBEPERFECT, INMOTIONSC, ARMY, THEBASE, ALLINPHYSICALTHERAPY, PHYSIOTHERAPISTRU, INTERNALXYXYZ).
Layout:
- Tenant logo (from
TENANT_LOGO_PATHSmap) - Tenant display name headline
- "Runs on {Otera|Okta}" subtitle — parent brand resolved at runtime from hostname
- Two login CTAs: "I'm a patient" / "I'm a therapist" (both go to
/login) - "Learn more about Otera/Okta" link pointing back to the parent marketing site
The /patients Route¶
Before the redesign, / was a patient-first landing page. After the redesign, / became the clinic-buyer marketing page, so the old patient-first page was moved verbatim to /patients. This preserves the SEO and external links pointing at patient-intent copy, and gives patients who land on the marketing site a dedicated destination.
Both / and /patients are listed in the publicRoutes array in middleware.ts, so they bypass auth and render for logged-out visitors.
Shared Marketing Components¶
Used by both OTERA and OKTA homepages to avoid duplication:
RtmCalculator— live reimbursement calculator with CMS 2025 CPT rates baked in. Also exportsRtmCptCodeListfor the code breakdown UIPersonaSection— two-column section template used by*ForOwnersand*ForTherapistson both brandsFeatureModuleCard— product module card used in the product-modules gridsDemoCTACard— full-width gradient closer with primary/secondary CTAs
Translations¶
All clinic-homepage copy lives in the clinic-home i18n namespace. Files:
public/locales/en/clinic-home.jsonpublic/locales/ru/clinic-home.json
pages/index.tsx's getStaticProps loads both common and clinic-home namespaces for every locale. See Translations for the {{variable}} interpolation syntax and validation script.
Key Files¶
| File | Role |
|---|---|
OktaPT-FE/pages/index.tsx |
Build-time three-way brand switch |
OktaPT-FE/pages/patients.tsx |
Preserved patient-first landing page |
OktaPT-FE/lib/brand/parentBrand.ts |
Runtime hostname → parent brand resolver |
OktaPT-FE/components/landing/otera/OteraHomePage.tsx |
Otera top-level homepage |
OktaPT-FE/components/landing/otera/sections/ |
Otera section components (12) |
OktaPT-FE/components/landing/okta/OktaHomePage.tsx |
OKTA top-level homepage |
OktaPT-FE/components/landing/okta/sections/ |
OKTA section components (8) |
OktaPT-FE/components/landing/custom/CustomTenantHomePage.tsx |
Custom-tenant login gateway |
OktaPT-FE/components/landing/shared/RtmCalculator.tsx |
Reusable RTM reimbursement calculator |
OktaPT-FE/components/landing/shared/PersonaSection.tsx |
Reusable owner/therapist persona layout |
OktaPT-FE/components/landing/shared/FeatureModuleCard.tsx |
Reusable product-module card |
OktaPT-FE/components/landing/shared/DemoCTACard.tsx |
Reusable demo CTA closer |
OktaPT-FE/public/locales/en/clinic-home.json |
English clinic-home strings |
OktaPT-FE/public/locales/ru/clinic-home.json |
Russian clinic-home strings |
OktaPT-FE/middleware.ts |
publicRoutes whitelist (includes / and /patients) |