feat(landing): honest high-end redesign — kill fake social proof, brand gradient identity, final CTA, mobile fixes
- removed fabricated fork counts/'verified' badges, 'our customers ship today' copy, pseudo client logo marks and stale v0.1 badge (zero-user product must not fake traction) - new proof-by-specificity band: verifiable links to /docs/oauth, /status, /security instead of testimonial cosplay - identity: indigo-to-cyan brand gradient, indigo-tinted elevated surfaces, mono section kickers, terminal-chrome hero rotator, gradient h-11 CTA - how-it-works as connected pipeline; new final CTA band (page no longer ends on FAQ); footer upgraded to 4-column product/resources/legal - lib/pricing.ts single tier source for pricing page + landing teaser; annual-billing FAQ claim softened to truth (no annual checkout exists) - hero video preload=metadata + IntersectionObserver play (2.6MB off the critical path); 44px touch targets; mobile menu: Guides link, CTA, scroll-lock, escape/outside-tap close Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SXUwmPVRTD8AKQtio6gCN5
This commit is contained in:
@@ -39,42 +39,83 @@ export default function MarketingLayout({ children }: { children: React.ReactNod
|
||||
</div>
|
||||
</header>
|
||||
<main className="flex-1">{children}</main>
|
||||
<footer className="border-t border-[--color-border] py-8">
|
||||
<div className="mx-auto flex max-w-6xl flex-col gap-4 px-6 text-[12px] text-[--color-fg-subtle] md:flex-row md:items-center md:justify-between">
|
||||
<Link
|
||||
href="/status"
|
||||
className="flex items-center gap-2 transition-colors hover:text-[--color-fg]"
|
||||
>
|
||||
<span className="size-1.5 animate-pulse rounded-full bg-emerald-400" />
|
||||
<span>System status</span>
|
||||
</Link>
|
||||
<div className="flex flex-wrap gap-x-5 gap-y-1">
|
||||
<Link href="/docs" className="transition-colors hover:text-[--color-fg]">
|
||||
Docs
|
||||
</Link>
|
||||
<Link href="/contact" className="transition-colors hover:text-[--color-fg]">
|
||||
Contact
|
||||
</Link>
|
||||
<Link href="/security" className="transition-colors hover:text-[--color-fg]">
|
||||
Security
|
||||
</Link>
|
||||
<Link href="/privacy" className="transition-colors hover:text-[--color-fg]">
|
||||
Privacy
|
||||
</Link>
|
||||
<Link href="/agb" className="transition-colors hover:text-[--color-fg]">
|
||||
AGB
|
||||
</Link>
|
||||
<Link href="/impressum" className="transition-colors hover:text-[--color-fg]">
|
||||
Impressum
|
||||
</Link>
|
||||
<Link href="/terms" className="transition-colors hover:text-[--color-fg]">
|
||||
Terms
|
||||
</Link>
|
||||
<footer className="border-t border-[--color-border] py-12">
|
||||
<div className="mx-auto max-w-6xl px-6">
|
||||
<div className="grid gap-10 sm:grid-cols-2 md:grid-cols-4">
|
||||
{/* Brand column — positioning line + live status. */}
|
||||
<div className="sm:col-span-2 md:col-span-1">
|
||||
<Logo />
|
||||
<p className="mt-3 max-w-xs text-[12.5px] leading-relaxed text-[--color-fg-subtle]">
|
||||
From a prompt to a hosted, OAuth-protected MCP server — for Claude, Cursor and
|
||||
ChatGPT.
|
||||
</p>
|
||||
<Link
|
||||
href="/status"
|
||||
className="mt-4 flex items-center gap-2 text-[12px] text-[--color-fg-subtle] transition-colors hover:text-[--color-fg]"
|
||||
>
|
||||
<span className="size-1.5 animate-pulse rounded-full bg-emerald-400" />
|
||||
<span>System status</span>
|
||||
</Link>
|
||||
</div>
|
||||
<FooterColumn
|
||||
title="Product"
|
||||
links={[
|
||||
{ href: '/templates', label: 'Templates' },
|
||||
{ href: '/pricing', label: 'Pricing' },
|
||||
{ href: '/changelog', label: 'Changelog' },
|
||||
{ href: '/security', label: 'Security' },
|
||||
]}
|
||||
/>
|
||||
<FooterColumn
|
||||
title="Resources"
|
||||
links={[
|
||||
{ href: '/docs', label: 'Docs' },
|
||||
{ href: '/guides', label: 'Guides' },
|
||||
{ href: '/docs/faq', label: 'FAQ' },
|
||||
{ href: '/contact', label: 'Contact' },
|
||||
]}
|
||||
/>
|
||||
<FooterColumn
|
||||
title="Legal"
|
||||
links={[
|
||||
{ href: '/privacy', label: 'Privacy' },
|
||||
{ href: '/terms', label: 'Terms' },
|
||||
{ href: '/agb', label: 'AGB' },
|
||||
{ href: '/impressum', label: 'Impressum' },
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
<div className="mt-10 border-t border-[--color-border] pt-6 text-[12px] text-[--color-fg-subtle]">
|
||||
© {new Date().getFullYear()} BuildMyMCPServer
|
||||
</div>
|
||||
<div>© {new Date().getFullYear()} BuildMyMCPServer</div>
|
||||
</div>
|
||||
</footer>
|
||||
<CookieBanner />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function FooterColumn({
|
||||
title,
|
||||
links,
|
||||
}: {
|
||||
title: string;
|
||||
links: { href: string; label: string }[];
|
||||
}) {
|
||||
return (
|
||||
<div>
|
||||
<h3 className="text-[11px] font-semibold uppercase tracking-[0.16em] text-[--color-fg-muted]">
|
||||
{title}
|
||||
</h3>
|
||||
<ul className="mt-3 space-y-2 text-[12.5px] text-[--color-fg-subtle]">
|
||||
{links.map((l) => (
|
||||
<li key={l.href}>
|
||||
<Link href={l.href} className="transition-colors hover:text-[--color-fg]">
|
||||
{l.label}
|
||||
</Link>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -12,31 +12,11 @@ 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 { TIERS } from '@/lib/pricing';
|
||||
import { FAQ, faqJsonLd } from '@/lib/seo';
|
||||
import { ChevronDown } from 'lucide-react';
|
||||
import type { ComponentType } from 'react';
|
||||
import { Activity, ChevronDown, Container, ShieldCheck } 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"
|
||||
}
|
||||
}
|
||||
}`;
|
||||
import type { ComponentType } from 'react';
|
||||
|
||||
interface ExampleEntry {
|
||||
title: string;
|
||||
@@ -50,41 +30,58 @@ interface ExampleEntry {
|
||||
}
|
||||
|
||||
const EXAMPLES: ExampleEntry[] = [
|
||||
{ title: 'PostgreSQL', desc: 'Read-only access to your tables with schema introspection.', Icon: PostgresIcon, bg: '#336791', fg: '#ffffff' },
|
||||
{ title: 'Salesforce', desc: 'Query opportunities, accounts and leads from Claude.', Icon: SalesforceCloudIcon, bg: '#00a1e0', fg: '#ffffff' },
|
||||
{ title: 'Notion', desc: 'Search pages, read content, append blocks.', Icon: NotionIcon, bg: '#ffffff', fg: '#0a0a0b' },
|
||||
{ title: 'GitHub', desc: 'List issues, search code, post comments. Scoped to one repo.', Icon: GitHubIcon, bg: '#181717', fg: '#ffffff' },
|
||||
{ title: 'Stripe', desc: 'Look up charges, customers, refunds (read-only by default).', Icon: StripeIcon, bg: '#635bff', fg: '#ffffff' },
|
||||
{ title: 'Custom REST',desc: 'Wrap any HTTP API behind one prompt-defined tool surface.', Icon: RestIcon, bg: '#6366f1', fg: '#ffffff' },
|
||||
{
|
||||
title: 'PostgreSQL',
|
||||
desc: 'Read-only access to your tables with schema introspection.',
|
||||
Icon: PostgresIcon,
|
||||
bg: '#336791',
|
||||
fg: '#ffffff',
|
||||
},
|
||||
{
|
||||
title: 'Salesforce',
|
||||
desc: 'Query opportunities, accounts and leads from Claude.',
|
||||
Icon: SalesforceCloudIcon,
|
||||
bg: '#00a1e0',
|
||||
fg: '#ffffff',
|
||||
},
|
||||
{
|
||||
title: 'Notion',
|
||||
desc: 'Search pages, read content, append blocks.',
|
||||
Icon: NotionIcon,
|
||||
bg: '#ffffff',
|
||||
fg: '#0a0a0b',
|
||||
},
|
||||
{
|
||||
title: 'GitHub',
|
||||
desc: 'List issues, search code, post comments. Scoped to one repo.',
|
||||
Icon: GitHubIcon,
|
||||
bg: '#181717',
|
||||
fg: '#ffffff',
|
||||
},
|
||||
{
|
||||
title: 'Stripe',
|
||||
desc: 'Look up charges, customers, refunds (read-only by default).',
|
||||
Icon: StripeIcon,
|
||||
bg: '#635bff',
|
||||
fg: '#ffffff',
|
||||
},
|
||||
{
|
||||
title: 'Custom REST',
|
||||
desc: 'Wrap any HTTP API behind one prompt-defined tool surface.',
|
||||
Icon: RestIcon,
|
||||
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 },
|
||||
// Honest marketplace preview data: template names + tool counts only. These
|
||||
// mirror the first-party starter templates; no invented fork counts, no
|
||||
// "verified" theatre — the frame is labelled as a preview of the card format.
|
||||
const PREVIEW_TEMPLATES: { name: string; author: string; tools: number }[] = [
|
||||
{ name: 'notion-search', author: 'core', tools: 2 },
|
||||
{ name: 'github-issues', author: 'core', tools: 3 },
|
||||
{ name: 'stripe-readonly', author: 'core', tools: 4 },
|
||||
{ name: 'postgres-readonly', author: 'core', tools: 3 },
|
||||
];
|
||||
|
||||
const MARKETPLACE_POINTS: { t: string; d: string }[] = [
|
||||
@@ -97,94 +94,104 @@ const MARKETPLACE_POINTS: { t: string; d: string }[] = [
|
||||
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.',
|
||||
t: 'Open from day one',
|
||||
d: 'Publish a server you built and anyone can fork it. The marketplace is young — early templates set the standard.',
|
||||
},
|
||||
];
|
||||
|
||||
const TIERS = [
|
||||
// Proof-by-specificity band: three claims a visitor can verify with one
|
||||
// click instead of taking our word for it. Substitute for social proof
|
||||
// until there is social proof.
|
||||
const PROOF_POINTS: {
|
||||
t: string;
|
||||
d: string;
|
||||
href: string;
|
||||
linkLabel: string;
|
||||
Icon: ComponentType<{ size?: number; className?: string }>;
|
||||
}[] = [
|
||||
{
|
||||
name: 'Hobby',
|
||||
price: '€0',
|
||||
tag: 'Forever free',
|
||||
features: ['1 server', '100k calls/mo', 'BMM subdomain', 'Community support'],
|
||||
t: 'OAuth 2.1 authorization server',
|
||||
d: 'PKCE, Dynamic Client Registration and Resource Indicators (RFC 8707) in front of every server.',
|
||||
href: '/docs/oauth',
|
||||
linkLabel: 'Read the auth docs',
|
||||
Icon: ShieldCheck,
|
||||
},
|
||||
{
|
||||
name: 'Pro',
|
||||
price: '€49',
|
||||
tag: '/ month',
|
||||
features: [
|
||||
'5 servers',
|
||||
'1M calls/mo',
|
||||
'Priority build queue',
|
||||
'Custom domain · soon',
|
||||
'Email support',
|
||||
],
|
||||
t: 'Live system status',
|
||||
d: 'Uptime and incident history, public. If a build queue slows down, you see it before we tell you.',
|
||||
href: '/status',
|
||||
linkLabel: 'Check status now',
|
||||
Icon: Activity,
|
||||
},
|
||||
{
|
||||
name: 'Team',
|
||||
price: '€199',
|
||||
tag: '/ month',
|
||||
features: ['25 servers', '10M calls/mo', 'Audit log', 'RBAC · soon', 'Slack support'],
|
||||
},
|
||||
{
|
||||
name: 'Enterprise',
|
||||
price: 'Custom',
|
||||
tag: 'talk to us',
|
||||
features: ['Unlimited', 'Custom infra · on request', 'SSO/SAML · on request', 'Dedicated hosting', 'Customer success'],
|
||||
t: 'Per-server container isolation',
|
||||
d: 'Every generated server runs in its own Docker container. Secrets AES-256-GCM encrypted at rest.',
|
||||
href: '/security',
|
||||
linkLabel: 'Security architecture',
|
||||
Icon: Container,
|
||||
},
|
||||
];
|
||||
|
||||
const PIPELINE_STEPS: { n: string; t: string; d: string }[] = [
|
||||
{
|
||||
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.',
|
||||
},
|
||||
];
|
||||
|
||||
/** Mono shell-comment section kicker: `## how_it_works` */
|
||||
function Kicker({ children }: { children: string }) {
|
||||
return <p className="kicker">## {children}</p>;
|
||||
}
|
||||
|
||||
export default function Landing() {
|
||||
const teaserTiers = TIERS.filter((t) => t.name === 'Hobby' || t.name === 'Pro');
|
||||
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. */}
|
||||
{/* Hero — left: copy + CTAs, right: cycling terminal tile. The WebGL
|
||||
particle field sits behind at z-0 with pointer-events:none so the
|
||||
CTAs stay interactive. */}
|
||||
<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]">
|
||||
<h1 className="text-balance text-[36px] font-semibold leading-[1.04] tracking-[-0.03em] sm:text-[44px] md:text-[60px]">
|
||||
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]">
|
||||
<p className="mt-5 max-w-md text-[15px] leading-relaxed text-[--color-fg-muted] sm:text-[16px]">
|
||||
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">
|
||||
<div className="mt-8 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]"
|
||||
className="btn-brand inline-flex h-11 items-center justify-center rounded-md px-5 text-[14px] font-medium"
|
||||
>
|
||||
Start building free
|
||||
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]"
|
||||
href="#flow"
|
||||
className="inline-flex h-11 items-center justify-center rounded-md border border-[--color-border] bg-[--color-bg-elevated] px-5 text-[14px] text-[--color-fg-muted] transition-colors hover:text-[--color-fg]"
|
||||
>
|
||||
Read the docs
|
||||
See a live build
|
||||
</PulseLink>
|
||||
</div>
|
||||
<div className="mt-8 flex flex-wrap gap-x-6 gap-y-2 text-[12px] text-[--color-fg-subtle]">
|
||||
@@ -208,28 +215,17 @@ export default function Landing() {
|
||||
</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. */}
|
||||
{/* Flow video — full-width edge-to-edge under the hero. Plays when
|
||||
scrolled into view (see hero-video.tsx); preload=metadata keeps the
|
||||
2.6 MB mp4 off the critical path on mobile. */}
|
||||
<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"
|
||||
@@ -241,95 +237,101 @@ export default function Landing() {
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* How it works */}
|
||||
{/* How it works — three pipeline nodes joined by a gradient connector.
|
||||
Desktop: horizontal line behind the numbered nodes. Mobile: the grid
|
||||
stacks and each card keeps its own node, joined by a left rail. */}
|
||||
<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]">
|
||||
<Kicker>how_it_works</Kicker>
|
||||
<h2 className="mt-3 text-[28px] font-semibold tracking-tight sm:text-[32px]">
|
||||
Three steps. No JSON to write, no Docker to manage.
|
||||
</p>
|
||||
</h2>
|
||||
</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 className="relative">
|
||||
{/* Gradient connector — desktop only, sits behind the node row. */}
|
||||
<div
|
||||
aria-hidden
|
||||
className="absolute left-0 right-0 top-[22px] hidden h-px md:block"
|
||||
style={{ background: 'var(--gradient-brand)', opacity: 0.35 }}
|
||||
/>
|
||||
{/* Mobile left rail joining the stacked nodes. */}
|
||||
<div
|
||||
aria-hidden
|
||||
className="absolute bottom-6 left-[22px] top-[22px] w-px md:hidden"
|
||||
style={{ background: 'var(--gradient-brand)', opacity: 0.35 }}
|
||||
/>
|
||||
<div className="grid gap-8 md:grid-cols-3 md:gap-6">
|
||||
{PIPELINE_STEPS.map((s) => (
|
||||
<div key={s.n} className="relative flex gap-4 md:block">
|
||||
<div
|
||||
className="mono relative z-10 flex size-11 shrink-0 items-center justify-center rounded-full border border-[--color-border-strong] text-[12px] tracking-widest text-[--color-fg]"
|
||||
style={{
|
||||
background: 'var(--color-bg)',
|
||||
boxShadow: 'inset 0 1px 0 rgba(255,255,255,0.05)',
|
||||
}}
|
||||
>
|
||||
{s.n}
|
||||
</div>
|
||||
<div className="min-w-0 md:mt-5">
|
||||
<h3 className="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>
|
||||
<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>
|
||||
</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">
|
||||
{/* Proof by specificity — three verifiable claims, each one click from
|
||||
its evidence. Replaces the old pseudo-logo row: no invented marks,
|
||||
just a plain-text compatibility line. */}
|
||||
<section className="border-b border-[--color-border] py-16 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]"
|
||||
<Kicker>verify_it_yourself</Kicker>
|
||||
<h2 className="mt-3 max-w-2xl text-[28px] font-semibold leading-[1.1] tracking-tight sm:text-[32px]">
|
||||
No testimonials yet — we're new.
|
||||
<br />
|
||||
<span className="text-[--color-fg-muted]">So check the claims instead.</span>
|
||||
</h2>
|
||||
<div className="mt-10 grid gap-4 md:grid-cols-3">
|
||||
{PROOF_POINTS.map((p) => {
|
||||
const Icon = p.Icon;
|
||||
return (
|
||||
<Link
|
||||
key={p.t}
|
||||
href={p.href}
|
||||
className="panel-raised group flex flex-col p-5 transition-colors hover:border-[--color-border-strong]"
|
||||
>
|
||||
{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>
|
||||
))}
|
||||
<Icon size={20} className="text-[--color-accent]" />
|
||||
<h3 className="mt-4 text-[15px] font-semibold tracking-tight">{p.t}</h3>
|
||||
<p className="mt-2 flex-1 text-[13px] leading-relaxed text-[--color-fg-muted]">
|
||||
{p.d}
|
||||
</p>
|
||||
<span className="mt-4 text-[13px] font-medium text-[--color-accent] transition-colors group-hover:text-[--color-fg]">
|
||||
{p.linkLabel} →
|
||||
</span>
|
||||
</Link>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
<p className="mt-10 text-center text-[13px] text-[--color-fg-subtle]">
|
||||
Works with Claude Desktop, Cursor, ChatGPT, VS Code Copilot and Continue.dev — anything
|
||||
that speaks MCP.
|
||||
</p>
|
||||
</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. */}
|
||||
{/* Use cases — brand-coloured integration grid. */}
|
||||
<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>
|
||||
<Kicker>use_cases</Kicker>
|
||||
<h2 className="mt-3 text-[32px] font-semibold leading-[1.1] tracking-tight sm:text-[40px]">
|
||||
Wrap any HTTP API.
|
||||
<br />
|
||||
@@ -337,7 +339,7 @@ export default function Landing() {
|
||||
</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.
|
||||
Ship integrations like these from one prompt each.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -347,7 +349,7 @@ export default function Landing() {
|
||||
return (
|
||||
<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]"
|
||||
className="panel-raised group flex items-start gap-4 p-5 transition-colors hover:border-[--color-border-strong]"
|
||||
>
|
||||
<div
|
||||
aria-hidden
|
||||
@@ -372,27 +374,20 @@ export default function Landing() {
|
||||
</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. */}
|
||||
{/* Marketplace — split layout: selling points left, honest preview
|
||||
frame right. */}
|
||||
<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>
|
||||
<Kicker>marketplace</Kicker>
|
||||
<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.
|
||||
The marketplace is a library of working MCP servers. Fork one, paste your credentials,
|
||||
deploy. Or publish yours and let others build on it.
|
||||
</p>
|
||||
|
||||
<ul className="mt-8 space-y-5">
|
||||
@@ -414,29 +409,22 @@ export default function Landing() {
|
||||
|
||||
<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]"
|
||||
className="btn-brand mt-8 inline-flex h-11 items-center gap-2 rounded-md px-5 text-[14px] font-medium"
|
||||
>
|
||||
Browse the marketplace →
|
||||
</PulseLink>
|
||||
</div>
|
||||
|
||||
{/* Right — mock marketplace browser frame */}
|
||||
<MarketplaceMock />
|
||||
<MarketplacePreview />
|
||||
</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. */}
|
||||
{/* Pricing teaser — Hobby + Pro only; the full matrix lives on
|
||||
/pricing. Data is shared via lib/pricing.ts so it can't drift. */}
|
||||
<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>
|
||||
<div className="mx-auto max-w-4xl px-6">
|
||||
<div className="mb-12 text-center">
|
||||
<Kicker>pricing</Kicker>
|
||||
<h2 className="mt-3 text-[32px] font-semibold leading-[1.1] tracking-tight sm:text-[40px]">
|
||||
Pay for tool calls.
|
||||
<br />
|
||||
@@ -444,16 +432,16 @@ export default function Landing() {
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div className="grid gap-5 md:grid-cols-2 lg:grid-cols-4">
|
||||
{TIERS.map((t) => {
|
||||
const featured = t.name === 'Pro';
|
||||
<div className="grid gap-5 sm:grid-cols-2">
|
||||
{teaserTiers.map((t) => {
|
||||
const featured = Boolean(t.highlight);
|
||||
return (
|
||||
<div
|
||||
key={t.name}
|
||||
className={`relative flex flex-col gap-6 rounded-xl border p-6 transition-colors ${
|
||||
className={`relative flex flex-col gap-6 rounded-xl border p-6 ${
|
||||
featured
|
||||
? 'border-[--color-accent] bg-[--color-bg-elevated]'
|
||||
: 'border-[--color-border] bg-[--color-bg-elevated] hover:border-[--color-border-strong]'
|
||||
: 'border-[--color-border] bg-[--color-bg-elevated]'
|
||||
}`}
|
||||
style={
|
||||
featured
|
||||
@@ -461,7 +449,7 @@ export default function Landing() {
|
||||
boxShadow:
|
||||
'0 0 0 4px rgba(99, 102, 241, 0.12), 0 24px 50px rgba(0, 0, 0, 0.35)',
|
||||
}
|
||||
: undefined
|
||||
: { boxShadow: 'inset 0 1px 0 rgba(255,255,255,0.04)' }
|
||||
}
|
||||
>
|
||||
{featured && (
|
||||
@@ -483,6 +471,9 @@ export default function Landing() {
|
||||
</span>
|
||||
<span className="text-[12px] text-[--color-fg-subtle]">{t.tag}</span>
|
||||
</div>
|
||||
<p className="mt-3 text-[13px] leading-relaxed text-[--color-fg-muted]">
|
||||
{t.description}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<ul className="flex flex-1 flex-col gap-2.5 border-t border-[--color-border] pt-5 text-[13px] text-[--color-fg-muted]">
|
||||
@@ -498,23 +489,42 @@ export default function Landing() {
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
|
||||
<Link
|
||||
href={t.href}
|
||||
className={`inline-flex h-10 items-center justify-center rounded-md px-4 text-[13px] font-medium transition-colors ${
|
||||
featured
|
||||
? 'btn-brand'
|
||||
: 'border border-[--color-border] bg-[--color-bg-subtle] text-[--color-fg] hover:border-[--color-border-strong]'
|
||||
}`}
|
||||
>
|
||||
{t.cta}
|
||||
</Link>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
||||
<div className="mt-8 text-center">
|
||||
<Link
|
||||
href="/pricing"
|
||||
className="text-[14px] font-medium text-[--color-accent] transition-colors hover:text-[--color-fg]"
|
||||
>
|
||||
See all plans — Team, Enterprise →
|
||||
</Link>
|
||||
</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">
|
||||
{/* FAQ — collapsible accordion using native <details>. Crawlers and
|
||||
screen readers see the full Q+A in the HTML. */}
|
||||
<section className="border-b border-[--color-border] 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>
|
||||
<Kicker>faq</Kicker>
|
||||
<h2 className="mt-3 text-[28px] font-semibold tracking-tight">
|
||||
Questions, answered straight.
|
||||
</h2>
|
||||
<div className="mt-8 border-t border-[--color-border]">
|
||||
{FAQ.map((f) => (
|
||||
<details
|
||||
@@ -536,28 +546,58 @@ export default function Landing() {
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Final CTA — the page must not end on FAQ. Gradient top border keeps
|
||||
the brand mark scarce but present at the exit point. */}
|
||||
<section className="relative py-20 sm:py-28">
|
||||
<div
|
||||
aria-hidden
|
||||
className="absolute inset-x-0 top-0 h-px"
|
||||
style={{ background: 'var(--gradient-brand)', opacity: 0.6 }}
|
||||
/>
|
||||
<div className="mx-auto max-w-3xl px-6 text-center">
|
||||
<h2 className="text-balance text-[32px] font-semibold leading-[1.1] tracking-tight sm:text-[44px]">
|
||||
Your first server is <span className="text-brand-gradient">one prompt away</span>.
|
||||
</h2>
|
||||
<p className="mx-auto mt-4 max-w-md text-[14.5px] leading-relaxed text-[--color-fg-muted]">
|
||||
Free tier, full source export, no lock-in. If it doesn't work for you, take the
|
||||
TypeScript and leave.
|
||||
</p>
|
||||
<div className="mt-8 flex flex-wrap items-center justify-center gap-3">
|
||||
<PulseLink
|
||||
href="/login"
|
||||
className="btn-brand inline-flex h-11 items-center justify-center rounded-md px-6 text-[14px] font-medium"
|
||||
>
|
||||
Start building free →
|
||||
</PulseLink>
|
||||
<PulseLink
|
||||
href="/docs"
|
||||
className="inline-flex h-11 items-center justify-center rounded-md border border-[--color-border] bg-[--color-bg-elevated] px-6 text-[14px] text-[--color-fg-muted] transition-colors hover:text-[--color-fg]"
|
||||
>
|
||||
Read the docs
|
||||
</PulseLink>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mock marketplace preview.
|
||||
* Honest 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.
|
||||
* Static, server-rendered browser frame showing what a template card looks
|
||||
* like. Card data mirrors the first-party starter templates — names, author
|
||||
* and tool counts only. No fork counts, no "verified" badges: the frame is
|
||||
* explicitly labelled a preview, not live marketplace traffic.
|
||||
*/
|
||||
function MarketplaceMock() {
|
||||
function MarketplacePreview() {
|
||||
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)' }}
|
||||
style={{
|
||||
boxShadow: 'inset 0 1px 0 rgba(255,255,255,0.04), 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">
|
||||
@@ -573,50 +613,37 @@ function MarketplaceMock() {
|
||||
|
||||
{/* 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>
|
||||
<span className="text-[13px] font-semibold tracking-tight text-[--color-fg]">
|
||||
Templates
|
||||
</span>
|
||||
<span className="mono text-[10px] uppercase tracking-wider text-[--color-fg-subtle]">
|
||||
preview
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* Template cards grid */}
|
||||
<div className="grid gap-3 p-4 sm:grid-cols-2">
|
||||
{MOCK_TEMPLATES.map((t) => (
|
||||
{PREVIEW_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 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>
|
||||
<span className="inline-flex items-center rounded-full border border-[--color-border-strong] px-1.5 py-px text-[9.5px] font-medium uppercase tracking-wider text-[--color-fg-subtle]">
|
||||
template
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mt-4 flex items-center justify-between text-[11px] text-[--color-fg-subtle]">
|
||||
<div className="mt-4 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>
|
||||
))}
|
||||
@@ -624,20 +651,3 @@ function MarketplaceMock() {
|
||||
</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>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { TIERS } from '@/lib/pricing';
|
||||
import { pageMetadata } from '@/lib/seo';
|
||||
import Link from 'next/link';
|
||||
|
||||
@@ -8,80 +9,6 @@ export const metadata = pageMetadata({
|
||||
path: '/pricing',
|
||||
});
|
||||
|
||||
const TIERS = [
|
||||
{
|
||||
name: 'Hobby',
|
||||
price: '€0',
|
||||
tag: 'Forever free',
|
||||
description: 'For trying things out and shipping single-user tools.',
|
||||
model: 'Open-tier AI',
|
||||
modelDetail: 'Free-tier model · ~30-60s analyze',
|
||||
features: [
|
||||
'1 MCP server',
|
||||
'100,000 tool calls / month',
|
||||
'5 prompt analyses / day',
|
||||
'BuildMyMCP subdomain',
|
||||
'Community support',
|
||||
],
|
||||
cta: 'Start free',
|
||||
href: '/login',
|
||||
},
|
||||
{
|
||||
name: 'Pro',
|
||||
price: '€49',
|
||||
tag: '/ month',
|
||||
description: 'For solo founders and small teams shipping production tools.',
|
||||
model: 'Claude AI',
|
||||
modelDetail: 'Powered by Anthropic Claude · ~10–20s analyze',
|
||||
features: [
|
||||
'5 MCP servers',
|
||||
'1M tool calls / month',
|
||||
'40 prompt analyses / day',
|
||||
'Priority build queue',
|
||||
'Custom domain · coming soon',
|
||||
'Email support, 1 business-day response',
|
||||
],
|
||||
cta: 'Start Pro',
|
||||
href: '/settings/billing?tier=pro_monthly',
|
||||
highlight: true,
|
||||
},
|
||||
{
|
||||
name: 'Team',
|
||||
price: '€199',
|
||||
tag: '/ month',
|
||||
description: 'For teams that need an audit trail and room to scale.',
|
||||
model: 'Claude AI',
|
||||
modelDetail: "Anthropic's flagship quality",
|
||||
features: [
|
||||
'25 MCP servers',
|
||||
'10M tool calls / month',
|
||||
'50 prompt analyses / day',
|
||||
'Audit log',
|
||||
'RBAC · coming soon',
|
||||
'Shared Slack channel support',
|
||||
],
|
||||
cta: 'Start Team',
|
||||
href: '/settings/billing?tier=team_monthly',
|
||||
},
|
||||
{
|
||||
name: 'Enterprise',
|
||||
price: 'Custom',
|
||||
tag: 'talk to us',
|
||||
description: 'For organizations with custom infrastructure, compliance and scale needs.',
|
||||
model: 'Claude AI',
|
||||
modelDetail: 'Top-tier Claude · EU data-residency option',
|
||||
features: [
|
||||
'Unlimited servers',
|
||||
'Custom infrastructure & data residency — on request',
|
||||
'Dedicated hosting — scoped per contract',
|
||||
'SSO / SAML — on request',
|
||||
'Customer success manager',
|
||||
],
|
||||
cta: 'Contact sales',
|
||||
href: 'mailto:sales@buildmymcpserver.com',
|
||||
},
|
||||
];
|
||||
|
||||
const FAQ = [
|
||||
{
|
||||
q: 'What counts as a tool call?',
|
||||
@@ -93,7 +20,7 @@ const FAQ = [
|
||||
},
|
||||
{
|
||||
q: 'Annual billing?',
|
||||
a: 'Yes — save 20% on Pro and Team paying annually. Enterprise is annual by default.',
|
||||
a: 'Annual plans are coming — contact us for annual invoicing today. Enterprise is annual by default.',
|
||||
},
|
||||
{
|
||||
q: 'Plan changes?',
|
||||
|
||||
Reference in New Issue
Block a user