Files
aigrowthtech/src/app/[lang]/page.tsx
T
Alejandro Veras 828a81f3a5 Add Spanish and Arabic versions, a contact form captcha and a multilingual sitemap
- English, Spanish (/es) and Arabic (/ar, right to left) versions of every page, with a language switch
- Self-hosted "I'm not a robot" check on the contact form; the message field is optional
- Google Tag Manager, GA4 and Search Console verification in the shared layout
- Sitemap, robots.txt and canonical links point at aigrowthtechnologies.com
2026-10-13 11:53:18 -04:00

378 lines
15 KiB
TypeScript

import { Fragment, type CSSProperties, type ReactNode } from "react";
import GlobeCanvas from "@/components/globe-canvas";
import StatCounter from "@/components/stat-counter";
import RevealObserver from "@/components/reveal-observer";
import Capabilities from "@/components/capabilities";
import QueryTicker from "@/components/query-ticker";
import ProductVisual from "@/components/product-visuals";
import Link from "next/link";
import { home } from "@/content/home";
import { localize } from "@/i18n/config";
import { getLocale } from "@/i18n/server";
type Vars = CSSProperties & Record<`--${string}`, string | number>;
const delay = (ms: number) => ({ "--d": `${ms}ms` }) as Vars;
const Arrow = () => <span className="arrow">→</span>;
function Eyebrow({ index, children }: { index?: string; children: ReactNode }) {
return (
<p className="eyebrow">
{index && <span className="idx">{index}</span>}
{children}
</p>
);
}
export default async function Home() {
const locale = await getLocale();
const c = home[locale];
const to = (path: string) => localize(path, locale);
const { hero, numbers, capabilities, technology, discovery, journey, difference, cta } = c;
return (
<>
{/* ───────────────────────── Hero ───────────────────────── */}
<section className="hero" id="top" aria-labelledby="hero-title">
<GlobeCanvas />
<div className="wrap hero-inner">
<div data-reveal>
<Eyebrow>{hero.eyebrow}</Eyebrow>
</div>
<h1 id="hero-title" className="display h1" data-reveal style={delay(120)}>
{hero.title}
</h1>
<div className="hero-grid">
<div className="hero-lead lead" data-reveal style={delay(260)}>
<p>{hero.lead}</p>
<p className="muted">{hero.leadMuted}</p>
</div>
<div className="hero-body" data-reveal style={delay(380)}>
<div className="copy">
<p>{hero.body}</p>
<p className="hl">{hero.highlight}</p>
</div>
<div className="hero-actions">
<Link href={to("/contact")} className="btn btn-solid">
{hero.primary} <Arrow />
</Link>
<Link href={to("/services")} className="btn btn-ghost">
{hero.secondary} <Arrow />
</Link>
</div>
</div>
</div>
<div className="hero-foot" data-reveal style={delay(520)}>
<div className="hero-channels" aria-hidden="true">
{hero.channels.map((ch, i) => (
<Fragment key={ch}>
{i > 0 && <i />}
<span>{ch}</span>
</Fragment>
))}
</div>
<a href="#evidence" className="scroll-cue">
{hero.scroll} <i />
</a>
</div>
</div>
</section>
{/* ───────────────────────── Numbers ───────────────────────── */}
<section className="section" id="evidence" aria-labelledby="evidence-title">
<div className="wrap">
<div className="section-head">
<div className="title" data-reveal>
<Eyebrow index="01">{numbers.eyebrow}</Eyebrow>
<h2 id="evidence-title" className="display h2">
{numbers.title}
</h2>
</div>
</div>
<div className="stats">
{numbers.stats.map((s, i) => (
<div key={s.label} className="stat" data-reveal style={delay(i * 120)}>
<StatCounter value={s.value} suffix={s.suffix} />
<div className="stat-label">{s.label}</div>
</div>
))}
</div>
</div>
</section>
{/* ───────────────────────── Capabilities ───────────────────────── */}
<section className="section section-night" id="capabilities" aria-labelledby="cap-title">
<div className="wrap">
<div className="section-head">
<div className="title" data-reveal>
<Eyebrow index="02">{capabilities.eyebrow}</Eyebrow>
<h2 id="cap-title" className="display h2">
{capabilities.title[0]}
<br />
{capabilities.title[1]}
</h2>
</div>
</div>
<div className="split">
<div className="lead" data-reveal>
<p>{capabilities.lead}</p>
</div>
<div className="copy" data-reveal style={delay(140)}>
<p>{capabilities.copy}</p>
<p className="hl">{capabilities.highlight}</p>
<p>{capabilities.after}</p>
</div>
</div>
<div data-reveal>
<Capabilities
items={capabilities.items.map((it) => ({ ...it, href: to(it.href) }))}
core={capabilities.core}
/>
</div>
</div>
</section>
{/* ───────────────────────── Proprietary technology ───────────────────────── */}
<section className="section" id="technology" aria-labelledby="tech-title">
<div className="wrap">
<div className="section-head">
<div className="title" data-reveal>
<Eyebrow index="03">{technology.eyebrow}</Eyebrow>
<h2 id="tech-title" className="display h2">
{technology.title}
</h2>
</div>
</div>
<div className="split">
<div className="lead" data-reveal>
<p>{technology.lead}</p>
<p className="muted">{technology.leadMuted}</p>
</div>
<div className="copy" data-reveal style={delay(140)}>
<p>{technology.copy}</p>
<p>
{technology.closing} <span className="hl">{technology.closingHighlight}</span>
</p>
</div>
</div>
<div className="products">
{technology.products.map((p, i) => (
<article key={p.name} className="product" aria-labelledby={`product-${i}`}>
<div className="product-visual" data-reveal>
<ProductVisual kind={p.visual} labels={technology.visuals} />
</div>
<div className="product-body" data-reveal style={delay(160)}>
<div className="product-kind">
<span dir="ltr">{String(i + 1).padStart(2, "0")} / 03</span>
<span className="pill">{p.kind}</span>
</div>
<h3 id={`product-${i}`} className="product-name">
{p.name}
</h3>
<h4 className="display h3">{p.headline}</h4>
<div className="copy">
{p.body.map((b) => (
<p key={b}>{b}</p>
))}
</div>
<Link href={to(p.href)} className="arrow-link">
{p.cta} <Arrow />
</Link>
</div>
</article>
))}
</div>
</div>
</section>
{/* ───────────────────────── Discovery ───────────────────────── */}
<section className="section section-night discovery" id="discovery" aria-labelledby="disc-title">
<div className="wrap">
<div className="section-head">
<div className="title" data-reveal>
<Eyebrow index="04">{discovery.eyebrow}</Eyebrow>
<h2 id="disc-title" className="display h2">
{discovery.title}
</h2>
</div>
</div>
<div className="discovery-stage" data-reveal>
<div className="query-label">{discovery.queryLabel}</div>
<QueryTicker queries={discovery.queries} />
<div className="surfaces">
<div className="surface left">
{discovery.searchPills.map((p) => (
<span key={p} className="pill">
{p}
</span>
))}
</div>
<div className="surface-core">{discovery.yourBrand}</div>
<div className="surface">
<span className="pill">ChatGPT</span>
<span className="pill">Gemini</span>
<span className="pill">AI Overviews</span>
<span className="pill">Perplexity</span>
</div>
</div>
</div>
<div className="split">
<div className="lead" data-reveal>
<p>{discovery.lead}</p>
<p className="muted">{discovery.leadMuted}</p>
</div>
<div data-reveal style={delay(140)}>
<div className="copy">
<p className="hl">{discovery.highlight}</p>
{discovery.copy.map((p) => (
<p key={p}>{p}</p>
))}
</div>
<Link href={to("/services/llmo")} className="arrow-link" style={{ marginTop: 28 }}>
{discovery.cta} <Arrow />
</Link>
</div>
</div>
</div>
</section>
{/* ───────────────────────── Attention to action ───────────────────────── */}
<section className="section" id="approach" aria-labelledby="journey-title">
<div className="wrap">
<div className="section-head">
<div className="title" data-reveal>
<Eyebrow index="05">{journey.eyebrow}</Eyebrow>
<h2 id="journey-title" className="display h2">
{journey.title}
</h2>
</div>
</div>
<div className="journey" data-reveal-group>
<ol>
{journey.steps.map((s, i) => (
<li key={s.label} style={{ "--i": i } as Vars}>
<span className="dot" />
<span className="channel">
{String(i + 1).padStart(2, "0")} — {s.channel}
</span>
<span className="step">{s.label}</span>
</li>
))}
</ol>
</div>
<div className="credit split">
<h3 className="display question" data-reveal>
{journey.question}
</h3>
<div className="copy" data-reveal style={delay(140)}>
{journey.copy.map((p) => (
<p key={p}>{p}</p>
))}
</div>
</div>
<figure className="pullquote" data-reveal>
<Eyebrow>{journey.quoteEyebrow}</Eyebrow>
<blockquote>{journey.quote}</blockquote>
<figcaption className="copy">
<p>{journey.caption}</p>
<p className="hl">{journey.captionHighlight}</p>
</figcaption>
<Link href={to("/about")} className="arrow-link">
{journey.cta} <Arrow />
</Link>
</figure>
</div>
</section>
{/* ───────────────────────── Connections ───────────────────────── */}
<section className="section section-night" id="difference" aria-labelledby="diff-title">
<div className="wrap">
<div className="section-head">
<div className="title" data-reveal>
<Eyebrow index="06">{difference.eyebrow}</Eyebrow>
<h2 id="diff-title" className="display h2">
{difference.title}
</h2>
</div>
</div>
<ul className="gaps">
{difference.gaps.map((g, i) => (
<li key={g} data-reveal style={delay(i * 80)}>
<span>{g}</span>
<svg className="break" viewBox="0 0 120 14" aria-hidden="true">
<line x1="0" y1="7" x2="50" y2="7" />
<line x1="70" y1="7" x2="120" y2="7" />
<line className="cut" x1="55" y1="1" x2="65" y2="13" />
</svg>
</li>
))}
</ul>
<div className="split" style={{ marginTop: "clamp(80px, 10vw, 144px)" }}>
<h3 className="display h2" data-reveal>
{difference.gapTitle}
</h3>
<div className="copy" data-reveal style={delay(140)}>
<p>{difference.copy}</p>
<p className="hl">{difference.highlight}</p>
</div>
</div>
<div className="nos">
{difference.nos.map((n, i) => (
<div key={n} data-reveal style={i ? delay(i * 120) : undefined}>
<span>
{difference.noLabel} {String(i + 1).padStart(2, "0")}
</span>
{n}
</div>
))}
</div>
<p className="closing" data-reveal>
{difference.closing}
</p>
</div>
</section>
{/* ───────────────────────── CTA ───────────────────────── */}
<section className="cta" id="contact" aria-labelledby="cta-title">
<GlobeCanvas layout="center" />
<div className="wrap">
<div data-reveal>
<Eyebrow>{cta.eyebrow}</Eyebrow>
</div>
<h2 id="cta-title" className="display h2" data-reveal style={delay(120)}>
{cta.title}
</h2>
<div className="copy" data-reveal style={delay(240)}>
{cta.copy.map((p) => (
<p key={p}>{p}</p>
))}
</div>
<div className="lead" data-reveal style={delay(320)}>
<p>{cta.lead}</p>
<p className="muted">{cta.leadMuted}</p>
</div>
<div data-reveal style={delay(400)}>
<Link href={to("/contact")} className="btn btn-solid">
{cta.button} <Arrow />
</Link>
</div>
</div>
</section>
<RevealObserver />
</>
);
}