import type { TablerIcon as IconComponent } from '@tabler/icons-react'; import { IconBucket, IconCertificate, IconComponents, IconDeviceSdCard, IconFunction, IconKey, IconMail, IconMarkdown, IconPlugConnected, IconRouter, IconShieldLock, } from '@tabler/icons-react'; import { motion } from 'framer-motion'; import { useTranslation } from 'react-i18next'; import logoIcon from '../assets/logo-icon.svg'; import cloudflareLogo from '../assets/logos/provider-cloudflare.svg'; import digitaloceanLogo from '../assets/logos/provider-digitalocean.svg'; import hetznerLogo from '../assets/logos/provider-hetzner.svg'; import linodeLogo from '../assets/logos/provider-linode.svg'; import scalewayLogo from '../assets/logos/provider-scaleway.svg'; import vultrLogo from '../assets/logos/provider-vultr.svg'; import dockerLogo from '../assets/logos/tech-docker.svg'; import fluxLogo from '../assets/logos/tech-flux.svg'; import framerLogo from '../assets/logos/tech-framer.svg'; import grafanaLogo from '../assets/logos/tech-grafana.svg'; import honoLogo from '../assets/logos/tech-hono.svg'; import i18nextLogo from '../assets/logos/tech-i18next.svg'; import kubernetesLogo from '../assets/logos/tech-kubernetes.svg'; import postgresqlLogo from '../assets/logos/tech-postgresql.svg'; import prometheusLogo from '../assets/logos/tech-prometheus.svg'; import pulumiLogo from '../assets/logos/tech-pulumi.svg'; import reactLogo from '../assets/logos/tech-react.svg'; import reactHookFormLogo from '../assets/logos/tech-reacthookform.svg'; import reactQueryLogo from '../assets/logos/tech-reactquery.svg'; import reactRouterLogo from '../assets/logos/tech-reactrouter.svg'; import redisLogo from '../assets/logos/tech-redis.svg'; import stripeLogo from '../assets/logos/tech-stripe.svg'; import supabaseLogo from '../assets/logos/tech-supabase.svg'; import swaggerLogo from '../assets/logos/tech-swagger.svg'; import tailwindLogo from '../assets/logos/tech-tailwindcss.svg'; import traefikLogo from '../assets/logos/tech-traefikproxy.svg'; import typescriptLogo from '../assets/logos/tech-typescript.svg'; import viteLogo from '../assets/logos/tech-vite.svg'; import zodLogo from '../assets/logos/tech-zod.svg'; /** * The stack drawn as a cross-section: six labeled strata whose left-edge * accent steps teal→magenta with depth — the "nothing hidden, all the way * down" motif shared with the Grounded pillar mark. Each layer card carries * its technologies as brand-mark chips. * * Tech names are product nouns and stay untranslated; layer labels come from * landing.stack in the locale file. Brand marks are vendored simple-icons * SVGs with the brand fill stamped in (see the provider-*.svg convention). * Features without a real brand mark keep Tabler icons. */ type LayerKey = 'app' | 'api' | 'integrations' | 'edge' | 'ops' | 'infra'; /** Teal→magenta interpolation by stratum depth (0 = surface, 1 = bedrock). */ function depthColor(i: number, count: number) { const pct = Math.round(100 - (i / (count - 1)) * 100); return `color-mix(in oklch, var(--primary) ${pct}%, var(--secondary-accent))`; } /** A chip is either an icon-fronted feature name or a brand-marked product * (one or two SVG urls); `badge` renders a muted mono affix (e.g. "add-on"). * Brand marks ship at their official colors, unmodified — a mark whose * official color doesn't survive both themes gets a Tabler feature icon * instead, never a recolored logo. */ type Chip = ({ name: string; icon: IconComponent } | { name: string; imgs: string[] }) & { badge?: string; }; const LAYERS: Array<{ key: LayerKey; tech: Chip[] }> = [ { key: 'app', tech: [ { name: 'React 19', imgs: [reactLogo] }, { name: 'TypeScript', imgs: [typescriptLogo] }, { name: 'React Router 8', imgs: [reactRouterLogo] }, { name: 'Tailwind CSS', imgs: [tailwindLogo] }, { name: 'Shadcn UI', icon: IconComponents }, { name: 'TanStack Query', imgs: [reactQueryLogo] }, { name: 'Zod + React Hook Form', imgs: [zodLogo, reactHookFormLogo] }, { name: 'Framer Motion', imgs: [framerLogo] }, { name: 'MDX', icon: IconMarkdown }, { name: 'i18next', imgs: [i18nextLogo] }, { name: 'Vite 8', imgs: [viteLogo] }, ], }, { key: 'api', tech: [ { name: 'Hono', imgs: [honoLogo] }, { name: 'Supabase', imgs: [supabaseLogo] }, { name: 'PostgreSQL', imgs: [postgresqlLogo] }, { name: 'Supavisor', icon: IconPlugConnected }, { name: 'Edge Functions', icon: IconFunction }, { name: 'OpenAPI + Swagger docs', imgs: [swaggerLogo] }, { name: 'Redis', imgs: [redisLogo] }, ], }, { key: 'integrations', tech: [ { name: 'Stripe billing', imgs: [stripeLogo] }, { name: 'OAuth sign-in', icon: IconKey }, { name: 'SMTP email', icon: IconMail }, { name: 'S3 object storage', icon: IconBucket }, ], }, { key: 'edge', tech: [ { name: 'Traefik', imgs: [traefikLogo] }, { name: 'Kong gateway', icon: IconRouter }, { name: "Let's Encrypt TLS", icon: IconCertificate }, { name: 'Cloudflare DNS', imgs: [cloudflareLogo] }, { name: 'WireGuard', icon: IconShieldLock }, ], }, { key: 'ops', tech: [ { name: 'Docker', imgs: [dockerLogo] }, { name: 'Kubernetes', imgs: [kubernetesLogo] }, { name: 'Pulumi', imgs: [pulumiLogo] }, { name: 'Flux GitOps', imgs: [fluxLogo] }, { name: 'WAL-G backups', icon: IconDeviceSdCard }, { name: 'Grafana & Prometheus', imgs: [grafanaLogo, prometheusLogo] }, ], }, { key: 'infra', tech: [ { name: 'Hetzner', imgs: [hetznerLogo] }, { name: 'DigitalOcean', imgs: [digitaloceanLogo] }, { name: 'Linode', imgs: [linodeLogo] }, { name: 'Vultr', imgs: [vultrLogo] }, { name: 'Scaleway', imgs: [scalewayLogo] }, ], }, ]; export function StackSection() { const { t } = useTranslation(); return (

{t('landing.stack.headline')}{' '} {t('landing.stack.headlineHighlight')}

{t('landing.stack.subheading')}

{/* The cross-section: each stratum's left edge and label step teal→magenta with depth. */}
{LAYERS.map((layer, i) => (
{t(`landing.stack.layers.${layer.key}`)}
{layer.tech.map((item) => ( {'imgs' in item ? ( item.imgs.map((img) => ( )) ) : ( )} {item.name} {item.badge && ( {item.badge} )} ))}
))}
); }