buildmymcpserver/apps/web/app/(marketing)/page.tsx
Marco Sadjadi 7a32385e2b
All checks were successful
Deploy to Production / deploy (push) Successful in 1m2s
feat(marketing): give each below-the-fold section its own visual archetype
Owner: "die sektionen unter dem video sehen viel zu ähnlich aus — das
kannst du besser." Correct — every section was the same `panel + 3-col
grid` pattern, no page rhythm. Each section now reads as its own type
of moment:

- **Clients** ("Connects everywhere your AI lives"): typographic logo
  row, no panels. Each client carries a small mono mark in a 7×7 box
  (C, ⌘, ✦, <>, →) plus a 17px tracking-tight wordmark. Group hover
  flips the mark and label to the accent colour so the row reads as
  interactive trust signal, not a wall of text. Generous py-20/24
  spacing — this is a beat between sections, not a feature card.

- **Examples** ("Wrap any HTTP API. In minutes."): asymmetric 2-col
  header (h2 left, supporting copy right) over a 3-col card grid
  where each integration carries a coloured 48×48 brand mark —
  Postgres `#336791`, Salesforce `#00a1e0`, Notion black-on-white,
  GitHub `#181717`, Stripe `#635bff`, Custom REST `#6366f1`. The marks
  give each card its own visual identity, breaking the uniform-card
  pattern. h2 sized 32/40 px (was a flat 28 px).

- **Marketplace** ("Skip the prompt. Fork what works."): split layout.
  Left column: eyebrow + headline + supporting paragraph + bullet
  list of the three selling points (no longer equal-weight cards) +
  PulseLink CTA. Right column: new `MarketplaceMock` — a faux-browser
  frame containing four realistic template cards (notion-search /
  github-issues / stripe-readonly / linear-tasks) with author chips,
  ✓ verified badges, tool counts, and a fork glyph. Visitor SEES the
  marketplace instead of reading copy about it.

- **Pricing** ("Pay for tool calls. Not for boilerplate."): 4-card
  row but Pro is featured — indigo border, indigo glow shadow
  `0 0 0 4px rgba(99,102,241,0.12)`, "RECOMMENDED" pill floating at
  -top-3, and accent-coloured feature bullets. Other tiers stay
  calm so the eye lands on Pro first. Price typography enlarged from
  26 px to 40 px so prices read as the headline of each card.

Spacing rhythm: every section is now py-20/28 sm:py-24/28 (was
py-12-14 sm:py-16-20) — gives the below-the-fold the breathing room
it needed; the page no longer feels like a stack of crammed cards.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 16:36:06 +02:00

633 lines
28 KiB
TypeScript

