feat(web): improve header and footer

pull/716/head
Travis Fischer 2025-06-30 01:34:30 -05:00
rodzic e056237fb8
commit fa987bac7d
15 zmienionych plików z 325 dodań i 186 usunięć

Wyświetl plik

@ -14,9 +14,10 @@ The platform consists of:
- **Gateway Service** (`apps/gateway/`) - Cloudflare Worker that proxies requests to origin MCP/OpenAPI services
- **Website** (`apps/web/`) - Next.js site for both the marketing site and authenticated webapp
- **E2E Tests** (`apps/e2e/`) - End-to-end test suite for HTTP and MCP gateway requests
- **Shared Packages** (`packages/`) - Common utilities, types, validators, and configuration
- **Shared Packages** (`packages/`) - Common utilities, types, validators, and config
- **StdLib Packages** (`stdlib/`) - TS AI SDK adapters
The gateway accepts requests at `https://gateway.agentic.so/deploymentIdentifier/toolName` for HTTP requests or `https://gateway.agentic.so/deploymentIdentifier/mcp` for MCP.
The gateway accepts requests at `https://gateway.agentic.so/deploymentIdentifier/tool-ame` for HTTP requests or `https://gateway.agentic.so/deploymentIdentifier/mcp` for MCP.
### Development Commands

Wyświetl plik

@ -1,5 +1,6 @@
import Link from 'next/link'
import { DotsSection } from '@/components/dots-section'
import { PageContainer } from '@/components/page-container'
import { SupplySideCTA } from '@/components/supply-side-cta'
import { githubUrl, twitterUrl } from '@/lib/config'
@ -179,13 +180,15 @@ export default function AboutPage() {
</section>
{/* CTA section */}
<section className='flex flex-col gap-12'>
<h2 className='text-center text-balance leading-snug md:leading-none text-3xl font-heading'>
Don't miss out on this AI wave
</h2>
<DotsSection>
<div className='flex flex-col gap-12 relative z-10'>
<h2 className='text-center text-balance leading-snug md:leading-none text-3xl font-heading'>
Don't miss out on the AI wave
</h2>
<SupplySideCTA variant='github-2' />
</section>
<SupplySideCTA variant='github-2' />
</div>
</DotsSection>
</PageContainer>
)
}

Wyświetl plik

