buildmymcpserver/apps/web/app/templates/page.tsx

13 lines
587 B
TypeScript
Raw Normal View History

import { fetchPublicTemplates } from '@/lib/templates-server';
import { TemplatesBrowser } from './templates-browser';
feat(marketplace): template publish + fork + voting/ranking + admin moderation What this enables: - A user builds an MCP server. If others would benefit, they click 'Publish as template' on their server detail page. The spec + pre-rendered TypeScript snapshot is preserved. - Visitors browse /templates, filter by category, sort by trending/top/newest. Each template card shows fork count + active deployment count as natural manipulation-resistant popularity signal. - /templates/[slug] shows the full plan: tool list with input schemas, required-credential explanations (with 'how to get one' deep links), and a collapsible code preview so users can audit before forking. - Fork is one click → /servers/new?template=slug. The wizard skips Step 1 and pre-fills Step 2 with the template's parsed spec. Forker only fills in their own credentials. mcp_servers.template_id is recorded; template.fork_count is bumped atomically. Each fork gets its own isolated container with its own port, its own AES-256 secrets — the template author has zero visibility into the fork's traffic or data. - Admin /admin/templates moderation: verify quality templates (shows shield badge in marketplace), hide low-effort ones, takedown anything malicious. Takedowns cascade-pause every fork container — owners must re-deploy. Why template+fork instead of shared-container: - Shared containers would mean the publisher's quota + their secrets + their logs are exposed to forkers. Bad ergonomics, bad security, bad ownership. - Templates/forks decouple the spec (shared, vouched-for) from the runtime (isolated per user). Network-effect moat without the trust collapse. Why no 5-star voting in v1: - Manipulation-anfällig, empty lists without adoption. We use fork count + active deploys + verified badge. Trending algorithm: score = (activeDeploys * 3 + forks) / sqrt(ageDays + 1) Real signal, no brigading attack surface. Backend: - New schema: templates table (16 cols incl. tools_schema, generated_code, required_secrets, allowedDomains, status enum, verified, fork_count). - mcp_servers.template_id FK + idx for fork lookup. - @bmm/types: SpecEdit unchanged, CreateServerInput accepts optional templateId. - preview-cache.ts: new cachePrebuiltCode/loadPrebuiltCode for storing the template's full rendered server.ts alongside the spec. Generator worker detects this and skips the render step — uses the audited pre-built code verbatim. Banned-pattern re-scan at publish time. - routes/templates.ts: 5 public/auth routes + 2 admin routes. Banned-pattern re-scan before publish. Slug auto-uniqued. forkCount atomic-increment via SQL. UI: - /templates marketplace with trending/top/newest tabs, category filter, search. Cards show forks + live count + author + verified badge. - /templates/[slug] full detail with tools, credentials-with-hints, expandable code preview, fork CTA, ownership + stats sidebar, 'forking is safe' explainer. - /servers/new?template=slug — wizard auto-jumps to Step 2 with template spec pre-filled, fork banner at top with link back to template. - /servers/[id] new Publish tab with title, category, descriptions, per-secret hint fields (description + howToGetUrl per UPPER_SNAKE_CASE key). - /admin/templates moderation with verify/hide/takedown actions. - Marketing nav now includes /templates. Verified end-to-end: - Published Echo Demo Template from marco@test.local's live server - Marketplace lists it correctly with stats - Detail page renders with all sections - Fork CTA navigates to wizard with ?template= param - Wizard skips Step 1, shows fork banner, pre-fills spec - Build succeeds in ~10s (cached spec + prebuilt code path skips Claude AND render), container live on :4109 with proper OAuth 401 → token → 200 flow - DB: templates.fork_count=1, activeDeployments=1, mcp_servers.template_id populated on the fork - /admin/templates shows the new template with verify/hide/takedown controls
2026-05-19 23:22:35 +02:00
// Server component: fetch the default (all/trending) template list at render
// time so the marketplace grid is present in the initial HTML for crawlers.
// All interactivity (search, filters, scope) lives in TemplatesBrowser.
export const revalidate = 300;
feat(marketplace): template publish + fork + voting/ranking + admin moderation What this enables: - A user builds an MCP server. If others would benefit, they click 'Publish as template' on their server detail page. The spec + pre-rendered TypeScript snapshot is preserved. - Visitors browse /templates, filter by category, sort by trending/top/newest. Each template card shows fork count + active deployment count as natural manipulation-resistant popularity signal. - /templates/[slug] shows the full plan: tool list with input schemas, required-credential explanations (with 'how to get one' deep links), and a collapsible code preview so users can audit before forking. - Fork is one click → /servers/new?template=slug. The wizard skips Step 1 and pre-fills Step 2 with the template's parsed spec. Forker only fills in their own credentials. mcp_servers.template_id is recorded; template.fork_count is bumped atomically. Each fork gets its own isolated container with its own port, its own AES-256 secrets — the template author has zero visibility into the fork's traffic or data. - Admin /admin/templates moderation: verify quality templates (shows shield badge in marketplace), hide low-effort ones, takedown anything malicious. Takedowns cascade-pause every fork container — owners must re-deploy. Why template+fork instead of shared-container: - Shared containers would mean the publisher's quota + their secrets + their logs are exposed to forkers. Bad ergonomics, bad security, bad ownership. - Templates/forks decouple the spec (shared, vouched-for) from the runtime (isolated per user). Network-effect moat without the trust collapse. Why no 5-star voting in v1: - Manipulation-anfällig, empty lists without adoption. We use fork count + active deploys + verified badge. Trending algorithm: score = (activeDeploys * 3 + forks) / sqrt(ageDays + 1) Real signal, no brigading attack surface. Backend: - New schema: templates table (16 cols incl. tools_schema, generated_code, required_secrets, allowedDomains, status enum, verified, fork_count). - mcp_servers.template_id FK + idx for fork lookup. - @bmm/types: SpecEdit unchanged, CreateServerInput accepts optional templateId. - preview-cache.ts: new cachePrebuiltCode/loadPrebuiltCode for storing the template's full rendered server.ts alongside the spec. Generator worker detects this and skips the render step — uses the audited pre-built code verbatim. Banned-pattern re-scan at publish time. - routes/templates.ts: 5 public/auth routes + 2 admin routes. Banned-pattern re-scan before publish. Slug auto-uniqued. forkCount atomic-increment via SQL. UI: - /templates marketplace with trending/top/newest tabs, category filter, search. Cards show forks + live count + author + verified badge. - /templates/[slug] full detail with tools, credentials-with-hints, expandable code preview, fork CTA, ownership + stats sidebar, 'forking is safe' explainer. - /servers/new?template=slug — wizard auto-jumps to Step 2 with template spec pre-filled, fork banner at top with link back to template. - /servers/[id] new Publish tab with title, category, descriptions, per-secret hint fields (description + howToGetUrl per UPPER_SNAKE_CASE key). - /admin/templates moderation with verify/hide/takedown actions. - Marketing nav now includes /templates. Verified end-to-end: - Published Echo Demo Template from marco@test.local's live server - Marketplace lists it correctly with stats - Detail page renders with all sections - Fork CTA navigates to wizard with ?template= param - Wizard skips Step 1, shows fork banner, pre-fills spec - Build succeeds in ~10s (cached spec + prebuilt code path skips Claude AND render), container live on :4109 with proper OAuth 401 → token → 200 flow - DB: templates.fork_count=1, activeDeployments=1, mcp_servers.template_id populated on the fork - /admin/templates shows the new template with verify/hide/takedown controls
2026-05-19 23:22:35 +02:00
export default async function TemplatesPage() {
const { templates, categories } = await fetchPublicTemplates();
return <TemplatesBrowser initialTemplates={templates} initialCategories={categories} />;
feat(marketplace): dashboard nav link + My-templates filter The logged-in user can now reach the marketplace and filter to their own templates. Dashboard nav: - Added 'Marketplace' item (Overview · Servers · Marketplace · Audit · Settings). /templates page — login-aware: - Detects session via /v1/auth/me. Logged-in users get a 'Dashboard' + '+ New server' header instead of 'Home' + 'Start building'. - New [All templates | My templates] scope toggle, shown only when logged in. - 'My templates' loads GET /v1/templates/mine and shows EVERY status the user owns (public / hidden / draft / takedown) with a colored status badge on each card — so a template you unshared doesn't appear to have vanished. - Sort tabs (trending/top/newest) hide in 'mine' scope — meaningless for a handful of own templates. Category filter + search still apply (client-side). - Takedown cards link to the source server's Publish tab instead of the detail route (which 410s); everything else opens the detail page. Backend: - GET /v1/templates/mine (requireAuth) — all own templates, any status, registered before /:slug so the static route always wins the match. - GET /v1/templates/:slug — now does an optional session check: the OWNER can view their own hidden/draft template (so a 'My templates' card click never dead-ends in a 404). takedown stays 410 for everyone, owner included — that's an admin decision, not the owner's to reverse. Detail page: - Fork CTA is gated on status === 'public'. For a non-public template the owner sees an amber 'not forkable — re-share from the Publish tab' notice plus a 'Manage in server' link, instead of a Fork button that would fail silently. Verified: - GET /v1/templates/mine → marco's 1 template; 401 without auth - Owner GET of a hidden template → 200 status:hidden; anon → 404 - Dashboard nav shows Marketplace (screenshot) - /templates 'My templates' toggle → only own template, public badge, sort tabs hidden (screenshot)
2026-05-20 17:18:58 +02:00
}