feat(web): marketing landing page with Anthropic design system

Landing page at / matching claude.com/product/claude-code structure:
hero, surfaces, pricing, laptop-to-laptop, features, meets-you, faq, cta,
+ floating "Latest news" toaster. Motion-based scroll reveals.

Design system extracted from claude.com via playwriter reverse-engineering:
- Self-hosted Anthropic Sans/Serif/Mono fonts (6 woff2 files)
- --cm-* tokens in globals.css (clay #d97757, gray-050..900, fluid clamps)
- Serif display, Sans UI, Mono terminals & section markers
- Italic clay phrases for emphasis

Header rewritten for design consistency: claudemesh wordmark (mesh glyph +
serif), dark bg, nav (Docs · Pricing · Changelog · GitHub), "Start free" CTA.

Free-first messaging: hero subhead "Free and open-source. Forever.", primary
CTA "Start free", pricing defaults to Solo=Free.

Fixes:
- packages/api: comment out aiRouter (module removed in 1f094c4)
- packages/db/schema/mesh.ts: rename memberRelations → meshMemberRelations
  (missed in beeaa3b rename pass, caught via web build — ack'd by BotMou)
- credits/{api,server,index}: stub out @turbostarter/ai/credits/utils
- remove (marketing)/legal/[slug] route and common/mdx.tsx (cms-backed)
- sitemap: drop blog/legal enumeration (cms removed)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Alejandro Gutiérrez
2026-04-04 22:09:38 +01:00
parent e25115f1b0
commit 84e14ff410
28 changed files with 1358 additions and 2058 deletions

View File

@@ -1,42 +1,29 @@
"use client";
import { useTranslation } from "@turbostarter/i18n";
import { buttonVariants } from "@turbostarter/ui-web/button";
import { Icons } from "@turbostarter/ui-web/icons";
import { pathsConfig } from "~/config/paths";
import { TurboLink } from "~/modules/common/turbo-link";
import { Hero } from "~/modules/marketing/home/hero";
import { Surfaces } from "~/modules/marketing/home/surfaces";
import { Pricing } from "~/modules/marketing/home/pricing";
import { LaptopToLaptop } from "~/modules/marketing/home/laptop-to-laptop";
import { Features } from "~/modules/marketing/home/features";
import { MeetsYou } from "~/modules/marketing/home/meets-you";
import { FAQ } from "~/modules/marketing/home/faq";
import { CallToAction } from "~/modules/marketing/home/cta";
import { LatestNewsToaster } from "~/modules/marketing/home/toaster";
const HomePage = () => {
const { t } = useTranslation("common");
return (
<main className="flex min-h-[calc(100vh-4rem)] flex-col items-center justify-center px-4">
<div className="mx-auto max-w-3xl text-center">
<h1 className="text-4xl font-bold tracking-tight sm:text-6xl">
{t("home.title", { defaultValue: "Welcome to TurboStarter" })}
</h1>
<p className="mt-6 text-lg leading-8 text-muted-foreground">
{t("home.description", { defaultValue: "The fastest way to build your next SaaS. Authentication, billing, database, and UI components — all pre-configured and ready to go." })}
</p>
<div className="mt-10 flex items-center justify-center gap-x-6">
<TurboLink
href={pathsConfig.auth.login}
className={buttonVariants({ size: "lg" })}
>
{t("home.getStarted", { defaultValue: "Get Started" })}
<Icons.ArrowRight className="ml-2 size-4" />
</TurboLink>
<TurboLink
href="https://turbostarter.dev/docs"
className={buttonVariants({ variant: "outline", size: "lg" })}
target="_blank"
>
{t("home.documentation", { defaultValue: "Documentation" })}
</TurboLink>
</div>
</div>
</main>
<div
className="bg-[var(--cm-bg)] text-[var(--cm-fg)] antialiased"
style={{ fontFamily: "var(--cm-font-sans)" }}
>
<Hero />
<Surfaces />
<Pricing />
<LaptopToLaptop />
<Features />
<MeetsYou />
<FAQ />
<CallToAction />
<LatestNewsToaster />
</div>
);
};