From 52302243cd70c5d79244fa35e30a6f98e1c2dfaf Mon Sep 17 00:00:00 2001 From: Travis Fischer Date: Wed, 25 Jun 2025 09:33:55 -0500 Subject: [PATCH] feat(web): finesse features section --- apps/web/src/app/mcp-authors/page.tsx | 164 +--------- apps/web/src/app/page.tsx | 1 - apps/web/src/components/demand-side-cta.tsx | 2 +- apps/web/src/components/features.tsx | 336 ++++++++++++++++++++ apps/web/src/components/footer.tsx | 14 +- apps/web/src/components/grid-pattern.tsx | 64 ++++ apps/web/src/components/header/index.tsx | 2 +- apps/web/src/components/supply-side-cta.tsx | 2 +- 8 files changed, 428 insertions(+), 157 deletions(-) create mode 100644 apps/web/src/components/features.tsx create mode 100644 apps/web/src/components/grid-pattern.tsx diff --git a/apps/web/src/app/mcp-authors/page.tsx b/apps/web/src/app/mcp-authors/page.tsx index ee6e6898..8948ec83 100644 --- a/apps/web/src/app/mcp-authors/page.tsx +++ b/apps/web/src/app/mcp-authors/page.tsx @@ -2,14 +2,10 @@ import Link from 'next/link' import { DotsSection } from '@/components/dots-section' import { ExampleAgenticConfigs } from '@/components/example-agentic-configs' +import { Features } from '@/components/features' import { GitHubStarCounter } from '@/components/github-star-counter' import { SupplySideCTA } from '@/components/supply-side-cta' -import { - calendarBookingUrl, - docsUrl, - githubUrl, - twitterUrl -} from '@/lib/config' +import { githubUrl, twitterUrl } from '@/lib/config' export default function MCPAuthorsPage() { return ( @@ -64,147 +60,10 @@ export default function MCPAuthorsPage() { {/* Features section */}

- Production-Ready and Extremely Flexible + Production-Ready MCP Gateway

-
-
-

- Auth -

- -

- Ship to production fast with Agentic's free, built-in - authentication. Email & password, OAuth, GitHub, Google, Twitter, - etc – if your origin API requires OAuth credentials, Agentic - likely already supports it, and if not,{' '} - - let me know - - . -

-
- -
-

- Stripe Billing -

- -

- Charge for your MCP products with a flexible, declarative pricing - model built on top of Stripe. Agentic supports almost any - combination of fixed and{' '} - usage-based billing models, - both at the MCP level, at the tool-call level, and at the custom - metric level (e.g., tokens, image transformations, etc). -

-
- -
-

- Support both MCP and HTTP -

- -

- All agentic products support being used both as a standard MCP - server and as an extremely simple HTTP API. MCP is - important for interop, discoverability, and future-proofing, - whereas being able to call your agentic tools via simple{' '} - HTTP POST requests makes tool use easy to debug and makes - integration with existing LLM tool calling patterns a breeze. With - Agentic, you get the best of both worlds, including future support - for unreleased MCP features and related specs. -

-
- -
-

- API keys -

- -

- When a customer subscribes to your product, they're given a unique - API key. MCP URLs are appended with this API key to correlate - usage with their subscription. Customer HTTP tool calls use the - same API key as a standard HTTP Authorization header. -

-
- -
-

- Rate-limiting -

- -

- All agentic products are protected by durable rate-limiting built - on top of Cloudflare's global infrastructure. Customize the - default rate-limits, change them based on a customer's pricing - plan, or create custom tool-specific overrides. REST assured that - your origin API will be safe behind Agentic's robust API gateway. -

-
- -
-

- Caching -

- -

- Opt-in to caching with familiar cache-control and{' '} - stale-while-revalidate options. MCP tool calls include - caching information in their _meta fields, providing - parity with standard HTTP headers. All caching takes place in - Cloudflare's global edge cache, and caching will only be enabled - if you choose to enable it for your product or individual tools. -

-
- -
-

- Analytics -

- -

- Agentic tracks all tool calls for usage-based billing and - analytics at a fine-grained level, so you can drill in and deeply - understand how your customers are using your product. -

-
- -
-

- Versioning -

- -

- Just like Vercel, Agentic uses immutable deployments, so every - time you make a change to your product's config, pricing, or docs, - a unique preview deployment is created for that change. This - enables instant rollbacks if there are problems with a deployment. - Publishing deployments publicly uses semantic versioning ( - semver), so your customers can choose how to handle - breaking changes. -

-
- -
-

- That's just the start -

- -

- - Check out our docs - {' '} - for more details on Agentic's MCP API gateway. -

-
-
+
{/* Open source section */} @@ -214,7 +73,6 @@ export default function MCPAuthorsPage() {

- Open source is very dear to my heart, and I couldn't be happier that Agentic is fully OSS. It's written in{' '} TypeScript and has a small but vibrant developer community.{' '} @@ -242,13 +100,15 @@ export default function MCPAuthorsPage() { {/* CTA section */} -

-

- Deploy Your MCP Today -

+ +
+

+ Deploy Your MCP Today +

- -
+ + + ) } diff --git a/apps/web/src/app/page.tsx b/apps/web/src/app/page.tsx index 6b474400..dd429855 100644 --- a/apps/web/src/app/page.tsx +++ b/apps/web/src/app/page.tsx @@ -105,7 +105,6 @@ export default async function TheBestDamnLandingPageEver() {

- Open source is very dear to my heart, and I couldn't be happier that Agentic is fully OSS. It's written in{' '} TypeScript and has a small but vibrant developer community.{' '} diff --git a/apps/web/src/components/demand-side-cta.tsx b/apps/web/src/components/demand-side-cta.tsx index 3c3a6eb3..81e00b15 100644 --- a/apps/web/src/components/demand-side-cta.tsx +++ b/apps/web/src/components/demand-side-cta.tsx @@ -6,7 +6,7 @@ import { docsMarketplaceUrl } from '@/lib/config' export function DemandSideCTA() { return ( -

+
gotoTools(); diff --git a/apps/web/src/components/features.tsx b/apps/web/src/components/features.tsx new file mode 100644 index 00000000..67ac934e --- /dev/null +++ b/apps/web/src/components/features.tsx @@ -0,0 +1,336 @@ +'use client' + +import type { ComponentType, ReactNode } from 'react' +import { + ChartNoAxesCombinedIcon, + CheckCheckIcon, + CreditCardIcon, + DatabaseZapIcon, + HistoryIcon, + KeyRoundIcon, + ShieldCheckIcon, + TextSelectIcon, + UserIcon +} from 'lucide-react' +import { + motion, + type MotionValue, + useMotionTemplate, + useMotionValue +} from 'motion/react' +import Link from 'next/link' + +import { calendarBookingUrl, docsUrl } from '@/lib/config' + +import { GridPattern } from './grid-pattern' + +type Feature = { + name: string + description: ReactNode + icon: ComponentType<{ className?: string }> + pattern: Omit + href?: string +} + +const FEATURES: Feature[] = [ + { + name: 'Auth', + description: ( + <> + Ship to production fast with Agentic's free, built-in authentication. + Email & password, OAuth, GitHub, Google, Twitter, etc – if your origin + API requires OAuth credentials, Agentic likely already supports it, and + if not,{' '} + + let me know + + . + + ), + icon: UserIcon, + pattern: { + y: 16, + squares: [ + [0, 1], + [1, 3] + ] + } + }, + { + name: 'Stripe Billing', + description: ( + <> + Charge for your MCP products with a flexible, declarative pricing model + built on top of Stripe. Agentic supports almost any combination of fixed + and usage-based billing models, + both at the MCP level, at the tool-call level, and at the custom metric + level (e.g., tokens, image transformations, etc). + + ), + icon: CreditCardIcon, + pattern: { + y: -6, + squares: [ + [-1, 2], + [1, 3] + ] + } + }, + { + name: 'Support both MCP and HTTP', + description: ( + <> + All agentic products support being used both as a standard MCP server{' '} + and as an extremely simple HTTP API. MCP is important for + interop and future-proofing, whereas being able to call your agentic + tools via simple HTTP POST requests makes tool use easy to + debug and makes integration with existing LLM tool calling patterns a + breeze. + + ), + icon: CheckCheckIcon, + pattern: { + y: 32, + squares: [ + [0, 2], + [1, 4] + ] + } + }, + { + name: 'API Keys', + description: ( + <> + When a customer subscribes to your product, they're given a unique API + key. MCP URLs are appended with this API key to correlate usage with + their subscription. Customer HTTP tool calls use the same API key as a + standard HTTP Authorization header. + + ), + icon: KeyRoundIcon, + pattern: { + y: 22, + squares: [[0, 1]] + } + }, + { + name: 'Rate-limiting', + description: ( + <> + All agentic products are protected by durable rate-limiting built on top + of Cloudflare's global infrastructure. Customize the default + rate-limits, change them based on a customer's pricing plan, or create + custom tool-specific overrides. REST assured that your origin API will + be safe behind Agentic's API gateway. + + ), + icon: ShieldCheckIcon, + pattern: { + y: 2, + squares: [ + [-2, 3], + [1, 4] + ] + } + }, + { + name: 'Caching', + description: ( + <> + Opt-in to caching with familiar cache-control and{' '} + stale-while-revalidate options. MCP tool calls include caching + information in their _meta fields, providing parity with + standard HTTP headers. All caching takes place in Cloudflare's global + edge cache, and caching will only be enabled if you choose to enable it + for your product or individual tools. + + ), + icon: DatabaseZapIcon, + pattern: { + y: 8, + squares: [ + [0, 2], + [-1, 1] + ] + } + }, + { + name: 'Analytics', + description: ( + <> + Agentic tracks all tool calls for usage-based billing and analytics at a + fine-grained level, so you can drill in and deeply understand how your + customers are using your product. + + ), + icon: ChartNoAxesCombinedIcon, + pattern: { + y: -2, + squares: [[-2, 2]] + } + }, + { + name: 'Versioning', + description: ( + <> + Just like Vercel, Agentic uses immutable deployments, so every time you + make a change to your product's config, pricing, or docs, a unique + preview deployment is created for that change. This enables instant + rollbacks if there are problems with a deployment. Publishing + deployments publicly uses semantic versioning (semver), so your + customers can choose how to handle breaking changes. + + ), + icon: HistoryIcon, + pattern: { + y: 26, + squares: [ + [2, 4], + [-2, 3] + ] + } + }, + { + name: "That's just the start", + description: ( + <>Check out our docs for more details on Agentic's MCP gateway. + ), + href: docsUrl, + icon: TextSelectIcon, + pattern: { + y: 13, + squares: [ + [0, 2], + [0, 2] + ] + } + } +] + +function Feature({ name, description, icon, pattern, href }: Feature) { + const mouseX = useMotionValue(0) + const mouseY = useMotionValue(0) + + function onMouseMove({ + currentTarget, + clientX, + clientY + }: React.MouseEvent) { + const { left, top } = currentTarget.getBoundingClientRect() + mouseX.set(clientX - left) + mouseY.set(clientY - top) + } + + const content = ( + <> + + +
+ +
+ + +

+ {/* */} + {name} +

+ +

+ {description} +

+
+ + ) + + const className = + 'dark:bg-white/2.5 bg-gray-50 hover:shadow-gray-900/5 group relative flex rounded-2xl transition-shadow hover:shadow-md dark:hover:shadow-black/5' + + if (href) { + return ( + + {content} + + ) + } else { + return ( +
+ {content} +
+ ) + } +} + +// eslint-disable-next-line @typescript-eslint/naming-convention +function FeatureIcon({ icon: Icon }: { icon: Feature['icon'] }) { + return ( +
+ +
+ ) +} + +function FeaturePattern({ + mouseX, + mouseY, + ...gridProps +}: Feature['pattern'] & { + mouseX: MotionValue + mouseY: MotionValue +}) { + const maskImage = useMotionTemplate`radial-gradient(180px at ${mouseX}px ${mouseY}px, white, transparent)` + const style = { maskImage, WebkitMaskImage: maskImage } + + return ( +
+
+ +
+ + + + + + +
+ ) +} + +export function Features() { + return ( +
+
+ {FEATURES.map((feature) => ( + + ))} +
+
+ ) +} diff --git a/apps/web/src/components/footer.tsx b/apps/web/src/components/footer.tsx index da675c4e..b3c6f75a 100644 --- a/apps/web/src/components/footer.tsx +++ b/apps/web/src/components/footer.tsx @@ -3,7 +3,7 @@ import Link from 'next/link' import { ActiveLink } from '@/components/active-link' import { GitHubIcon } from '@/icons/github' import { TwitterIcon } from '@/icons/twitter' -import { copyright, githubUrl, twitterUrl } from '@/lib/config' +import { copyright, docsUrl, githubUrl, twitterUrl } from '@/lib/config' export function Footer() { return ( @@ -21,12 +21,24 @@ export function Footer() { + + + MCP Marketplace + + + For MCP Authors + + + Docs + + + About diff --git a/apps/web/src/components/grid-pattern.tsx b/apps/web/src/components/grid-pattern.tsx new file mode 100644 index 00000000..d3eb2035 --- /dev/null +++ b/apps/web/src/components/grid-pattern.tsx @@ -0,0 +1,64 @@ +import { type SVGProps, useId } from 'react' + +export type GridPattern = Omit< + SVGProps, + 'width' | 'height' | 'x' | 'y' +> & { + width: number + height: number + x: string | number + y: string | number + squares: Array<[x: number, y: number]> +} + +export function GridPattern({ + width, + height, + x, + y, + squares, + ...props +}: GridPattern) { + const patternId = useId() + + return ( + + ) +} diff --git a/apps/web/src/components/header/index.tsx b/apps/web/src/components/header/index.tsx index 166beaab..f294409b 100644 --- a/apps/web/src/components/header/index.tsx +++ b/apps/web/src/components/header/index.tsx @@ -19,7 +19,7 @@ export function Header() {
- Marketplace + MCP Marketplace diff --git a/apps/web/src/components/supply-side-cta.tsx b/apps/web/src/components/supply-side-cta.tsx index e92e0dd0..aa72d7d7 100644 --- a/apps/web/src/components/supply-side-cta.tsx +++ b/apps/web/src/components/supply-side-cta.tsx @@ -19,7 +19,7 @@ export function SupplySideCTA({ const ctx = useAgentic() return ( -
+