Landing Page Redesign — Design Spec
Date: 2026-06-11 Status: Approved (brainstorm with ssh) Scope: Full rebuild ofui/src/pages/Landing.tsx and ui/src/components/landing/*
Why
Two drivers, in order:- Performance. The current landing pulls the fused 1.87MB react+three core chunk (via
@react-three/fiberin the hero shader) on every visit.manualChunkssplitting is a known dead end (regresses or TDZ-crashes — seeproject_three_react_chunk_entanglement). The fix is structural: no three.js on the landing at all. - Conversion. Twelve sections tell twelve stories; none drives a single action. The page needs one north star.
<body>.
Decisions (locked during brainstorm)
| Question | Decision |
|---|---|
| North-star conversion action | Payback calculator — the visitor’s own number does the selling |
| Scope | Full rebuild, not restructure |
| Architecture | Classic hero, calculator as section 2 — hero CTA scrolls to it |
| Stories that survive as full sections | WhatsApp ops, Ruby (AI), Clinical depth |
| Social proof | None. Too early — no testimonials, no logo strips, no invented stats |
| Aesthetic | Keep & refine current identity: light #fafafa, violet/teal accents, first-person voice. No 3D shader |
| SEO | Keep existing <title>/meta/OG/JSON-LD verbatim; add GEO layer on top |
Page structure (7 sections)
The narrative arc: credibility → your number → how we recover it → who’s working for you → clinical depth → answers → ask. Every section after the calculator justifies the number it showed.- Hero — h1: “AI-powered dental software built for Pakistan” (the literal GEO keyphrase, naturally worded). One-line promise. Primary CTA: “See what no-shows cost you ↓” (smooth-scrolls to §2). Secondary: “Book a demo”. Static product screenshot (AVIF/WebP) + CSS gradient atmosphere. No logos, no shader, no video.
- Payback calculator ★ — “How much are no-shows costing your clinic?” Existing math carries over (appts/day × 26 × no-show% → annual leak → ×0.40 recoverable; Lahore blended avg fee ≈ PKR 6k). Big animated result number. CTA directly under the result: “Recover this — book a demo”. Never discloses our price.
- WhatsApp ops — “Here’s how we recover it.” Pure HTML/CSS phone mock showing a real reminder→confirm→reschedule conversation. The 11-trigger lifecycle told simply.
- Ruby — “Your front desk never sleeps.” Morning brief + patient chat mocks (static HTML/CSS). Ruby branding per
feedback_ruby_branding— never “AI assistant” generic labels. - Clinical depth — charting, treatment plans, DICOM, before/after in one consolidated tabbed/grid showcase (merges today’s DicomSection + BeforeAfter + DetailedFeatures).
- FAQ — the GEO section — questions written exactly as people ask LLMs: “What is the best dental software in Pakistan?”, “Is there AI-powered dental software in Pakistan?”, “How does dental software reduce no-shows?”, “What does OdontoX cost?” (answer: pays for itself, see calculator — no price). Each answer is 2–4 natural sentences naming OdontoX. Mirrored 1:1 in FAQPage JSON-LD.
- Final CTA + footer — “Your first month pays for itself” callback. Footer keeps existing links, adds one keyword-bearing descriptive line.
/bridge page), MobileAppCTA (footer badge), Testimonials, standalone RoiCalculator section (it becomes §2).
Performance architecture
- Zero three.js / @react-three/fiber imports anywhere in the landing route. This unfuses the core chunk by construction.
- Budget: < 150KB JS (gzip) to first paint on
/; LCP < 1.5s on fast-4G; CLS ≈ 0. - §1–2 load eagerly (calculator is the north star). §3–7 stay
LazySection-gated as today. - All device/chat mocks are HTML/CSS. Hero screenshot is a compressed static image with explicit dimensions.
- Verify after build: landing route’s chunk graph must not include three/fiber; check with
vite build+ chunk inspection, and confirm fresh dist + matching live chunk hash on deploy (project_ui_build_stale_dist_2026_06_09).
SEO / GEO layer
- Keep verbatim: existing
<title>, meta description, OG/Twitter tags, SoftwareApplication JSON-LD inui/index.html. - Build-time prerendering of the landing route: deployed
index.htmlcontains the rendered section content (h1, h2s, FAQ text) as static HTML so non-JS crawlers (GPTBot, ClaudeBot, PerplexityBot, Google-Extended) read the full story. Implementation choice (vite prerender plugin vs. render-to-string postbuild script) is decided at planning time; constraint: must not break the SPA hydration or the existingpostbuild.js. - FAQPage JSON-LD generated from the §6 content — single source of truth so page text and schema never drift.
llms.txtat domain root: structured prose description (what OdontoX is, who it’s for, key capabilities, the keyphrases: best dental software Pakistan, #1 dental software Pakistan, AI-powered dental software, AI-powered dental software Pakistan — woven into sentences, not listed as spam).- Keyword placement: h1 (§1), section h2s, FAQ answers, footer line. Never stuffed; every occurrence is a readable sentence.
Constraints & guardrails
- First-person brand voice (“we”, “our platform”) — not smothered with “OdontoX” (
feedback_landing_brand_voice). - No DollarSign icons — Banknote only (
feedback_no_dollar_icons). - No superadmin mentions (
feedback_no_superadmin_public). - Payback calculator never discloses price.
- No invented metrics, clinic names, or testimonials anywhere.
- Mobile: every section must degrade to a single column; no iOS WebKit OOM risk (no shaders, no large videos).
- Existing routes/anchors that other surfaces link to (
#paybackfrom navbar,/onboarding,/legal?tab=book) must keep working;#savingsanchor maps to §2.
Out of scope
- Marketing-site subpages (
/bridge, pricing page, blog). - Any backend/API changes.
- Mobile app store presence.
- Paid-ads landing variants.
Success criteria
/route loads with no three.js chunk in its network waterfall.- Lighthouse mobile: Performance ≥ 90, SEO = 100 on the deployed page.
curl https://odontox.io/(no JS) returns HTML containing the h1, all section h2s, and full FAQ text.- FAQPage JSON-LD validates in Google Rich Results test.
- The calculator is reachable in one click/scroll from the hero and produces a number with two inputs.

