'use client'; import { useEffect, useState } from 'react'; import Link from 'next/link'; import { ShieldCheck, GitFork, Activity } from 'lucide-react'; import { apiFetch } from '@/lib/api'; import { cn } from '@/lib/cn'; import { Logo } from '@/components/logo'; import { Input } from '@/components/input'; interface Template { id: string; slug: string; title: string; shortDescription: string; category: string; verified: boolean; forkCount: number; activeDeployments: number; ownerName: string | null; ownerOrgName: string | null; createdAt: string; } type Sort = 'trending' | 'top' | 'newest'; export default function TemplatesMarketplace() { const [templates, setTemplates] = useState(null); const [categories, setCategories] = useState([]); const [sort, setSort] = useState('trending'); const [category, setCategory] = useState(''); const [search, setSearch] = useState(''); useEffect(() => { const params = new URLSearchParams({ sort }); if (category) params.set('category', category); apiFetch<{ templates: Template[]; categories: string[] }>(`/v1/templates?${params}`).then((r) => { setTemplates(r.templates); setCategories(r.categories); }); }, [sort, category]); const visible = templates?.filter((t) => search ? t.title.toLowerCase().includes(search.toLowerCase()) || t.shortDescription.toLowerCase().includes(search.toLowerCase()) : true, ); return (
/ templates
Marketplace

MCP server templates

Pre-built MCP servers from the community. Fork in one click — your own container, your own credentials, fully isolated. The template author never sees your data.

{(['trending', 'top', 'newest'] as Sort[]).map((s) => ( ))}
setSearch(e.target.value)} placeholder="Search…" className="w-60" />
{!visible && (

Loading…

)} {visible && visible.length === 0 && (

No templates yet.

Build a server you're proud of and click Publish as template{' '} on its detail page.

)} {visible && visible.length > 0 && (
{visible.map((t) => (

{t.title}

{t.verified && ( verified )}
{t.category}

{t.shortDescription}

{t.forkCount} {t.activeDeployments}
by {t.ownerName ?? t.ownerOrgName ?? 'anonymous'}
))}
)}
); }