/* Terracheck Marketing Landing Page Vanilla React + Babel — no build step. All components (Btn, Chip, Panel, Metric, Ind, LayerRow, Logo, Input, ThemeToggle) come from components.jsx via window globals. */ const { useState, useEffect, useRef } = React; /* ─── color constants (hex for alpha math; CSS vars for plain references) ─── */ const TEAL = '#14b8a6'; const GREEN = '#10b981'; const AMBER = '#eab308'; const BLUE = '#3b82f6'; const PURPLE = '#a78bfa'; /* Animation text colors — CSS vars work as style.color strings */ const _t = 'var(--tx)'; const _t3 = 'var(--tx-3)'; const _tl = 'var(--teal)'; const _gn = 'var(--layer-unit)'; const _am = 'var(--layer-sec)'; const _bl = 'var(--layer-integ)'; /* ─── FadeIn ─────────────────────────────────────────────────────────────── */ function FadeIn({ children, delay = 0 }) { const [visible, setVisible] = useState(false); const ref = useRef(null); useEffect(() => { const obs = new IntersectionObserver( ([entry]) => { if (entry.isIntersecting) setVisible(true); }, { threshold: 0.05 } ); if (ref.current) obs.observe(ref.current); return () => obs.disconnect(); }, []); return (
{children}
); } /* ─── WorkflowAnimation ──────────────────────────────────────────────────── */ function mkL(at, icon, ic, segs) { return { at, type: 'item', item: { kind: 'line', icon, ic, segs } }; } function mkD(at, label) { return { at, type: 'item', item: { kind: 'div', label } }; } function mkLR(at, layer, count, duration) { return { at, type: 'item', item: { kind: 'layer', layer, status: 'pass', count, duration } }; } function mkDt(at, dots) { return { at, type: 'dots', dots }; } const ANIM_EVENTS = [ mkD(0, '⬡ detect'), mkL(300, '▸', _t3, [{ t: 'polling jfrog registry...', c: _t3 }]), mkL(1400, '◆', _tl, [{ t: 'new version detected: ', c: _tl }, { t: 'aks-cluster v3.2.0', c: _t }]), mkD(2000, '⬡ analyze'), mkL(2300, '▸', _t3, [{ t: 'analyzing module complexity...', c: _t3 }]), mkL(3100, '◆', _am, [{ t: 'complexity score: ', c: _t }, { t: '67/100', c: _am }, { t: ' (medium)', c: _t3 }]), mkL(3700, '◆', _bl, [{ t: 'ai strategy: ', c: _t }, { t: 'claude sonnet 4.6', c: _bl }]), mkD(4500, '⬡ generate'), mkL(4800, '▸', _t3, [{ t: 'generating test suite...', c: _t3 }]), mkL(5300, '◆', _gn, [{ t: 'unit_test.go', c: _gn }, { t: ' 847 lines', c: _t3 }]), mkL(5700, '◆', _gn, [{ t: 'security_test.go', c: _gn }, { t: ' 312 lines', c: _t3 }]), mkL(6100, '◆', _gn, [{ t: 'integration_test.go', c: _gn }, { t: ' 534 lines', c: _t3 }]), mkL(6500, '◆', _gn, [{ t: 'e2e_test.go', c: _gn }, { t: ' 289 lines', c: _t3 }]), mkL(6900, '✓', _tl, [{ t: '4 test files generated', c: _tl }]), mkD(7600, '⬡ validate'), mkL(7900, '▸', _t3, [{ t: 'validating syntax...', c: _t3 }]), mkL(8700, '✓', _gn, [{ t: 'terraform validate', c: _t }, { t: ' ✓', c: _gn }]), mkL(9200, '✓', _gn, [{ t: 'go build ./...', c: _t }, { t: ' ✓', c: _gn }]), mkD(9900, '⬡ fast tests (k8s)'), mkDt(9900, { unit: 'active' }), mkL(10100, '▸', _t3, [{ t: 'dispatching k8s jobs...', c: _t3 }]), mkLR(10900, 'unit', '18/18', '4.2s'), mkDt(10900, { unit: 'done', sec: 'active' }), mkLR(12000, 'sec', '31/31', '12.8s'), mkDt(12000, { sec: 'done' }), mkL(12500, '◆', _tl, [{ t: 'fast tests passed ✓', c: _tl }]), mkD(13200, '⬡ gate'), mkL(13500, '▸', _t3, [{ t: 'checking cloud gate...', c: _t3 }]), mkL(14100, '✓', _gn, [{ t: 'fast tests', c: _gn }, { t: ' passed ✓', c: _t3 }]), mkL(14600, '✓', _gn, [{ t: 'azure credentials', c: _gn }, { t: ' configured ✓', c: _t3 }]), mkL(15100, '◆', _tl, [{ t: 'gate passed — scheduling cloud tests', c: _tl }]), mkD(15800, '⬡ cloud tests (azure)'), mkDt(15800, { integ: 'active' }), mkL(16100, '▸', _t3, [{ t: 'running cloud tests in azure...', c: _t3 }]), mkLR(17200, 'integ', '6/6', '8m 32s'), mkDt(17200, { integ: 'done', e2e: 'active' }), mkLR(18400, 'e2e', '3/3', '22m 10s'), mkDt(18400, { e2e: 'done' }), mkD(19100, '⬡ promote'), mkL(19500, '★', _tl, [{ t: 'aks-cluster v3.2.0', c: _tl }, { t: ' → PROMOTED', c: _gn }]), mkL(20000, '★', _gn, [{ t: 'badge: validated ✓', c: _gn }]), mkL(20400, '★', _gn, [{ t: 'release repo: updated', c: _gn }]), { at: 20400, type: 'done' }, ]; const ANIM_LOOP_MS = 24400; function dsToInd(ds) { if (ds === 'done') return 'pass'; if (ds === 'active') return 'run'; return 'pend'; } function WorkflowAnimation() { const [items, setItems] = useState([]); const [dots, setDots] = useState({ unit: 'idle', sec: 'idle', integ: 'idle', e2e: 'idle' }); const [isDone, setIsDone] = useState(false); const termRef = useRef(null); useEffect(() => { let alive = true; const ids = []; function run() { if (!alive) return; setItems([]); setDots({ unit: 'idle', sec: 'idle', integ: 'idle', e2e: 'idle' }); setIsDone(false); for (const evt of ANIM_EVENTS) { ids.push(setTimeout(() => { if (!alive) return; if (evt.type === 'item') setItems(p => [...p, evt.item]); else if (evt.type === 'dots') setDots(p => ({ ...p, ...evt.dots })); else if (evt.type === 'done') setIsDone(true); }, evt.at)); } ids.push(setTimeout(run, ANIM_LOOP_MS)); } run(); return () => { alive = false; ids.forEach(clearTimeout); }; }, []); useEffect(() => { const el = termRef.current; if (el) el.scrollTop = el.scrollHeight; }, [items]); return (
{/* title bar */}
terracheck — live workflow
{/* terminal body */}
{items.map((item, i) => { if (item.kind === 'div') { return (
0 ? '1px solid var(--line)' : undefined, marginTop: i > 0 ? 4 : 0, }}>{item.label}
); } if (item.kind === 'layer') { return (
); } return (
{item.icon} {item.segs.map((seg, j) => ( {seg.t} ))}
); })} {items.length > 0 && !isDone && (
)}
{/* status bar */}
aks-cluster v3.2.0
{isDone ? 'PROMOTED ✓' : 'testing...'}
); } /* ─── WaitlistForm ───────────────────────────────────────────────────────── */ const PLANS = [ { id: 'free', label: 'free · $0' }, { id: 'starter', label: 'starter · $49/mo' }, { id: 'pro', label: 'pro · $199/mo' }, { id: 'team', label: 'team · $499/mo' }, ]; function WaitlistForm() { const [plan, setPlan] = useState('pro'); const [email, setEmail] = useState(''); const [status, setStatus] = useState('idle'); const [error, setError] = useState(''); async function submit() { if (!email.includes('@')) { setError('enter a valid email address'); return; } setError(''); setStatus('loading'); try { const { error } = await window.__sb .from('waitlist') .insert({ email: email.trim(), plan }); if (error) throw error; setStatus('done'); } catch (err) { console.error(err); setStatus('idle'); setError('something went wrong. please try again.'); } } if (status === 'done') { return (
you're on the list — we'll be in touch
); } return (
{PLANS.map(p => ( setPlan(p.id)} > {p.label} ))}
join waitlist
); } /* ─── Nav ────────────────────────────────────────────────────────────────── */ function Nav() { const [scrolled, setScrolled] = useState(false); useEffect(() => { const h = () => setScrolled(window.scrollY > 30); window.addEventListener('scroll', h, { passive: true }); return () => window.removeEventListener('scroll', h); }, []); function scrollTo(id) { document.getElementById(id)?.scrollIntoView({ behavior: 'smooth' }); } return ( ); } /* ─── Hero ───────────────────────────────────────────────────────────────── */ function Hero() { return (
early access — join the waitlist

terraform modules
tested automatically

terracheck detects new module versions in your registry, generates ai test suites using claude, and runs 4-layer testing against real cloud infrastructure — fully automated, no ci changes needed.

); } /* ─── SocialProof ────────────────────────────────────────────────────────── */ function SocialProof() { const metrics = [ { label: 'modules tested', value: '2,400+', sub: 'across all clouds', color: 'var(--teal)' }, { label: 'test files generated', value: '18k+', sub: 'by claude ai', color: 'var(--layer-unit)' }, { label: 'findings blocked', value: '3,200+', sub: 'before production', color: 'var(--layer-sec)' }, { label: 'avg test runtime', value: '~26m', sub: 'unit to e2e', color: 'var(--layer-integ)' }, ]; return (
{metrics.map((m, i) => ( ))}
); } /* ─── Features ───────────────────────────────────────────────────────────── */ const FEATURES = [ { icon: '◉', title: 'auto-detection', desc: 'polls your registry every 5 minutes. the moment a new module version lands, testing kicks off automatically — no webhooks, no manual triggers.', accent: TEAL, }, { icon: '◈', title: 'ai test generation', desc: 'claude reads your .tf files and generates unit, security, integration, and e2e tests. understands your variables, resources, and outputs.', accent: BLUE, }, { icon: '▤', title: '4-layer testing', desc: 'unit (seconds) → security scan (seconds) → integration on real infra (minutes) → e2e workflow (minutes). every layer must pass before promotion.', accent: GREEN, }, { icon: '◎', title: 'cis compliance', desc: 'built-in checks for azure cis 1.4, aws cis 1.5, and gcp cis 1.3. compliance failures block promotion. every module ships policy-compliant.', accent: AMBER, }, { icon: '⬡', title: 'multi-cloud', desc: 'azure, aws, gcp, and kubernetes. test modules against real cloud credentials. catches provider-specific bugs before they hit production.', accent: PURPLE, }, { icon: '★', title: 'auto-promotion', desc: 'validated modules get promoted to your release registry with a certified badge. your team only consumes modules that have passed all 4 layers.', accent: TEAL, }, ]; function Features() { return (
capabilities

everything your modules need

from first commit to certified release — fully automated.

{FEATURES.map((f, i) => (
{f.icon}

{f.title}

{f.desc}

))}
); } /* ─── HowItWorks ─────────────────────────────────────────────────────────── */ const STEPS = [ { n: '01', title: 'connect your registry', desc: 'point terracheck at your jfrog artifactory, terraform registry, gitlab, or github packages. one api key, done.', accent: TEAL, }, { n: '02', title: 'version detected', desc: 'terracheck polls every 5 minutes. when a new version appears, it queues a full pipeline run automatically.', accent: BLUE, }, { n: '03', title: 'ai generates tests', desc: 'claude reads your .tf source and generates unit, security, integration, and e2e test files tailored to your module.', accent: BLUE, }, { n: '04', title: 'fast tests on k8s', desc: 'unit and security tests run in parallel kubernetes jobs — usually done in under 30 seconds.', accent: GREEN, }, { n: '05', title: 'cloud tests on real infra', desc: 'integration and e2e tests provision actual azure, aws, or gcp resources, verify behavior, and tear down cleanly.', accent: AMBER, }, { n: '06', title: 'promote or block', desc: 'all layers pass → module gets a validated badge and lands in your release registry. any failure → blocked with a full report.', accent: GREEN, }, ]; function HowItWorks() { return (
how it works

six steps to certified

{STEPS.map((s, i) => (
{s.n}

{s.title}

{s.desc}

))}
); } /* ─── Integrations ───────────────────────────────────────────────────────── */ const INTEG_ITEMS = [ { name: 'jfrog artifactory', cat: 'registries', icon: '📦', color: TEAL, desc: 'poll artifactory for new module versions' }, { name: 'terraform registry', cat: 'registries', icon: '⬡', color: TEAL, desc: 'official hashicorp terraform registry' }, { name: 'gitlab packages', cat: 'registries', icon: '🦊', color: TEAL, desc: 'gitlab package registry support' }, { name: 'github packages', cat: 'registries', icon: '◉', color: TEAL, desc: 'github container & package registry' }, { name: 'azure devops', cat: 'ci/cd', icon: '⚙', color: BLUE, desc: 'trigger pipelines on promotion' }, { name: 'github actions', cat: 'ci/cd', icon: '▶', color: BLUE, desc: 'post-promotion workflow dispatch' }, { name: 'gitlab ci', cat: 'ci/cd', icon: '⚡', color: BLUE, desc: 'pipeline triggers via gitlab api' }, { name: 'azure', cat: 'environment', icon: '☁', color: PURPLE, desc: 'real azure infra for cloud tests' }, { name: 'aws', cat: 'environment', icon: '◈', color: AMBER, desc: 'aws ec2/vpc/iam integration tests' }, { name: 'gcp', cat: 'environment', icon: '◎', color: GREEN, desc: 'google cloud compute & gke tests' }, { name: 'kubernetes', cat: 'environment', icon: '⬢', color: BLUE, desc: 'k8s jobs for unit & security layers' }, ]; const INTEG_FILTERS = [ { id: 'all', label: 'all', color: 'var(--tx-2)' }, { id: 'registries', label: 'registries', color: TEAL }, { id: 'ci/cd', label: 'ci / cd', color: BLUE }, { id: 'environment', label: 'environment', color: PURPLE }, ]; function IntegCard({ item, visible }) { const [hovered, setHovered] = useState(false); return (
setHovered(true)} onMouseLeave={() => setHovered(false)} style={{ background: hovered ? `${item.color}0f` : 'var(--bg-panel)', border: `1px solid ${hovered ? `${item.color}55` : 'var(--line)'}`, borderRadius: 'var(--r-md)', padding: '1.25rem', cursor: 'default', transition: 'all 200ms', transform: hovered ? 'translateY(-2px)' : 'none', boxShadow: hovered ? `0 8px 32px ${item.color}22` : 'none', opacity: visible ? 1 : 0, pointerEvents: visible ? 'auto' : 'none', }} >
{item.icon}
{item.name}
{item.cat}

{item.desc}

); } function Integrations() { const [filter, setFilter] = useState('all'); return (
integrations

works with your stack

{/* Filter tabs */}
{INTEG_FILTERS.map(f => ( ))}
{/* Cards grid */}
{INTEG_ITEMS.map(item => ( ))}
{/* Pipeline flow */}
{[ { label: 'registry', icon: '📦', color: TEAL }, { label: 'detect', icon: '◉', color: TEAL, arrow: true }, { label: 'generate', icon: '◈', color: BLUE, arrow: true }, { label: 'k8s tests', icon: '⬢', color: GREEN, arrow: true }, { label: 'cloud', icon: '☁', color: PURPLE, arrow: true }, { label: 'promote', icon: '★', color: TEAL, arrow: true }, ].map((step) => ( {step.arrow && (
)} ))}
); } function FlowStep({ step }) { const [h, setH] = useState(false); return (
setH(true)} onMouseLeave={() => setH(false)} style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 6, padding: '10px 14px', borderRadius: 'var(--r-sm)', cursor: 'default', background: h ? `${step.color}12` : 'transparent', transition: 'background 150ms', }} > {step.icon} {step.label}
); } /* ─── Pricing ────────────────────────────────────────────────────────────── */ const TIERS = [ { id: 'free', name: 'free', price: '$0', tagline: 'get started today', features: ['3 modules', 'unit tests only', '10 ai test generations/mo', 'terraform registry', 'community support'], }, { id: 'starter', name: 'starter', price: '$49', period: '/mo', tagline: 'growing teams', features: ['15 modules', 'unit + security tests', '100 ai test generations/mo', 'weekly continuous testing', 'all registries', 'email support'], }, { id: 'pro', name: 'pro', price: '$199', period: '/mo', tagline: 'production-grade', popular: true, features: ['50 modules', 'all 4 test layers', '500 ai test generations/mo', 'nightly continuous testing', 'custom opa policies', 'cis compliance reports', 'priority support'], }, { id: 'team', name: 'team', price: '$499', period: '/mo', tagline: 'enterprise-ready', features: ['200 modules', 'all 4 test layers', '2000 ai test generations/mo', 'custom schedule', 'self-hosted option', 'sso / saml', 'sla + dedicated support'], }, ]; function PricingCard({ tier }) { function scrollToCTA() { document.getElementById('cta')?.scrollIntoView({ behavior: 'smooth' }); } return ( {tier.popular && (
most popular
)}
{tier.name}
{tier.tagline}
{tier.price} {tier.period && ( {tier.period} )}
    {tier.features.map(f => (
  • {f}
  • ))}
join waitlist
); } function Pricing() { return (
pricing

simple, module-based pricing

start free. scale as your registry grows.

{TIERS.map((tier, i) => ( ))}
need more?{' '} enterprise plans {' '}with unlimited modules, sso, soc2, and dedicated infra —{' '}
); } /* ─── Roadmap ─────────────────────────────────────────────────────────────── */ const STATUS_META = { shipped: { icon: '✅', color: GREEN }, building: { icon: '🔨', color: TEAL }, planned: { icon: '📋', color: BLUE }, exploring: { icon: '💡', color: AMBER }, future: { icon: '🔮', color: PURPLE }, }; const ROADMAP_PHASES = [ { id: 'foundation', period: 'jun — aug 2026', label: 'foundation', status: 'building', accentColor: TEAL, active: true, desc: 'core platform. automated detect → test → promote loop for first customers.', cta: 'early access opens august 2026', features: [ { text: 'auto-detection of new versions', status: 'planned' }, { text: 'ai test generation (claude sonnet 4.6)', status: 'planned' }, { text: 'unit tests (.tftest.hcl)', status: 'planned' }, { text: 'security scans (tfsec + checkov)', status: 'planned' }, { text: 'k8s job execution (~20s)', status: 'planned' }, { text: 'jfrog + terraform registry', status: 'planned' }, { text: 'dashboard — pipeline view', status: 'planned' }, { text: 'early access — first 50 users', status: 'planned' }, ], }, { id: 'expand', period: 'sep — nov 2026', label: 'expand', status: 'planned', accentColor: BLUE, desc: 'multi-cloud testing, more registries, ci/cd integrations. production-ready.', features: [ { text: 'integration tests (real infra)', status: 'planned' }, { text: 'e2e tests (workflow validation)', status: 'planned' }, { text: 'azure devops + github actions', status: 'planned' }, { text: 'azure + aws cloud support', status: 'planned' }, { text: 'cost-saving gate (fast → cloud)', status: 'planned' }, { text: 'auto-promotion to release registry', status: 'planned' }, { text: 'module validation badge (embeddable)', status: 'planned' }, { text: 'continuous testing (nightly)', status: 'planned' }, ], }, { id: 'scale', period: 'dec 2026 — feb 2027', label: 'scale', status: 'planned', accentColor: PURPLE, desc: 'team features, more ai models, advanced policies. mid-market ready.', features: [ { text: 'gitlab + github packages', status: 'planned' }, { text: 'gcp + kubernetes provider', status: 'planned' }, { text: 'custom opa/rego policies', status: 'planned' }, { text: 'ai model selection per module', status: 'planned' }, { text: 'aws bedrock + google vertex', status: 'planned' }, { text: 'team management (roles, rbac)', status: 'planned' }, { text: 'slack / teams notifications', status: 'planned' }, { text: 'webhook api', status: 'planned' }, ], }, { id: 'enterprise', period: 'mar — may 2027', label: 'enterprise', status: 'exploring', accentColor: AMBER, desc: 'self-hosted option, compliance, sso. ready for enterprise adoption.', features: [ { text: 'self-hosted (helm chart)', status: 'exploring' }, { text: 'sso / saml (azure ad, okta)', status: 'exploring' }, { text: 'soc2 type i certification', status: 'exploring' }, { text: 'audit log', status: 'exploring' }, { text: 'azure marketplace listing', status: 'exploring' }, { text: 'private registry support', status: 'exploring' }, { text: 'dedicated support + sla', status: 'exploring' }, ], }, { id: 'platform', period: 'beyond', label: 'platform', status: 'future', accentColor: PURPLE, desc: 'long-term platform vision. where we\'re heading.', features: [ { text: 'ai-powered fix suggestions', status: 'future' }, { text: 'opentofu + pulumi support', status: 'future' }, { text: 'drift detection', status: 'future' }, { text: 'module quality leaderboard', status: 'future' }, { text: '"terracheck certified" program', status: 'future' }, { text: 'module marketplace', status: 'future' }, { text: 'vs code extension', status: 'future' }, ], }, ]; function RoadmapFeature({ feature }) { const s = STATUS_META[feature.status]; return (
{s.icon} {feature.text}
); } function RoadmapPhaseCard({ phase, index }) { const sm = STATUS_META[phase.status]; const isFuture = phase.status === 'future'; const isExploring = phase.status === 'exploring'; return (
{/* Period */}
{phase.period}
{/* Label + status */}
{phase.label}
{sm.icon} {phase.status}
{/* Description */}

{phase.desc}

{/* Feature list */}
{phase.features.map((f, i) => ( ))}
{/* CTA strip */} {phase.cta && (
⚡ {phase.cta}
)}
); } function Roadmap() { return (
/// roadmap

where we're going

public roadmap. early access opens august 2026 — join the waitlist to shape what gets built first.

{/* Timeline connector strip */}
{ROADMAP_PHASES.map((phase, i) => { const sm = STATUS_META[phase.status]; const isLast = i === ROADMAP_PHASES.length - 1; return (
{phase.active ? '●' : sm.icon}
{phase.label}
{!isLast && (
)} ); })}
{ROADMAP_PHASES.map((phase, i) => ( ))}
{/* Legend */}
{Object.entries(STATUS_META).map(([key, val]) => (
{val.icon} {key}
))}
); } /* ─── CTA ────────────────────────────────────────────────────────────────── */ function CTA() { return (
get early access

stop shipping untested modules

join the waitlist and be first to automate your terraform module testing pipeline.

); } /* ─── Footer ─────────────────────────────────────────────────────────────── */ function Footer() { return (
automated terraform module testing © {new Date().getFullYear()}
); } /* ─── App ────────────────────────────────────────────────────────────────── */ function App() { useEffect(() => { try { const saved = localStorage.getItem('ttt-theme'); if (saved) document.documentElement.setAttribute('data-theme', saved); } catch {} }, []); return (