@ -9,11 +9,7 @@ import { HeroSimulation2 } from '@/components/hero-simulation-2'
import { MCPMarketplaceFeatures } from '@/components/mcp-marketplace-features'
import { PageContainer } from '@/components/page-container'
import { SupplySideCTA } from '@/components/supply-side-cta'
import {
docsPublishingQuickStartUrl,
githubUrl,
twitterUrl
} from '@/lib/config'
import { githubUrl, twitterUrl } from '@/lib/config'
import {
defaultConfig,
getCodeForDeveloperConfig
@ -117,7 +113,10 @@ export default async function TheBestDamnLandingPageEver() {
</p>
<p>
<Link href={docsPublishingQuickStartUrl} className='link'>
<Link
href='https://docs.agentic.so/publishing/quickstart'
className='link'
>
And of course, <span className='font-semibold'>MCP</span> is an
integral part of that mission. We're working on a bunch of features
designed to simplify advanced MCP use cases like bundling multiple

Wyświetl plik

@ -8,7 +8,7 @@ import { GitHubStarCounter } from '@/components/github-star-counter'
import { MCPGatewayFeatures } from '@/components/mcp-gateway-features'
import { PageContainer } from '@/components/page-container'
import { SupplySideCTA } from '@/components/supply-side-cta'
import { docsPublishingUrl, githubUrl, twitterUrl } from '@/lib/config'
import { githubUrl, twitterUrl } from '@/lib/config'
export default function PublishingMCPsPage() {
return (
@ -47,7 +47,7 @@ export default function PublishingMCPsPage() {
</div>
<p className='text-sm max-w-2xl text-center'>
<Link href={docsPublishingUrl} className='link'>
<Link href='https://docs.agentic.so/publishing' className='link'>
Deploy any MCP server or OpenAPI service to Agentic's MCP Gateway,
which handles auth, billing, rate-limiting, caching, etc. And
instantly turn your API into a paid MCP product that supports every
@ -65,7 +65,7 @@ export default function PublishingMCPsPage() {
<ExampleAgenticConfigs />
<p className='text-sm max-w-2xl text-center'>
<Link href={`${docsPublishingUrl}/config`} className='link'>
<Link href='https://docs.agentic.so/publishing/config' className='link'>
Configuring your Agentic project
</Link>{' '}
is straightforward , regardless of whether your origin is an MCP
@ -74,7 +74,7 @@ export default function PublishingMCPsPage() {
file, or fall back to using an{' '}
<span className='font-semibold'>agentic.config.json</span> file to
configure your project.{' '}
<Link href={docsPublishingUrl} className='link'>
<Link href='https://docs.agentic.so/publishing' className='link'>
Learn more
</Link>
.

Wyświetl plik

@ -5,7 +5,6 @@ import useInfiniteScroll from 'react-infinite-scroll-hook'
import { useAuthenticatedAgentic } from '@/components/agentic-provider'
import { LoadingIndicator } from '@/components/loading-indicator'
import { docsPublishingQuickStartUrl } from '@/lib/config'
import { useInfiniteQuery } from '@/lib/query-client'
export function AppProjectsList() {
@ -64,7 +63,10 @@ export function AppProjectsList() {
) : !projects.length ? (
<p>
No projects found.{' '}
<Link href={docsPublishingQuickStartUrl} className='link'>
<Link
href='https://docs.agentic.so/publishing/quickstart'
className='link'
>
Create your first project to get started.
</Link>
</p>

Wyświetl plik

@ -2,7 +2,6 @@ import Link from 'next/link'
import { HeroButton } from '@/components/hero-button'
import { Button } from '@/components/ui/button'
import { docsUrl } from '@/lib/config'
export function DemandSideCTA() {
return (
@ -14,7 +13,7 @@ export function DemandSideCTA() {
</HeroButton>
<Button variant='outline' asChild className='h-full'>
<Link href={docsUrl} className='font-mono'>
<Link href='https://docs.agentic.so' className='font-mono'>
readTheDocs();
</Link>
</Button>

Wyświetl plik

@ -1,104 +0,0 @@
import Link from 'next/link'
import { ActiveLink } from '@/components/active-link'
import { GitHubIcon } from '@/icons/github'
import { TwitterIcon } from '@/icons/twitter'
import { copyright, docsUrl, githubUrl, twitterUrl } from '@/lib/config'
export function Footer() {
return (
<footer className='w-full pt-12 pb-4 border-t flex flex-col items-center'>
<div className='container px-4 md:px-6 max-w-1200px'>
<div className='flex flex-col md:grid md:grid-cols-4 gap-8'>
<div className='flex flex-col md:items-center'>
<div className='space-y-4'>
<h3 className='text-lg font-semibold'>Site</h3>
<nav className='flex flex-col space-y-2'>
<span>
<ActiveLink href='/' className='link'>
Home
</ActiveLink>
</span>
<span>
<ActiveLink href='/marketplace' className='link'>
MCP Marketplace
</ActiveLink>
</span>
<span>
<ActiveLink href='/publishing' className='link'>
Publishing MCPs
</ActiveLink>
</span>
<span>
<ActiveLink href={docsUrl} className='link'>
Docs
</ActiveLink>
</span>
<span>
<ActiveLink href='/about' className='link'>
About
</ActiveLink>
</span>
<span>
<ActiveLink href='/legal' className='link'>
Legal
</ActiveLink>
</span>
</nav>
</div>
</div>
<div className='flex flex-col order-last md:order-none col-span-2'>
<div className='space-y-4 flex flex-col w-full'>
<h3 className='text-lg font-semibold'>TODO</h3>
<div className='grid grid-cols-[repeat(auto-fill,_minmax(10em,_1fr))] gap-y-4 gap-x-8 w-full flex-auto'>
<div className='link'>TODO</div>
</div>
</div>
</div>
<div className='flex flex-col md:items-center gap-4'>
<div className='space-y-4'>
<h3 className='text-lg font-semibold'>Social</h3>
<nav className='flex flex-col gap-4'>
<Link
href={twitterUrl}
className='flex items-center space-x-2'
target='_blank'
rel='noopener noreferrer'
>
<TwitterIcon className='h-4 w-4' />
<span>Twitter</span>
</Link>
<Link
href={githubUrl}
className='flex items-center space-x-2'
target='_blank'
rel='noopener noreferrer'
>
<GitHubIcon className='h-4 w-4' />
<span>GitHub</span>
</Link>
</nav>
</div>
</div>
</div>
<div className='mt-8 pt-8 border-t border-border text-center text-sm text-muted-foreground'>
<span>{copyright}</span>
</div>
</div>
</footer>
)
}

Wyświetl plik

@ -0,0 +1,42 @@
'use client'
import { ActiveLink } from '@/components/active-link'
import { useAgentic } from '@/components/agentic-provider'
export function DynamicFooter() {
const ctx = useAgentic()
return (
<>
{ctx?.isAuthenticated ? (
<>
<div>
<ActiveLink href='/app' className='link'>
Dashboard
</ActiveLink>
</div>
<div>
<ActiveLink href='/logout' className='link'>
Logout
</ActiveLink>
</div>
</>
) : (
<>
<div>
<ActiveLink href='/login' className='link whitespace-nowrap'>
Log in
</ActiveLink>
</div>
<div>
<ActiveLink href='/signup' className='link whitespace-nowrap'>
Sign up
</ActiveLink>
</div>
</>
)}
</>
)
}

Wyświetl plik

@ -0,0 +1,198 @@
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 { DynamicFooter } from './dynamic'
export function Footer() {
return (
<footer className='w-full pt-12 pb-4 border-t flex flex-col items-center'>
<div className='container px-4 md:px-6 max-w-1200px'>
<div className='flex flex-col md:grid md:grid-cols-4 gap-8'>
<div className='flex flex-col md:items-center'>
<div className='space-y-4'>
<h3 className='text-lg font-semibold'>Platform</h3>
<nav className='flex flex-col space-y-2'>
<div>
<ActiveLink href='/' className='link'>
Home
</ActiveLink>
</div>
<div>
<ActiveLink href='/marketplace' className='link'>
MCP Marketplace
</ActiveLink>
</div>
<div>
<ActiveLink href='/publishing' className='link'>
MCP Publishing
</ActiveLink>
</div>
<DynamicFooter />
</nav>
</div>
</div>
<div className='flex flex-col md:items-center'>
<div className='space-y-4'>
<h3 className='text-lg font-semibold'>Resources</h3>
<nav className='flex flex-col space-y-2'>
<div>
<Link href='https://docs.agentic.so' className='link'>
Docs
</Link>
</div>
<div>
<Link
href='https://docs.agentic.so/publishing'
className='link inline-block'
>
Publish your own MCP
</Link>
</div>
<div>
<Link
href='https://docs.agentic.so/publishing/guides/existing-openapi-service'
className='link'
>
OpenAPI to MCP
</Link>
</div>
<div>
<Link
href='https://docs.agentic.so/marketplace/ts-sdks/openai-chat'
className='link'
>
Agentic + OpenAI
</Link>
</div>
<div>
<Link
href='https://docs.agentic.so/marketplace/ts-sdks/ai-sdk'
className='link'
>
Agentic + Vercel AI SDK
</Link>
</div>
<div>
<Link
href='https://docs.agentic.so/marketplace/ts-sdks/langchain'
className='link'
>
Agentic + LangChain
</Link>
</div>
<div>
<Link
href='https://docs.agentic.so/marketplace/ts-sdks/llamaindex'
className='link'
>
Agentic + LlamaIndex
</Link>
</div>
<div>
<Link
href='https://docs.agentic.so/marketplace/ts-sdks/genkit'
className='link'
>
Agentic + Firebase GenKit
</Link>
</div>
<div>
<Link
href='https://docs.agentic.so/marketplace/ts-sdks/mastra'
className='link'
>
Agentic + Mastra
</Link>
</div>
</nav>
</div>
</div>
<div className='flex flex-col md:items-center'>
<div className='space-y-4'>
<h3 className='text-lg font-semibold'>Company</h3>
<nav className='flex flex-col space-y-2'>
<div>
<ActiveLink href='/about' className='link'>
About
</ActiveLink>
</div>
<div>
<ActiveLink href='/contact' className='link'>
Contact
</ActiveLink>
</div>
<div>
<ActiveLink href='/privacy-policy' className='link'>
Privacy Policy
</ActiveLink>
</div>
<div>
<ActiveLink href='/terms' className='link'>
Terms of Service
</ActiveLink>
</div>
</nav>
</div>
</div>
<div className='flex flex-col md:items-center gap-4'>
<div className='space-y-4'>
<h3 className='text-lg font-semibold'>Social</h3>
<nav className='flex flex-col gap-4'>
<Link
href={twitterUrl}
className='flex items-center space-x-2'
target='_blank'
rel='noopener noreferrer'
>
<TwitterIcon className='h-4 w-4' />
<span>Twitter</span>
</Link>
<Link
href={githubUrl}
className='flex items-center space-x-2'
target='_blank'
rel='noopener noreferrer'
>
<GitHubIcon className='h-4 w-4' />
<span>GitHub</span>
</Link>
</nav>
</div>
</div>
</div>
<div className='mt-8 pt-8 border-t border-border text-center text-sm text-muted-foreground'>
<span>{copyright}</span>
</div>
</div>
</footer>
)
}

Wyświetl plik

@ -0,0 +1,34 @@
'use client'
import { ActiveLink } from '@/components/active-link'
import { useAgentic } from '@/components/agentic-provider'
export function DynamicHeader() {
const ctx = useAgentic()
return (
<>
{ctx?.isAuthenticated ? (
<>
<ActiveLink href='/app' className='link'>
Dashboard
</ActiveLink>
<ActiveLink href='/logout' className='link'>
Logout
</ActiveLink>
</>
) : (
<>
<ActiveLink href='/login' className='link whitespace-nowrap'>
Log in
</ActiveLink>
<ActiveLink href='/signup' className='link whitespace-nowrap'>
Sign up
</ActiveLink>
</>
)}
</>
)
}

Wyświetl plik

@ -1,32 +1,24 @@
'use client'
import { useTheme } from 'next-themes'
import { ActiveLink } from '@/components/active-link'
import { useAgentic } from '@/components/agentic-provider'
import { DarkModeToggle } from '@/components/dark-mode-toggle'
import { docsUrl } from '@/lib/config'
import { cn } from '@/lib/utils'
import { DynamicHeader } from './dynamic'
import styles from './styles.module.css'
export function Header() {
// TODO: use CSS for this instead of a hook
const { resolvedTheme } = useTheme()
const ctx = useAgentic()
return (
<header className={cn(styles.header, 'shadow-sm')}>
<div className={styles.headerContent}>
<ActiveLink className={styles.logo} href='/'>
<ActiveLink className='select-none' href='/'>
<img
src={
resolvedTheme === 'dark'
? '/agentic-logo-dark.svg'
: '/agentic-logo-light.svg'
}
src='/agentic-logo-light.svg'
alt='AGENTIC'
className='w-[144px]'
className='w-[144px] dark:hidden'
/>
<img
src='/agentic-logo-dark.svg'
alt='AGENTIC'
className='w-[144px] hidden dark:block'
/>
</ActiveLink>
@ -38,31 +30,14 @@ export function Header() {
MCP Marketplace
</ActiveLink>
<ActiveLink href={docsUrl} className='link whitespace-nowrap'>
<ActiveLink
href='https://docs.agentic.so'
className='link whitespace-nowrap'
>
Docs
</ActiveLink>
{ctx?.isAuthenticated ? (
<>
<ActiveLink href='/app' className='link whitespace-nowrap'>
Dashboard
</ActiveLink>
<ActiveLink href='/logout' className='link whitespace-nowrap'>
Logout
</ActiveLink>
</>
) : (
<>
<ActiveLink href='/login' className='link whitespace-nowrap'>
Login
</ActiveLink>
<ActiveLink href='/signup' className='link whitespace-nowrap'>
Sign up
</ActiveLink>
</>
)}
<DynamicHeader />
<DarkModeToggle />
</div>

Wyświetl plik

@ -38,10 +38,6 @@
min-height: 32px;
}
.logo {
user-select: none;
}
.navHeader {
display: flex;
flex-direction: row;

Wyświetl plik

@ -12,10 +12,10 @@ import {
UserIcon
} from 'lucide-react'
import { docsPublishingUrl } from '@/lib/config'
import { Feature, type FeatureData } from './feature'
const docsPublishingUrl = 'https://docs.agentic.so/publishing'
const mcpGatewayFeatures: FeatureData[] = [
{
name: 'Auth',

Wyświetl plik

@ -6,12 +6,7 @@ import Link from 'next/link'
import { HeroButton, type HeroButtonVariant } from '@/components/hero-button'
import { Button } from '@/components/ui/button'
import { GitHubIcon } from '@/icons/github'
import {
calendarBookingUrl,
docsPublishingQuickStartUrl,
docsPublishingUrl,
githubUrl
} from '@/lib/config'
import { calendarBookingUrl, githubUrl } from '@/lib/config'
import { useAgentic } from './agentic-provider'
import { GitHubStarCounter } from './github-star-counter'
@ -31,8 +26,10 @@ export function SupplySideCTA({
<Link
href={
ctx?.isAuthenticated
? docsPublishingQuickStartUrl
: `/signup?${sanitizeSearchParams({ next: docsPublishingQuickStartUrl })}`
? 'https://docs.agentic.so/publishing/quickstart'
: `/signup?${sanitizeSearchParams({
next: 'https://docs.agentic.so/publishing/quickstart'
})}`
}
>
Quick Start
@ -50,7 +47,7 @@ export function SupplySideCTA({
</Button>
) : variant === 'docs' ? (
<Button variant='outline' asChild className='h-full py-[9px]'>
<Link href={docsPublishingUrl}>Publishing Docs</Link>
<Link href='https://docs.agentic.so/publishing'>Publishing Docs</Link>
</Button>
) : (
<Button variant='outline' asChild className='h-full py-[9px]'>

Wyświetl plik

@ -11,16 +11,13 @@ export const domain =
export const author = 'Travis Fischer'
export const authorTwitterUsername = 'transitive_bs'
export const twitterUrl = `https://x.com/${authorTwitterUsername}`
export const copyright = `© ${new Date().getFullYear()} Agentic. All rights reserved.`
export const githubUrl = 'https://github.com/transitive-bullshit/agentic'
// external urls
export const twitterUrl = `https://x.com/${authorTwitterUsername}`
export const githubUrl = 'https://github.com/transitive-bullshit/agentic'
// TODO: make an agentic-specific calendar for this
export const calendarBookingUrl = 'https://cal.com/travis-fischer/15min'
export const docsUrl = 'https://docs.agentic.so'
export const docsPublishingQuickStartUrl = `${docsUrl}/publishing/quickstart`
export const docsPublishingUrl = `${docsUrl}/publishing`
export const docsMarketplaceUrl = `${docsUrl}/marketplace`
export const discordUrl = 'https://discord.agentic.so'
export const keywords = [