Repository Public MIT
1import Link from "next/link";2import { ArrowRight } from "lucide-react";3import { ARTIFACT_TYPES, TYPE_LABELS, type ArtifactType } from "@skills/registry-core";4import { ArtifactGrid, EmptyState } from "@/components/artifact-card";5import { CodeBlock } from "@/components/code";6import { SearchTrigger } from "@/components/command-palette";7import { plural } from "@/lib/format";8import { t } from "@/lib/i18n";9import { publicCtx } from "@/lib/session";10import { listCollections } from "@/server/community";11import { facets, listArtifacts } from "@/server/registry";1213const TYPE_ROUTE: Partial<Record<ArtifactType, string>> = { skill: "/skills", "mcp-server": "/mcp-servers", agent: "/agents", workflow: "/workflows" };1415export default async function Home() {16 const ctx = await publicCtx();17 const [f, recent, collections] = await Promise.all([facets(ctx), listArtifacts(ctx, { perPage: 6, sort: "updated" }), listCollections(ctx)]);18 // "Featured verified": only artifacts whose publisher identity AND source provenance were verified. Never hand-picked numbers.19 const featured = recent.items.filter((a) => a.publisher.identityVerified && a.sourceVerified).slice(0, 3);20 const example = recent.items.find((a) => a.type === "skill" && a.latestVersion);2122 return (23 <>24 <section className="border-b border-line">25 <div className="container-page pb-16 pt-20 sm:pb-20 sm:pt-28">26 <p className="eyebrow mb-5">The Open Agent Capability Registry</p>27 <h1 className="max-w-4xl text-4xl font-semibold leading-[1.05] tracking-tight sm:text-6xl">28 Discover. Build. Publish.29 <br />30 <span className="text-muted">Extend your agents.</span>31 </h1>32 <p className="mt-6 max-w-2xl text-lg text-muted">{t.statement}</p>33 <div className="mt-9 max-w-2xl">34 <SearchTrigger large />35 </div>36 <div className="mt-6 flex flex-wrap gap-3">37 <Link href="/explore" className="btn btn-primary">Explore the registry <ArrowRight size={15} aria-hidden /></Link>38 <Link href="/docs" className="btn">Read the docs</Link>39 </div>40 <dl className="mt-12 flex flex-wrap gap-x-10 gap-y-4 border-t border-line pt-6" aria-label="Live registry counts">41 {[42 [f.totals.artifacts, "public artifact"],43 [f.totals.releases, "immutable release"],44 [f.totals.publishers, "publisher"],45 ].map(([n, label]) => (46 <div key={label as string}>47 <dd className="font-mono text-2xl text-text" data-testid={`count-${label}`}>{(n as number).toLocaleString("en-CA")}</dd>48 <dt className="text-sm text-muted">{plural(n as number, label as string).replace(/^[\d\s,.]+/, "")}</dt>49 </div>50 ))}51 </dl>52 <p className="mt-4 font-mono text-[11px] text-faint">Counted live from the registry database.</p>53 </div>54 </section>5556 <section aria-labelledby="types-h" className="container-page pt-16">57 <div className="mb-6 flex items-end justify-between gap-4">58 <div>59 <p className="eyebrow mb-2">Browse by type</p>60 <h2 id="types-h" className="text-2xl font-semibold tracking-tight">Ten typed kinds of capability</h2>61 </div>62 </div>63 <ul className="grid gap-px overflow-hidden rounded-[10px] border border-line bg-line sm:grid-cols-2 lg:grid-cols-5">64 {ARTIFACT_TYPES.map((type) => (65 <li key={type} className="bg-graphite">66 <Link href={TYPE_ROUTE[type] ?? `/explore?type=${type}`} className="group flex h-full flex-col p-4 transition-colors hover:bg-raised">67 <span className="flex items-baseline justify-between gap-2">68 <span className="text-sm font-medium text-text">{TYPE_LABELS[type].plural}</span>69 <span className="font-mono text-xs text-faint">{f.types[type] ?? 0}</span>70 </span>71 <span className="mt-1.5 text-xs leading-relaxed text-muted">{TYPE_LABELS[type].blurb}</span>72 </Link>73 </li>74 ))}75 </ul>76 </section>7778 {featured.length > 0 && (79 <section aria-labelledby="featured-h" className="container-page pt-16">80 <p className="eyebrow mb-2">Verified identity and source</p>81 <h2 id="featured-h" className="mb-6 text-2xl font-semibold tracking-tight">Featured</h2>82 <ArtifactGrid items={featured} />83 </section>84 )}8586 <section aria-labelledby="recent-h" className="container-page pt-16">87 <div className="mb-6 flex items-end justify-between gap-4">88 <div>89 <p className="eyebrow mb-2">Activity</p>90 <h2 id="recent-h" className="text-2xl font-semibold tracking-tight">Recently updated</h2>91 </div>92 <Link href="/explore" className="text-sm text-muted hover:text-text">View all <ArrowRight size={13} aria-hidden className="inline" /></Link>93 </div>94 {recent.items.length ? <ArtifactGrid items={recent.items} /> : <EmptyState title="The registry is empty.">Nothing has been published yet. No placeholder content is shown.</EmptyState>}95 </section>9697 <section aria-labelledby="install-h" className="container-page grid gap-10 pt-20 lg:grid-cols-2">98 <div>99 <p className="eyebrow mb-2">Install</p>100 <h2 id="install-h" className="text-2xl font-semibold tracking-tight">Inspect first. Then install.</h2>101 <p className="mt-3 text-muted">102 Every release is an immutable archive with a SHA-256 checksum. The CLI shows declared permissions and the destination, verifies the checksum, copies files and stops there. It never runs package scripts.103 </p>104 <ul className="mt-5 space-y-2 text-sm text-muted">105 <li>— Claude Code, OpenAI Codex, Cursor and generic Skills or MCP clients</li>106 <li>— Download, configure and execute stay three separate decisions</li>107 <li>— Version pinning, conflict detection and one-command rollback</li>108 </ul>109 <Link href="/docs" className="link mt-5 inline-block text-sm">Installation guides</Link>110 </div>111 <div className="space-y-3">112 <CodeBlock prompt label="Inspect before installing" code={`skills inspect ${example ? example.name : "@namespace/artifact"}`} />113 <CodeBlock prompt label="Install into Claude Code" code={`skills install ${example ? `${example.name}@${example.latestVersion}` : "@namespace/artifact"} --client claude-code`} />114 <CodeBlock prompt label="Use the registry from any MCP client" code={`claude mcp add --transport http skills-registry ${"https://skills.spboucher.ai"}/mcp`} />115 </div>116 </section>117118 <section aria-labelledby="collections-h" className="container-page pt-20">119 <div className="mb-6 flex items-end justify-between gap-4">120 <div>121 <p className="eyebrow mb-2">Curated</p>122 <h2 id="collections-h" className="text-2xl font-semibold tracking-tight">Research collections</h2>123 </div>124 <Link href="/collections" className="text-sm text-muted hover:text-text">All collections <ArrowRight size={13} aria-hidden className="inline" /></Link>125 </div>126 {collections.length === 0 ? (127 <EmptyState title="No collections yet." />128 ) : (129 <ul className="grid gap-4 sm:grid-cols-2 lg:grid-cols-4">130 {collections.slice(0, 8).map((c) => (131 <li key={c.slug}>132 <Link href={`/collections/${c.slug}`} className="card card-hover flex h-full flex-col p-5">133 <span className="text-sm font-medium text-text">{c.title}</span>134 <span className="mt-1.5 flex-1 text-xs leading-relaxed text-muted">{c.description}</span>135 <span className="mt-3 font-mono text-[11px] text-faint">{plural(c.item_count, "artifact")}</span>136 </Link>137 </li>138 ))}139 </ul>140 )}141 </section>142143 <section aria-labelledby="publish-h" className="container-page pt-20">144 <div className="card grid gap-8 p-8 sm:p-10 lg:grid-cols-[1.2fr_1fr]">145 <div>146 <p className="eyebrow mb-2">Open publishing</p>147 <h2 id="publish-h" className="text-2xl font-semibold tracking-tight">Publish what you build.</h2>148 <p className="mt-3 max-w-xl text-muted">149 Package a directory, validate it locally, review a dry run, and publish an immutable, checksummed release with a scoped token — from your terminal or directly from Claude Code. Preserve your upstream manifests; the registry adds a thin wrapper, not a new format.150 </p>151 <div className="mt-6 flex flex-wrap gap-3">152 <Link href="/publish" className="btn btn-primary">How to publish</Link>153 <Link href="/docs/security" className="btn">Trust & security model</Link>154 </div>155 </div>156 <CodeBlock prompt label="Publish from a terminal" code={`skills validate ./my-skill\nskills publish ./my-skill --dry-run\nskills publish ./my-skill --visibility public`} />157 </div>158 </section>159 </>160 );161}162