kopia lustrzana https://github.com/transitive-bullshit/chatgpt-api
pull/715/head
rodzic
a42ea77ff2
commit
6f71ac6635
|
@ -50,7 +50,7 @@ export default function RootLayout({
|
||||||
<div className='w-full min-h-[100vh] relative flex flex-col items-center'>
|
<div className='w-full min-h-[100vh] relative flex flex-col items-center'>
|
||||||
<Header />
|
<Header />
|
||||||
|
|
||||||
<main className='flex-1 w-full flex flex-col items-center max-w-[1200px] gap-16 pt-8 pb-16 px-4 md:px-0'>
|
<main className='flex-1 w-full flex flex-col items-center max-w-[1200px] gap-16 pt-16 pb-24 px-4 md:px-0'>
|
||||||
{children}
|
{children}
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
|
|
|
@ -75,9 +75,6 @@ export default function LoginPage() {
|
||||||
>
|
>
|
||||||
<div className='flex flex-col items-center gap-2 text-center'>
|
<div className='flex flex-col items-center gap-2 text-center'>
|
||||||
<h1 className='text-2xl font-bold'>Login to your account</h1>
|
<h1 className='text-2xl font-bold'>Login to your account</h1>
|
||||||
<p className='text-muted-foreground text-sm text-balance'>
|
|
||||||
Enter your email below to login to your account
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='grid gap-6'>
|
<div className='grid gap-6'>
|
||||||
|
|
|
@ -4,7 +4,6 @@ import { GitHubStarCounter } from '@/components/github-star-counter'
|
||||||
import { SupplySideCTA } from '@/components/supply-side-cta'
|
import { SupplySideCTA } from '@/components/supply-side-cta'
|
||||||
import {
|
import {
|
||||||
calendarBookingUrl,
|
calendarBookingUrl,
|
||||||
discordUrl,
|
|
||||||
docsUrl,
|
docsUrl,
|
||||||
githubUrl,
|
githubUrl,
|
||||||
twitterUrl
|
twitterUrl
|
||||||
|
@ -15,7 +14,7 @@ export default function TheBestDamnLandingPageEver() {
|
||||||
<>
|
<>
|
||||||
{/* Hero section */}
|
{/* Hero section */}
|
||||||
<section className='gap-8'>
|
<section className='gap-8'>
|
||||||
<h1 className='text-center text-balance leading-snug md:leading-none text-4xl font-extrabold'>
|
<h1 className='text-center text-balance leading-snug md:leading-none text-4xl font-bold'>
|
||||||
Your API → Paid MCP, Instantly
|
Your API → Paid MCP, Instantly
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
|
@ -30,7 +29,7 @@ export default function TheBestDamnLandingPageEver() {
|
||||||
|
|
||||||
{/* How it works section */}
|
{/* How it works section */}
|
||||||
<section className='flex flex-col gap-8'>
|
<section className='flex flex-col gap-8'>
|
||||||
<h2 className='text-center text-balance leading-snug md:leading-none text-2xl font-heading'>
|
<h2 className='text-center text-balance leading-snug md:leading-none text-3xl font-heading'>
|
||||||
How It Works
|
How It Works
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
|
@ -39,11 +38,11 @@ export default function TheBestDamnLandingPageEver() {
|
||||||
|
|
||||||
{/* Features section */}
|
{/* Features section */}
|
||||||
<section className='flex flex-col gap-8'>
|
<section className='flex flex-col gap-8'>
|
||||||
<h2 className='text-center text-balance leading-snug md:leading-none text-2xl font-heading'>
|
<h2 className='text-center text-balance leading-snug md:leading-none text-3xl font-heading'>
|
||||||
Production-Ready and Extremely Flexible
|
Production-Ready and Extremely Flexible
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
<div className='grid gap-6'>
|
<div className='grid gap-6 max-w-2xl'>
|
||||||
<div className='flex flex-col gap-2'>
|
<div className='flex flex-col gap-2'>
|
||||||
<h4 className='text-center text-balance text-lg font-heading'>
|
<h4 className='text-center text-balance text-lg font-heading'>
|
||||||
Auth
|
Auth
|
||||||
|
@ -68,21 +67,22 @@ export default function TheBestDamnLandingPageEver() {
|
||||||
|
|
||||||
<div className='flex flex-col gap-2'>
|
<div className='flex flex-col gap-2'>
|
||||||
<h4 className='text-center text-balance text-lg font-heading'>
|
<h4 className='text-center text-balance text-lg font-heading'>
|
||||||
Monetization
|
Stripe Billing
|
||||||
</h4>
|
</h4>
|
||||||
|
|
||||||
<p className='text-sm'>
|
<p className='text-sm'>
|
||||||
Charge for your MCP products with a flexible, declarative pricing
|
Charge for your MCP products with a flexible, declarative pricing
|
||||||
model built on top of Stripe. Agentic supports almost any
|
model built on top of Stripe. Agentic supports almost any
|
||||||
combination of fixed and usage-based billing models, both at the
|
combination of fixed and{' '}
|
||||||
MCP level, at the tool-call level, and at the custom metric level
|
<span className='font-semibold'>usage-based billing</span> models,
|
||||||
(e.g., tokens, image transformations, etc).
|
both at the MCP level, at the tool-call level, and at the custom
|
||||||
|
metric level (e.g., tokens, image transformations, etc).
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='flex flex-col gap-2'>
|
<div className='flex flex-col gap-2'>
|
||||||
<h4 className='text-center text-balance text-lg font-heading'>
|
<h4 className='text-center text-balance text-lg font-heading'>
|
||||||
Support both MCP <em>and</em> HTTP
|
Support both MCP and HTTP
|
||||||
</h4>
|
</h4>
|
||||||
|
|
||||||
<p className='text-sm'>
|
<p className='text-sm'>
|
||||||
|
@ -97,18 +97,30 @@ export default function TheBestDamnLandingPageEver() {
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className='flex flex-col gap-2'>
|
||||||
|
<h4 className='text-center text-balance text-lg font-heading'>
|
||||||
|
API keys
|
||||||
|
</h4>
|
||||||
|
|
||||||
|
<p className='text-sm'>
|
||||||
|
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 <em>Authorization</em> header.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className='flex flex-col gap-2'>
|
<div className='flex flex-col gap-2'>
|
||||||
<h4 className='text-center text-balance text-lg font-heading'>
|
<h4 className='text-center text-balance text-lg font-heading'>
|
||||||
Rate-limiting
|
Rate-limiting
|
||||||
</h4>
|
</h4>
|
||||||
|
|
||||||
<p className='text-sm'>
|
<p className='text-sm'>
|
||||||
Customize your MCP product with durable rate-limiting built on top
|
All agentic products are protected by durable rate-limiting built
|
||||||
of Cloudflare's global infrastructure. Create default rate-limits,
|
on top of Cloudflare's global infrastructure. Customize the
|
||||||
change them based on a customer's subscribed pricing plan, and
|
default rate-limits, change them based on a customer's pricing
|
||||||
create custom tool-specific overrides, all with a simple,
|
plan, or create custom tool-specific overrides. REST assured that
|
||||||
strongly-typed JSON config. REST assured that your origin API will
|
your origin API will be safe behind Agentic's robust API gateway.
|
||||||
be safe behind Agentic's robust API gateway.
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -119,11 +131,11 @@ export default function TheBestDamnLandingPageEver() {
|
||||||
|
|
||||||
<p className='text-sm'>
|
<p className='text-sm'>
|
||||||
Opt-in to caching with familiar <em>cache-control</em> and{' '}
|
Opt-in to caching with familiar <em>cache-control</em> and{' '}
|
||||||
<em>stale-while-revalidate</em> features. MCP tool calls include
|
<em>stale-while-revalidate</em> options. MCP tool calls include
|
||||||
caching information in their <em>_meta</em> fields with symmetry
|
caching information in their <em>_meta</em> fields, providing
|
||||||
to standard HTTP headers. All caching takes place in Cloudflare's
|
parity with standard HTTP headers. All caching takes place in
|
||||||
global edge cache, and will only be enabled if you choose to
|
Cloudflare's global edge cache, and caching will only be enabled
|
||||||
enable it for your product or specific tools.
|
if you choose to enable it for your product or individual tools.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -133,9 +145,9 @@ export default function TheBestDamnLandingPageEver() {
|
||||||
</h4>
|
</h4>
|
||||||
|
|
||||||
<p className='text-sm'>
|
<p className='text-sm'>
|
||||||
Agentic tracks usage-based billing and analytics at a fine-grained
|
Agentic tracks all tool calls for usage-based billing and
|
||||||
level, so you can understand how your customers are using your
|
analytics at a fine-grained level, so you can drill in and deeply
|
||||||
product.
|
understand how your customers are using your product.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -149,7 +161,7 @@ export default function TheBestDamnLandingPageEver() {
|
||||||
time you make a change to your product's config, pricing, or docs,
|
time you make a change to your product's config, pricing, or docs,
|
||||||
a unique preview deployment is created for that change. This
|
a unique preview deployment is created for that change. This
|
||||||
enables instant rollbacks if there are problems with a deployment.
|
enables instant rollbacks if there are problems with a deployment.
|
||||||
Publish deployment publicly uses semantic versioning (
|
Publishing deployments publicly uses semantic versioning (
|
||||||
<em>semver</em>), so your customers can choose how to handle
|
<em>semver</em>), so your customers can choose how to handle
|
||||||
breaking changes.
|
breaking changes.
|
||||||
</p>
|
</p>
|
||||||
|
@ -157,43 +169,42 @@ export default function TheBestDamnLandingPageEver() {
|
||||||
|
|
||||||
<div className='flex flex-col gap-2'>
|
<div className='flex flex-col gap-2'>
|
||||||
<h4 className='text-center text-balance text-lg font-heading'>
|
<h4 className='text-center text-balance text-lg font-heading'>
|
||||||
And more!
|
That's just the start
|
||||||
</h4>
|
</h4>
|
||||||
|
|
||||||
<p className='text-sm'>
|
<p className='text-sm'>
|
||||||
Checkout our <Link href={docsUrl}>docs</Link> for more details on
|
<Link href={docsUrl} className='link'>
|
||||||
Agentic's MCP API gateway.
|
Check out our docs
|
||||||
|
</Link>{' '}
|
||||||
|
for more details on Agentic's MCP API gateway.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* Marketplace section */}
|
{/* Marketplace section */}
|
||||||
<section className='flex flex-col gap-8'>
|
{/* <section className='flex flex-col gap-8'>
|
||||||
<h2 className='text-center text-balance leading-snug md:leading-none text-2xl font-heading'>
|
<h2 className='text-center text-balance leading-snug md:leading-none text-3xl font-heading'>
|
||||||
MCP Marketplace
|
MCP Marketplace
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
<p>Coming soon...</p>
|
<p>
|
||||||
</section>
|
<i>Coming soon...</i>
|
||||||
|
</p>
|
||||||
|
</section> */}
|
||||||
|
|
||||||
{/* Open source section */}
|
{/* Open source section */}
|
||||||
<section className='flex flex-col items-center gap-8 max-w-2xl text-center'>
|
<section className='flex flex-col items-center gap-8 max-w-2xl text-center'>
|
||||||
<h2 className='text-center text-balance leading-snug md:leading-none text-2xl font-heading italic'>
|
<h2 className='text-center text-balance leading-snug md:leading-none text-3xl font-heading'>
|
||||||
Agentic is 100% Open Source!
|
Agentic is 100% Open Source
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
<p className='text-sm'>
|
<p className=''>
|
||||||
Join the tens of thousands of TypeScript AI engineers who've{' '}
|
Open source is very dear to my heart, and I couldn't be happier that
|
||||||
<Link
|
Agentic is fully OSS. It's written in{' '}
|
||||||
href={githubUrl}
|
<span className='font-semibold'>TypeScript</span>, stands on the
|
||||||
target='_blank'
|
shoulders of infra giants (Vercel, Cloudflare, Postgres), and has a
|
||||||
rel='noopener'
|
small but vibrant developer community.{' '}
|
||||||
className='link'
|
|
||||||
>
|
|
||||||
starred the project on GitHub
|
|
||||||
</Link>
|
|
||||||
.{' '}
|
|
||||||
<Link
|
<Link
|
||||||
href={githubUrl}
|
href={githubUrl}
|
||||||
target='_blank'
|
target='_blank'
|
||||||
|
@ -201,17 +212,8 @@ export default function TheBestDamnLandingPageEver() {
|
||||||
className='link'
|
className='link'
|
||||||
>
|
>
|
||||||
Check out the source on GitHub
|
Check out the source on GitHub
|
||||||
</Link>
|
</Link>{' '}
|
||||||
,{' '}
|
or{' '}
|
||||||
<Link
|
|
||||||
href={discordUrl}
|
|
||||||
target='_blank'
|
|
||||||
rel='noopener'
|
|
||||||
className='link'
|
|
||||||
>
|
|
||||||
join our community on Discord
|
|
||||||
</Link>
|
|
||||||
, or{' '}
|
|
||||||
<Link
|
<Link
|
||||||
href={twitterUrl}
|
href={twitterUrl}
|
||||||
target='_blank'
|
target='_blank'
|
||||||
|
@ -219,16 +221,31 @@ export default function TheBestDamnLandingPageEver() {
|
||||||
className='link'
|
className='link'
|
||||||
>
|
>
|
||||||
ping me on Twitter
|
ping me on Twitter
|
||||||
</Link>
|
</Link>{' '}
|
||||||
.
|
with questions / feedback.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<GitHubStarCounter />
|
<GitHubStarCounter />
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
{/* Social proof section */}
|
||||||
|
<section className='gap-8'>
|
||||||
|
<h2 className='text-center text-balance leading-snug md:leading-none text-3xl font-heading'>
|
||||||
|
TODO: social proof
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<p className='text-center text-lg max-w-2xl'>TODO</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
{/* CTA section */}
|
{/* CTA section */}
|
||||||
<section className='flex flex-col gap-8'>
|
<section className='flex flex-col gap-12'>
|
||||||
<SupplySideCTA />
|
<h2 className='text-center text-balance leading-snug md:leading-none text-3xl font-heading'>
|
||||||
|
Deploy Your MCP Product Today
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<p>Join the AI gold rush && deploy your first MCP product today.</p>
|
||||||
|
|
||||||
|
<SupplySideCTA variant='github-2' />
|
||||||
</section>
|
</section>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|
|
@ -89,9 +89,6 @@ export default function SignupPage() {
|
||||||
>
|
>
|
||||||
<div className='flex flex-col items-center gap-2 text-center'>
|
<div className='flex flex-col items-center gap-2 text-center'>
|
||||||
<h1 className='text-2xl font-bold'>Create an account</h1>
|
<h1 className='text-2xl font-bold'>Create an account</h1>
|
||||||
<p className='text-muted-foreground text-sm text-balance'>
|
|
||||||
Enter your info below to create an account
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='grid gap-6'>
|
<div className='grid gap-6'>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
import NumberFlow from '@number-flow/react'
|
import NumberFlow from '@number-flow/react'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import { useEffect, useState } from 'react'
|
import { type ReactNode, useEffect, useState } from 'react'
|
||||||
|
|
||||||
import { GitHubIcon } from '@/icons/github'
|
import { GitHubIcon } from '@/icons/github'
|
||||||
import { githubUrl } from '@/lib/config'
|
import { githubUrl } from '@/lib/config'
|
||||||
|
@ -13,7 +13,13 @@ import { Button } from './ui/button'
|
||||||
// TODO: fetch this dynamically
|
// TODO: fetch this dynamically
|
||||||
const numGitHubStars = 17_600
|
const numGitHubStars = 17_600
|
||||||
|
|
||||||
export function GitHubStarCounter({ className }: { className?: string }) {
|
export function GitHubStarCounter({
|
||||||
|
className,
|
||||||
|
children
|
||||||
|
}: {
|
||||||
|
className?: string
|
||||||
|
children?: ReactNode
|
||||||
|
}) {
|
||||||
const [numStars, setNumStars] = useState(0)
|
const [numStars, setNumStars] = useState(0)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -35,9 +41,11 @@ export function GitHubStarCounter({ className }: { className?: string }) {
|
||||||
notation: 'compact',
|
notation: 'compact',
|
||||||
roundingPriority: 'morePrecision'
|
roundingPriority: 'morePrecision'
|
||||||
}}
|
}}
|
||||||
suffix=' stars'
|
suffix={children ? undefined : ' stars'}
|
||||||
willChange
|
willChange
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
{children}
|
||||||
</Link>
|
</Link>
|
||||||
</Button>
|
</Button>
|
||||||
)
|
)
|
||||||
|
|
|
@ -5,16 +5,22 @@ import Link from 'next/link'
|
||||||
|
|
||||||
import { HeroButton } from '@/components/hero-button'
|
import { HeroButton } from '@/components/hero-button'
|
||||||
import { Button } from '@/components/ui/button'
|
import { Button } from '@/components/ui/button'
|
||||||
import { calendarBookingUrl, docsQuickStartUrl } from '@/lib/config'
|
import { GitHubIcon } from '@/icons/github'
|
||||||
|
import { calendarBookingUrl, docsQuickStartUrl, githubUrl } from '@/lib/config'
|
||||||
|
|
||||||
import { useAgentic } from './agentic-provider'
|
import { useAgentic } from './agentic-provider'
|
||||||
|
import { GitHubStarCounter } from './github-star-counter'
|
||||||
|
|
||||||
export function SupplySideCTA() {
|
export function SupplySideCTA({
|
||||||
|
variant = 'github'
|
||||||
|
}: {
|
||||||
|
variant?: 'book-call' | 'github' | 'github-2'
|
||||||
|
}) {
|
||||||
const ctx = useAgentic()
|
const ctx = useAgentic()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='flex justify-center items-center gap-8'>
|
<div className='flex justify-center items-center gap-8'>
|
||||||
<HeroButton asChild className='h-full'>
|
<HeroButton asChild className=''>
|
||||||
<Link
|
<Link
|
||||||
href={
|
href={
|
||||||
ctx?.isAuthenticated
|
ctx?.isAuthenticated
|
||||||
|
@ -26,11 +32,22 @@ export function SupplySideCTA() {
|
||||||
</Link>
|
</Link>
|
||||||
</HeroButton>
|
</HeroButton>
|
||||||
|
|
||||||
<Button variant='outline' asChild className='h-full'>
|
{variant === 'github' ? (
|
||||||
<Link href={calendarBookingUrl} target='_blank' rel='noopener'>
|
<GitHubStarCounter className='h-full py-[9px]' />
|
||||||
Book a call with me 👋
|
) : variant === 'github-2' ? (
|
||||||
</Link>
|
<Button variant='outline' asChild className='h-full py-[9px]'>
|
||||||
</Button>
|
<Link href={githubUrl} target='_blank' rel='noopener'>
|
||||||
|
<GitHubIcon />
|
||||||
|
Star Agentic on GitHub
|
||||||
|
</Link>
|
||||||
|
</Button>
|
||||||
|
) : (
|
||||||
|
<Button variant='outline' asChild className='h-full py-[9px]'>
|
||||||
|
<Link href={calendarBookingUrl} target='_blank' rel='noopener'>
|
||||||
|
Book a call with the founder 👋
|
||||||
|
</Link>
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
- stripe billing portal
|
- stripe billing portal
|
||||||
- should we bypass stripe for `free` plans to increase conversions?
|
- should we bypass stripe for `free` plans to increase conversions?
|
||||||
- handle browser back/forward with `?next=`
|
- handle browser back/forward with `?next=`
|
||||||
|
- add some social proof to signup page
|
||||||
- **API gateway**
|
- **API gateway**
|
||||||
- oauth flow
|
- oauth flow
|
||||||
- https://docs.scalekit.com/guides/mcp/oauth
|
- https://docs.scalekit.com/guides/mcp/oauth
|
||||||
|
@ -43,6 +44,7 @@
|
||||||
- consider using [neon serverless driver](https://orm.drizzle.team/docs/connect-neon) for production
|
- consider using [neon serverless driver](https://orm.drizzle.team/docs/connect-neon) for production
|
||||||
- can this also be used locally?
|
- can this also be used locally?
|
||||||
- may need to update our `drizzle-orm` fork
|
- may need to update our `drizzle-orm` fork
|
||||||
|
- figure out the best OSS license for launch
|
||||||
|
|
||||||
## TODO: Post-MVP
|
## TODO: Post-MVP
|
||||||
|
|
||||||
|
|
Ładowanie…
Reference in New Issue