import { useState, useEffect, useRef } from 'react'; import { useFadeInRef } from '../../hooks/useFadeIn'; import HexCanvas from './HexCanvas'; import ScrollStory from './ScrollStory'; import BottomIllustration from './BottomIllustration'; import { TickerValue } from '../ui/TickerValue'; import { ChevronIcon } from '../ui/icons/ChevronIcon'; import { LogoIcon } from '../ui/icons/LogoIcon'; import { trackEvent } from '../../lib/analytics'; import type { FeatureMeta } from '../../types'; export default function HomePage({ onOpenDashboard, onOpenPricing: _onOpenPricing, theme = 'light', features = [], hidePricing: _hidePricing, }: { onOpenDashboard: () => void; onOpenPricing: () => void; theme?: 'light' | 'dark'; features?: FeatureMeta[]; hidePricing?: boolean; }) { const [statsActive, setStatsActive] = useState(false); useEffect(() => { const timer = setTimeout(() => setStatsActive(true), 300); return () => clearTimeout(timer); }, []); const whyRef = useFadeInRef(); const ctaRef = useFadeInRef(); // Scroll depth tracking const scrolledSections = useRef(new Set()); useEffect(() => { const ids = ['how-it-works', 'demo']; const observers: IntersectionObserver[] = []; ids.forEach((id) => { const el = document.getElementById(id); if (!el) return; const observer = new IntersectionObserver( ([entry]) => { if (entry.isIntersecting && !scrolledSections.current.has(id)) { scrolledSections.current.add(id); trackEvent('Scroll Depth', { section: id }); } }, { threshold: 0.1 } ); observer.observe(el); observers.push(observer); }); return () => observers.forEach((o) => o.disconnect()); }, []); // 30s time-on-page event useEffect(() => { const timer = setTimeout(() => trackEvent('Time on Page', { seconds: '30' }), 30000); return () => clearTimeout(timer); }, []); return (
{/* Hero */}

Maximum Value.
Minimum Compromise.

House hunting? Make your biggest investment your smartest move.

So many options - choosing the right one can feel overwhelming. Our interactive map makes it simple: select your must-haves and instantly see the areas that fit.

properties
filters
Every
postcode in England
{/* Our philosophy */}

Our philosophy

Listings show what's available, not what's possible — fragments without context. Traditional tools force you to begin with a location, separating area insight from property detail. You search, cross-reference, and repeat per location.

We take a different approach. Start with what matters to you, and the right places reveal themselves. No context lost. No property missed.

{/* How to use it + Comparison table (two columns) */}
{/* Left: How to use it */}

How to use it

{HOW_STEPS.map((step, i) => (
{i + 1}

{step.title}

{step.description}

))}
{/* Right: Comparison table */}

Others vs{' '} Perfect Postcode{' '}

{FEATURE_ROWS.map((row, i) => ( {[row.listings, row.postcode, row.guides].map((has, j) => ( ))} ))}
Listing portals {'\u201CCheck my postcode\u201D'} Area guides Perfect Postcode
{row.feature} {row.subtitle && (
{row.subtitle}
)}
{has ? '\u2713' : '\u2717'}
{/* Scrollytelling: Problem + Solution + Demo map */}

See It in Action

{/* The real cost CTA */}

Make your biggest investment your smartest move.

This deserves proper tools behind it — don't leave it to luck.

{/* Bottom illustration */}
); } const FEATURE_ROWS = [ // listings postcode guides { feature: 'Search without choosing an area first', subtitle: '(start with needs, not a location)', listings: false, postcode: false, guides: false, }, { feature: 'Area data', subtitle: '(crime, schools, noise, broadband)', listings: false, postcode: true, guides: true, }, { feature: 'Property-specific data', subtitle: '(price, EPC, floor area)', listings: true, postcode: false, guides: false, }, { feature: '56 combinable filters in one place', subtitle: '(all insights, one interactive map)', listings: false, postcode: false, guides: false, }, ]; const HOW_STEPS = [ { title: 'Set your must-haves', description: 'Budget, commute, schools \u2014 the map shows only what qualifies.', }, { title: 'Explore areas and discover hidden gems', description: 'Zoom in, dig into details and nice to haves.', }, { title: 'Drill into postcodes', description: 'See individual properties, sale prices, floor area, and compare.', }, { title: 'Shortlist with confidence', description: 'Every area on your list meets your actual criteria \u2014 not just what was listed that week.', }, ];