import { HeroStepRotator } from '@/components/hero-step-rotator';
import { HeroVideo } from '@/components/hero-video';
import { JsonLd } from '@/components/json-ld';
import { ParticleHero } from '@/components/particle-hero';
import { PulseLink } from '@/components/pulse';
import { ScrollCue } from '@/components/scroll-cue';
import { StaticCodeBlock } from '@/components/static-code-block';
import { FAQ, faqJsonLd } from '@/lib/seo';
import { ChevronDown } from 'lucide-react';
import Link from 'next/link';
const PROMPT_EXAMPLE = `Create an MCP server that searches our Notion workspace.
Tools: search_pages, get_page_content.
Auth: NOTION_API_KEY.`;
const OUTPUT_EXAMPLE = `> Generating spec... OK (2 tools)
> Static checks OK
> Building image bmm-mcp-notion OK 17.2s
> Deploying container OK
> Live at https://notion-x9.mcp.buildmymcpserver.com
> First request: 401 → token → 200 OK`;
const INSTALL_SNIPPET = `{
"mcpServers": {
"notion": {
"url": "https://notion-x9.mcp.buildmymcpserver.com/mcp",
"auth": "oauth2"
}
}
}`;
interface ExampleEntry {
title: string;
desc: string;
/** Single-character or short symbol shown in the brand-colored mark. */
mark: string;
/** Brand background colour for the mark. */
bg: string;
/** Foreground colour of the mark glyph. */
fg: string;
}
const EXAMPLES: ExampleEntry[] = [
{ title: 'Postgres', desc: 'Read-only access to your tables with schema introspection.', mark: 'P', bg: '#336791', fg: '#ffffff' },
{ title: 'Salesforce', desc: 'Query opportunities, accounts and leads from Claude.', mark: 'S', bg: '#00a1e0', fg: '#ffffff' },
{ title: 'Notion', desc: 'Search pages, read content, append blocks.', mark: 'N', bg: '#ffffff', fg: '#0a0a0b' },
{ title: 'GitHub', desc: 'List issues, search code, post comments — scoped to one repo.', mark: 'G', bg: '#181717', fg: '#ffffff' },
{ title: 'Stripe', desc: 'Look up charges, customers, refunds (read-only by default).', mark: 'S', bg: '#635bff', fg: '#ffffff' },
{ title: 'Custom REST', desc: 'Wrap any HTTP API behind one prompt-defined tool surface.', mark: '{}', bg: '#6366f1', fg: '#ffffff' },
];
interface ClientEntry {
name: string;
/** Single-character mark for inline visual identity. */
mark: string;
}
const CLIENTS: ClientEntry[] = [
{ name: 'Claude Desktop', mark: 'C' },
{ name: 'Cursor', mark: '⌘' },
{ name: 'ChatGPT', mark: '✦' },
{ name: 'VS Code Copilot', mark: '<>' },
{ name: 'Continue.dev', mark: '→' },
];
interface MockTemplate {
name: string;
author: string;
tools: number;
forks: number;
verified: boolean;
}
const MOCK_TEMPLATES: MockTemplate[] = [
{ name: 'notion-search', author: 'core', tools: 2, forks: 247, verified: true },
{ name: 'github-issues', author: 'core', tools: 3, forks: 89, verified: true },
{ name: 'stripe-readonly', author: 'core', tools: 4, forks: 156, verified: true },
{ name: 'linear-tasks', author: 'community', tools: 5, forks: 34, verified: false },
];
const MARKETPLACE_POINTS: { t: string; d: string }[] = [
{
t: 'Fork and own',
d: 'Start from a server someone already shipped. Fork it, paste your own credentials, deploy — no prompt required.',
},
{
t: 'Secrets never travel',
d: "A template carries the spec and generated code, never the author's API keys. You add your own on fork.",
},
{
t: 'Ranked by real usage',
d: 'Templates rise on fork count and active deploys — not vanity stars. The useful ones surface themselves.',
},
];
const TIERS = [
{
name: 'Hobby',
price: '€0',
tag: 'Forever free',
features: ['1 server', '100k calls/mo', 'BMM subdomain', 'Community support'],
},
{
name: 'Pro',
price: '€49',
tag: '/ month',
features: [
'5 servers',
'1M calls/mo',
'Custom domain',
'Priority build queue',
'Email support',
],
},
{
name: 'Team',
price: '€149',
tag: '/ month',
features: ['25 servers', '10M calls/mo', 'RBAC + audit log', 'SLA 99.9%', 'Slack support'],
},
{
name: 'Enterprise',
price: '€499+',
tag: '/ month',
features: ['Unlimited', 'BYOC', 'SSO / SAML', 'Dedicated cluster', 'Customer success'],
},
];
export default function Landing() {
return (
<>
{/* Hero — left: copy + CTAs, right: cycling step-rotator tile.
The old layout stacked three static code blocks vertically; the
new layout shows one centered tile that cycles through the same
three artifacts (prompt → build.log → claude config) with a
mouse-reactive 3D tilt and a step indicator. Shorter overall
so the video section below is teased above the fold. */}
<section
className="relative flex items-center overflow-hidden border-b border-[--color-border]"
style={{ minHeight: 'calc(100svh - 3rem)' }}
>
{/* WebGL particle field — capability-detected client component.
Sits behind the hero content at z-0 with pointer-events:none
so the CTAs above remain fully interactive. The canvas listens
for pointermove on window itself, so the ring still tracks
the cursor through the content above. With the hero now
filling the full first-viewport (minus the 48px sticky nav),
the field has cinematic-scale room and the indigo radial
glow + dot mask read as the dominant background motif. */}
<ParticleHero />
<div className="relative z-10 mx-auto grid w-full max-w-6xl gap-10 px-6 py-14 sm:py-20 md:grid-cols-[1.05fr_1fr] md:items-center md:gap-12">
<div className="min-w-0">
<span className="mono inline-block rounded-full border border-[--color-border] bg-[--color-bg-elevated] px-2.5 py-0.5 text-[11px] tracking-wide text-[--color-fg-muted]">
v0.1 updated 2026-05-20
</span>
<h1 className="mt-6 text-balance text-[30px] font-semibold leading-[1.06] tracking-tight sm:text-[40px] md:text-[52px]">
Describe your tool.
<br />
We host the server.
<br />
<span className="text-[--color-fg-muted]">AI uses it.</span>
</h1>
<p className="mt-5 max-w-md text-[15px] leading-relaxed text-[--color-fg-muted]">
From prompt to production MCP server in 60 seconds. OAuth 2.1, Streamable HTTP, ready
for Claude, Cursor and ChatGPT.
</p>
<div className="mt-7 flex flex-wrap items-center gap-3">
<PulseLink
href="/login"
className="inline-flex h-9 items-center justify-center rounded-md bg-[--color-accent] px-4 text-[13px] font-medium text-white transition-colors duration-200 hover:bg-[#5557e8]"
>
Start building free
</PulseLink>
<PulseLink
href="/docs"
className="inline-flex h-9 items-center justify-center rounded-md border border-[--color-border] bg-[--color-bg-elevated] px-4 text-[13px] text-[--color-fg-muted] transition-colors hover:text-[--color-fg]"
>
Read the docs
</PulseLink>
</div>
<div className="mt-8 flex flex-wrap gap-x-6 gap-y-2 text-[12px] text-[--color-fg-subtle]">
<span className="inline-flex items-center gap-1.5">
<span className="size-1.5 rounded-full bg-emerald-400" /> OAuth 2.1 + PKCE
</span>
<span className="inline-flex items-center gap-1.5">
<span className="size-1.5 rounded-full bg-emerald-400" /> Streamable HTTP
</span>
<span className="inline-flex items-center gap-1.5">
<span className="size-1.5 rounded-full bg-emerald-400" /> AES-256 secrets
</span>
<span className="inline-flex items-center gap-1.5">
<span className="size-1.5 rounded-full bg-emerald-400" /> Per-server isolation
</span>
</div>
</div>
<div className="relative min-w-0">
<HeroStepRotator />
</div>
</div>
</section>
{/* Scroll cue — fixed at the bottom of the loadscreen rather than
inside the hero, so it sits at the natural lower edge of the
first viewport regardless of how tall the hero ends up. Fades
out once the user has scrolled past the loadscreen. */}
<ScrollCue targetId="flow" />
{/* Flow video — full-width edge-to-edge under the hero. The clip
shows the real flow (prompt → server schematic → live connection
to Claude Desktop) in three smooth phases. autoplay-muted-loop +
playsInline satisfies every mobile browser autoplay policy; the
`poster` carries first paint while the video decodes. */}
<section
id="flow"
className="relative w-full overflow-hidden border-b border-[--color-border] bg-black"
>
<div className="relative aspect-video w-full">
{/* HeroVideo: native <video> with autoplay+muted+loop, plus a
frosted mute toggle pinned bottom-right so visitors can
switch the narration on. See components/hero-video.tsx for
the autoplay/unmute mechanics. */}
<HeroVideo />
{/* Subtle vignette to integrate edges into the rest of the page */}
<div
aria-hidden
className="pointer-events-none absolute inset-0"
style={{
background:
'radial-gradient(ellipse at center, transparent 60%, rgba(10,10,11,0.55) 100%)',
}}
/>
</div>
</section>
{/* How it works */}
<section id="how" className="border-b border-[--color-border] py-14 sm:py-20">
<div className="mx-auto max-w-6xl px-6">
<div className="mb-10 max-w-2xl">
<h2 className="text-[28px] font-semibold tracking-tight">How it works</h2>
<p className="mt-2 text-[14px] text-[--color-fg-muted]">
Three steps. No JSON to write, no Docker to manage.
</p>
</div>
{/* The same video used to live here; it now has its own
full-width section directly under the hero so it's teased
above the fold and gets edge-to-edge real estate. This
section keeps the three explanatory cards as supporting
copy under the video. */}
<div className="grid gap-6 md:grid-cols-3">
{[
{
n: '01',
t: 'Describe your tool',
d: 'A sentence is enough. List your secrets and which APIs to call.',
},
{
n: '02',
t: 'We generate, check, deploy',
d: 'Claude writes the spec. We render TypeScript, run static checks, build a container, deploy to your subdomain.',
},
{
n: '03',
t: 'Install in your client',
d: 'Copy the snippet into Claude Desktop, Cursor or ChatGPT. OAuth flow on first use.',
},
].map((s) => (
<div key={s.n} className="panel p-5">
<div className="mono text-[11px] tracking-widest text-[--color-fg-subtle]">
{s.n}
</div>
<h3 className="mt-4 text-[15px] font-semibold tracking-tight">{s.t}</h3>
<p className="mt-2 text-[13px] leading-relaxed text-[--color-fg-muted]">{s.d}</p>
</div>
))}
</div>
</div>
</section>
{/* ── Clients · trust-signal row ─────────────────────────────────
Archetype: typographic logo row. No panels, no bullets, just
well-spaced word-marks with a small symbolic mark. The whole
section breathes — generous py — so it reads as a moment of
trust, not a feature card. */}
<section className="border-b border-[--color-border] bg-[--color-bg] py-20 sm:py-24">
<div className="mx-auto max-w-6xl px-6">
<p className="text-center text-[11px] uppercase tracking-[0.24em] text-[--color-fg-subtle]">
Connects everywhere your AI lives
</p>
<div className="mt-12 flex flex-wrap items-center justify-center gap-x-14 gap-y-7 sm:gap-x-20">
{CLIENTS.map((c) => (
<div
key={c.name}
className="group flex items-center gap-3 transition-colors"
>
<span
aria-hidden
className="mono flex size-7 items-center justify-center rounded-md border border-[--color-border] text-[12px] text-[--color-fg-muted] transition-colors group-hover:border-[--color-accent] group-hover:text-[--color-accent]"
>
{c.mark}
</span>
<span className="text-[17px] font-medium tracking-tight text-[--color-fg-muted] transition-colors group-hover:text-[--color-fg]">
{c.name}
</span>
</div>
))}
</div>
</div>
</section>
{/* ── Examples · integration grid with brand-coloured marks ──────
Archetype: 2-col header (title left, supporting copy right) +
asymmetric 3-col card grid where each card carries a coloured
square brand mark for the service. The marks give each card
its own visual identity, breaking the "every card looks the
same" pattern of the previous version. */}
<section className="border-b border-[--color-border] py-20 sm:py-28">
<div className="mx-auto max-w-6xl px-6">
<div className="mb-12 grid gap-6 md:grid-cols-[1fr_auto] md:items-end md:gap-12">
<div>
<p className="text-[11px] uppercase tracking-[0.22em] text-[--color-fg-subtle]">
Use cases
</p>
<h2 className="mt-3 text-[32px] font-semibold leading-[1.1] tracking-tight sm:text-[40px]">
Wrap any HTTP API.
<br />
<span className="text-[--color-fg-muted]">In minutes.</span>
</h2>
</div>
<p className="max-w-xs text-[14px] leading-relaxed text-[--color-fg-muted]">
Real integrations our customers ship today built from one prompt each.
</p>
</div>
<div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
{EXAMPLES.map((e) => (
<div
key={e.title}
className="group flex items-start gap-4 rounded-xl border border-[--color-border] bg-[--color-bg-elevated] p-5 transition-colors hover:border-[--color-border-strong]"
>
<div
aria-hidden
className="flex size-12 shrink-0 items-center justify-center rounded-lg font-semibold tracking-tight"
style={{
backgroundColor: e.bg,
color: e.fg,
fontSize: e.mark.length > 1 ? 16 : 20,
}}
>
{e.mark}
</div>
<div className="min-w-0">
<h3 className="text-[15px] font-semibold tracking-tight">{e.title}</h3>
<p className="mt-1.5 text-[13px] leading-relaxed text-[--color-fg-muted]">
{e.desc}
</p>
</div>
</div>
))}
</div>
</div>
</section>
{/* ── Marketplace · two-column with product preview ──────────────
Archetype: split layout. Left column carries the headline,
three bullet-form selling points, and the CTA. Right column
carries a mock browser frame containing real-looking template
cards — so the visitor SEES the marketplace, not just reads
a description of it. */}
<section className="border-b border-[--color-border] py-20 sm:py-28">
<div className="mx-auto grid max-w-6xl gap-14 px-6 md:grid-cols-[5fr_6fr] md:items-center md:gap-16">
{/* Left — text + points + CTA */}
<div>
<p className="text-[11px] uppercase tracking-[0.22em] text-[--color-fg-subtle]">
Marketplace
</p>
<h2 className="mt-3 text-[32px] font-semibold leading-[1.1] tracking-tight sm:text-[40px]">
Skip the prompt.
<br />
<span className="text-[--color-fg-muted]">Fork what works.</span>
</h2>
<p className="mt-5 max-w-md text-[14px] leading-relaxed text-[--color-fg-muted]">
The marketplace is a library of working MCP servers the community already built.
Fork one, paste your credentials, deploy. Or publish yours and let others build on it.
</p>
<ul className="mt-8 space-y-5">
{MARKETPLACE_POINTS.map((p) => (
<li key={p.t} className="flex items-start gap-3">
<span
aria-hidden
className="mt-[7px] size-1.5 shrink-0 rounded-full bg-[--color-accent]"
/>
<div>
<h3 className="text-[14px] font-semibold tracking-tight">{p.t}</h3>
<p className="mt-1 text-[13px] leading-relaxed text-[--color-fg-muted]">
{p.d}
</p>
</div>
</li>
))}
</ul>
<PulseLink
href="/templates"
className="mt-8 inline-flex h-9 items-center gap-2 rounded-md bg-[--color-accent] px-4 text-[13px] font-medium text-white transition-colors duration-200 hover:bg-[#5557e8]"
>
Browse the marketplace
</PulseLink>
</div>
{/* Right — mock marketplace browser frame */}
<MarketplaceMock />
</div>
</section>
{/* ── Pricing · 4 cards with Pro highlighted as recommended ─────
Archetype: centred header + 4-card row where the Pro tier is
visually distinct (accent border, indigo glow shadow, floating
"recommended" pill, slightly elevated). Other tiers stay calm
so the eye lands on Pro first. Big price typography (text-
[40px]) replaces the previous flat 26px. */}
<section id="pricing" className="border-b border-[--color-border] py-20 sm:py-28">
<div className="mx-auto max-w-6xl px-6">
<div className="mb-14 text-center">
<p className="text-[11px] uppercase tracking-[0.22em] text-[--color-fg-subtle]">
Pricing
</p>
<h2 className="mt-3 text-[32px] font-semibold leading-[1.1] tracking-tight sm:text-[40px]">
Pay for tool calls.
<br />
<span className="text-[--color-fg-muted]">Not for boilerplate.</span>
</h2>
</div>
<div className="grid gap-5 md:grid-cols-2 lg:grid-cols-4">
{TIERS.map((t) => {
const featured = t.name === 'Pro';
return (
<div
key={t.name}
className={`relative flex flex-col gap-6 rounded-xl border p-6 transition-colors ${
featured
? 'border-[--color-accent] bg-[--color-bg-elevated]'
: 'border-[--color-border] bg-[--color-bg-elevated] hover:border-[--color-border-strong]'
}`}
style={
featured
? {
boxShadow:
'0 0 0 4px rgba(99, 102, 241, 0.12), 0 24px 50px rgba(0, 0, 0, 0.35)',
}
: undefined
}
>
{featured && (
<span
className="absolute -top-3 left-1/2 -translate-x-1/2 whitespace-nowrap rounded-full border border-[--color-accent] px-3 py-0.5 text-[10px] font-semibold uppercase tracking-[0.18em] text-[--color-accent]"
style={{ backgroundColor: 'var(--color-bg)' }}
>
Recommended
</span>
)}
<div>
<div className="text-[11px] font-medium uppercase tracking-[0.18em] text-[--color-fg-muted]">
{t.name}
</div>
<div className="mt-3 flex items-baseline gap-2">
<span className="text-[40px] font-semibold leading-none tracking-tight text-[--color-fg]">
{t.price}
</span>
<span className="text-[12px] text-[--color-fg-subtle]">{t.tag}</span>
</div>
</div>
<ul className="flex flex-1 flex-col gap-2.5 border-t border-[--color-border] pt-5 text-[13px] text-[--color-fg-muted]">
{t.features.map((f) => (
<li key={f} className="flex items-start gap-2.5">
<span
aria-hidden
className={`mt-[7px] size-1 shrink-0 rounded-full ${
featured ? 'bg-[--color-accent]' : 'bg-[--color-fg-subtle]'
}`}
/>
<span>{f}</span>
</li>
))}
</ul>
</div>
);
})}
</div>
</div>
</section>
{/* FAQ — collapsible accordion using native <details>. Crawlers
and screen readers still see the full Q+A in the HTML; users
see one question at a time and expand on demand. No JS, no
state, semantically correct. `list-none` + the WebKit-marker
pseudo-class suppress the default disclosure triangle so we
can render our own chevron that rotates via `group-open`. */}
<section className="py-14 sm:py-20">
<JsonLd data={faqJsonLd()} />
<div className="mx-auto max-w-3xl px-6">
<h2 className="text-[28px] font-semibold tracking-tight">FAQ</h2>
<div className="mt-8 border-t border-[--color-border]">
{FAQ.map((f) => (
<details
key={f.q}
className="group border-b border-[--color-border] [&_summary::-webkit-details-marker]:hidden"
>
<summary className="flex cursor-pointer list-none items-center justify-between gap-4 py-4 text-[14.5px] font-semibold tracking-tight text-[--color-fg] transition-colors hover:text-[--color-accent]">
<span>{f.q}</span>
<ChevronDown
size={16}
className="shrink-0 text-[--color-fg-subtle] transition-transform duration-200 group-open:rotate-180 group-open:text-[--color-accent]"
/>
</summary>
<p className="pb-5 pr-8 text-[13.5px] leading-relaxed text-[--color-fg-muted]">
{f.a}
</p>
</details>
))}
</div>
</div>
</section>
</>
);
}
/**
* Mock marketplace preview.
*
* Static, server-rendered. Renders a faux-browser frame containing four
* realistic template cards so the visitor sees what the marketplace
* actually looks like rather than reading marketing copy about it.
*
* The card data lives in `MOCK_TEMPLATES` at the top of this file —
* those are real template-flavoured names, modest fork counts, and the
* `core` / `community` author tag. Numbers are deliberately small and
* truthful-looking for a young marketplace; nothing here pretends to be
* GitHub-trending traffic.
*/
function MarketplaceMock() {
return (
<div
className="overflow-hidden rounded-xl border border-[--color-border-strong] bg-[--color-bg-elevated]"
style={{ boxShadow: '0 24px 60px rgba(0, 0, 0, 0.45)' }}
>
{/* Browser chrome */}
<div className="flex items-center gap-3 border-b border-[--color-border] bg-[--color-bg-subtle] px-4 py-3">
<div className="flex gap-1.5">
<span className="size-2.5 rounded-full bg-zinc-700" />
<span className="size-2.5 rounded-full bg-zinc-700" />
<span className="size-2.5 rounded-full bg-zinc-700" />
</div>
<div className="mono flex-1 truncate rounded-md border border-[--color-border] bg-[--color-bg] px-3 py-1 text-[11px] text-[--color-fg-subtle]">
buildmymcpserver.com/templates
</div>
</div>
{/* Toolbar inside the page chrome */}
<div className="flex items-center justify-between gap-4 border-b border-[--color-border] px-5 py-3">
<div className="flex items-center gap-3">
<span className="text-[13px] font-semibold tracking-tight text-[--color-fg]">
Templates
</span>
<span className="text-[11px] text-[--color-fg-subtle]">·</span>
<span className="text-[11px] text-[--color-fg-subtle]">{MOCK_TEMPLATES.length} live</span>
</div>
<div className="hidden items-center gap-1.5 rounded-md border border-[--color-border] px-2 py-1 sm:flex">
<span className="text-[11px] text-[--color-fg-subtle]">trending</span>
<ChevronDown size={11} className="text-[--color-fg-subtle]" />
</div>
</div>
{/* Template cards grid */}
<div className="grid gap-3 p-4 sm:grid-cols-2">
{MOCK_TEMPLATES.map((t) => (
<div
key={t.name}
className="rounded-md border border-[--color-border] bg-[--color-bg-subtle] p-4 transition-colors hover:border-[--color-accent]/40"
>
<div className="flex items-start justify-between gap-3">
<div className="min-w-0">
<div className="mono truncate text-[13px] font-semibold tracking-tight text-[--color-fg]">
{t.name}
</div>
<div className="mt-1 flex items-center gap-1.5">
<span className="mono text-[10px] uppercase tracking-wider text-[--color-fg-subtle]">
{t.author}
</span>
{t.verified && (
<span className="inline-flex items-center gap-0.5 rounded-full border border-[--color-accent]/50 bg-[--color-accent]/10 px-1.5 py-px text-[9.5px] font-medium uppercase tracking-wider text-[--color-accent]">
verified
</span>
)}
</div>
</div>
</div>
<div className="mt-4 flex items-center justify-between text-[11px] text-[--color-fg-subtle]">
<span className="mono">{t.tools} tools</span>
<span className="mono inline-flex items-center gap-1">
<ForkGlyph />
{t.forks}
</span>
</div>
</div>
))}
</div>
</div>
);
}
function ForkGlyph() {
return (
<svg width="11" height="11" viewBox="0 0 14 14" fill="none" aria-hidden>
<circle cx="3.5" cy="3" r="1.4" stroke="currentColor" strokeWidth={1.2} />
<circle cx="10.5" cy="3" r="1.4" stroke="currentColor" strokeWidth={1.2} />
<circle cx="7" cy="11" r="1.4" stroke="currentColor" strokeWidth={1.2} />
<path
d="M 3.5 4.5 L 3.5 6.5 Q 3.5 7.5 4.5 7.5 L 9.5 7.5 Q 10.5 7.5 10.5 6.5 L 10.5 4.5"
stroke="currentColor"
strokeWidth={1.2}
fill="none"
/>
<path d="M 7 7.5 L 7 9.5" stroke="currentColor" strokeWidth={1.2} />
</svg>
);
}