From 0941544e316ae95e11f3ec8dfc41dab32ffa3493 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 13 May 2026 17:47:19 +0000 Subject: [PATCH 1/3] ux: layout chrome for new routes + nav surfaces MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ten newly-added pages (bounties, leaderboard, compare, run, use-case, use-cases, collections, skill-of-the-week, bounties/new, bounties/\$id) were orphans β€” no Nav, no Footer, no branding β€” which broke every viral CTA that pointed at them. - src/components/site/SitePage.tsx: shared chrome wrapper used by every non-landing route to inject Nav + Footer with consistent vertical flow - Wraps all 10 new routes - Nav.tsx: new "Community" dropdown surfacing Skill of the Week, Use cases, Bounties, Affiliate leaderboard (with mobile sheet parity) - Footer.tsx: new Community column with same links + Discord; grid expanded to 5 columns on md+ to keep legibility --- src/components/site/Footer.tsx | 9 ++++++++- src/components/site/Nav.tsx | 9 +++++++++ src/components/site/SitePage.tsx | 22 ++++++++++++++++++++++ src/routes/bounties.$id.tsx | 3 +++ src/routes/bounties.new.tsx | 3 +++ src/routes/bounties.tsx | 3 +++ src/routes/collections.$slug.tsx | 3 +++ src/routes/compare.$pair.tsx | 3 +++ src/routes/leaderboard.tsx | 3 +++ src/routes/run.$slug.tsx | 3 +++ src/routes/skill-of-the-week.tsx | 3 +++ src/routes/use-case.$vertical.$task.tsx | 3 +++ src/routes/use-cases.tsx | 3 +++ 13 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 src/components/site/SitePage.tsx diff --git a/src/components/site/Footer.tsx b/src/components/site/Footer.tsx index d6894cb2..39a48eb0 100644 --- a/src/components/site/Footer.tsx +++ b/src/components/site/Footer.tsx @@ -23,7 +23,7 @@ export function Footer() { -
+
+ + {SIMPLE.map((l) => ( setOpen(false)} /> setOpen(false)} /> + setOpen(false)} /> setOpen(false)} />
diff --git a/src/components/site/SitePage.tsx b/src/components/site/SitePage.tsx new file mode 100644 index 00000000..111e5cd9 --- /dev/null +++ b/src/components/site/SitePage.tsx @@ -0,0 +1,22 @@ +import type { ReactNode } from "react"; +import { Nav } from "./Nav"; +import { Footer } from "./Footer"; + +/** + * Standard page chrome: Nav + main content + Footer. Use for every route + * outside the marketing landing page so users never land on an "orphan" + * screen without branding or navigation. + * + * + *
…
+ *
+ */ +export function SitePage({ children }: { children: ReactNode }) { + return ( +
+
+ ); +} diff --git a/src/routes/bounties.$id.tsx b/src/routes/bounties.$id.tsx index 7eec7526..b41972cc 100644 --- a/src/routes/bounties.$id.tsx +++ b/src/routes/bounties.$id.tsx @@ -1,4 +1,5 @@ import { createFileRoute } from "@tanstack/react-router"; +import { SitePage } from "@/components/site/SitePage"; import { useState } from "react"; import { toast } from "sonner"; import { supabaseAdmin } from "@/integrations/supabase/client.server"; @@ -61,6 +62,7 @@ function BountyDetail() { const closed = bounty.status !== "open"; return ( +
← All bounties
@@ -103,5 +105,6 @@ function BountyDetail() {

+
); } diff --git a/src/routes/bounties.new.tsx b/src/routes/bounties.new.tsx index a7693162..dd2f3e2a 100644 --- a/src/routes/bounties.new.tsx +++ b/src/routes/bounties.new.tsx @@ -1,4 +1,5 @@ import { createFileRoute, useNavigate } from "@tanstack/react-router"; +import { SitePage } from "@/components/site/SitePage"; import { useState } from "react"; import { toast } from "sonner"; import { postBounty } from "@/lib/growth/bounties.functions"; @@ -56,6 +57,7 @@ function NewBounty() { const set = (k: K, v: (typeof form)[K]) => setForm((f) => ({ ...f, [k]: v })); return ( +

Post a Skill Bounty

@@ -125,5 +127,6 @@ function NewBounty() {

+
); } diff --git a/src/routes/bounties.tsx b/src/routes/bounties.tsx index 64ee88eb..4287a219 100644 --- a/src/routes/bounties.tsx +++ b/src/routes/bounties.tsx @@ -1,5 +1,6 @@ import { createFileRoute } from "@tanstack/react-router"; import { supabaseAdmin } from "@/integrations/supabase/client.server"; +import { SitePage } from "@/components/site/SitePage"; type Bounty = { id: string; title: string; brief: string; vertical: string; @@ -29,6 +30,7 @@ export const Route = createFileRoute("/bounties")({ function BountiesPage() { const { bounties } = Route.useLoaderData(); return ( +

Skill Bounties

@@ -68,5 +70,6 @@ function BountiesPage() {

+
); } diff --git a/src/routes/collections.$slug.tsx b/src/routes/collections.$slug.tsx index 0f35ff61..289b0d0b 100644 --- a/src/routes/collections.$slug.tsx +++ b/src/routes/collections.$slug.tsx @@ -1,4 +1,5 @@ import { createFileRoute } from "@tanstack/react-router"; +import { SitePage } from "@/components/site/SitePage"; import { supabaseAdmin } from "@/integrations/supabase/client.server"; type CollectionRow = { @@ -51,6 +52,7 @@ export const Route = createFileRoute("/collections/$slug")({ function CollectionPage() { const { collection, items } = Route.useLoaderData(); return ( +
{collection.cover_emoji ?? "πŸ“¦"}
@@ -87,5 +89,6 @@ function CollectionPage() {
+
); } diff --git a/src/routes/compare.$pair.tsx b/src/routes/compare.$pair.tsx index 440fa001..c2e02434 100644 --- a/src/routes/compare.$pair.tsx +++ b/src/routes/compare.$pair.tsx @@ -1,4 +1,5 @@ import { createFileRoute } from "@tanstack/react-router"; +import { SitePage } from "@/components/site/SitePage"; import { supabaseAdmin } from "@/integrations/supabase/client.server"; // SEO landing: /compare/-vs- @@ -52,6 +53,7 @@ export const Route = createFileRoute("/compare/$pair")({ function ComparePage() { const { left, right } = Route.useLoaderData(); return ( +

{left.name ?? left.slug} vs {right.name ?? right.slug} @@ -90,6 +92,7 @@ function ComparePage() { {`![trust](/api/badges/trust/${left.slug}.svg)`}

+
); } diff --git a/src/routes/leaderboard.tsx b/src/routes/leaderboard.tsx index 222532a8..1c33f999 100644 --- a/src/routes/leaderboard.tsx +++ b/src/routes/leaderboard.tsx @@ -1,4 +1,5 @@ import { createFileRoute } from "@tanstack/react-router"; +import { SitePage } from "@/components/site/SitePage"; import { supabaseAdmin } from "@/integrations/supabase/client.server"; import { rankLeaderboard } from "@/lib/growth/bounties"; @@ -32,6 +33,7 @@ export const Route = createFileRoute("/leaderboard")({ function LeaderboardPage() { const { rows } = Route.useLoaderData(); return ( +

Affiliate Leaderboard

@@ -58,5 +60,6 @@ function LeaderboardPage() {

+
); } diff --git a/src/routes/run.$slug.tsx b/src/routes/run.$slug.tsx index 563f8820..4bf0cbd5 100644 --- a/src/routes/run.$slug.tsx +++ b/src/routes/run.$slug.tsx @@ -1,4 +1,5 @@ import { createFileRoute } from "@tanstack/react-router"; +import { SitePage } from "@/components/site/SitePage"; import { useState } from "react"; import { toast } from "sonner"; import { supabaseAdmin } from "@/integrations/supabase/client.server"; @@ -77,6 +78,7 @@ function RunPage() { }; return ( +
← {pkg.name} @@ -130,5 +132,6 @@ function RunPage() { or install locally with npx super-agent install {pkg.slug}.
+
); } diff --git a/src/routes/skill-of-the-week.tsx b/src/routes/skill-of-the-week.tsx index 467310a5..73f9627b 100644 --- a/src/routes/skill-of-the-week.tsx +++ b/src/routes/skill-of-the-week.tsx @@ -1,4 +1,5 @@ import { createFileRoute } from "@tanstack/react-router"; +import { SitePage } from "@/components/site/SitePage"; import { supabaseAdmin } from "@/integrations/supabase/client.server"; type Winner = { @@ -39,6 +40,7 @@ export const Route = createFileRoute("/skill-of-the-week")({ function SkillOfTheWeekPage() { const { current, history } = Route.useLoaderData(); return ( +

Skill of the Week

@@ -89,6 +91,7 @@ function SkillOfTheWeekPage() { )}

+
); } diff --git a/src/routes/use-case.$vertical.$task.tsx b/src/routes/use-case.$vertical.$task.tsx index 743ff52a..4bde4908 100644 --- a/src/routes/use-case.$vertical.$task.tsx +++ b/src/routes/use-case.$vertical.$task.tsx @@ -1,4 +1,5 @@ import { createFileRoute } from "@tanstack/react-router"; +import { SitePage } from "@/components/site/SitePage"; import { supabaseAdmin } from "@/integrations/supabase/client.server"; import { findUseCase } from "@/lib/seo/use-cases"; @@ -64,6 +65,7 @@ export const Route = createFileRoute("/use-case/$vertical/$task")({ function UseCasePage() { const { useCase, skills } = Route.useLoaderData(); return ( +
{useCase.vertical} @@ -128,6 +130,7 @@ function UseCasePage() {

+
); } diff --git a/src/routes/use-cases.tsx b/src/routes/use-cases.tsx index c45aa136..41866e0c 100644 --- a/src/routes/use-cases.tsx +++ b/src/routes/use-cases.tsx @@ -1,4 +1,5 @@ import { createFileRoute } from "@tanstack/react-router"; +import { SitePage } from "@/components/site/SitePage"; import { USE_CASES } from "@/lib/seo/use-cases"; export const Route = createFileRoute("/use-cases")({ @@ -16,6 +17,7 @@ function UseCasesIndex() { for (const u of USE_CASES) (byVertical[u.vertical] ||= []).push(u); return ( +

Use cases

@@ -35,5 +37,6 @@ function UseCasesIndex() { ))}

+
); } From f95873aed7d18765c74df6f22c89c12ebf84288e Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 13 May 2026 17:50:15 +0000 Subject: [PATCH 2/3] ui: lucide icons, runtime cards, SVG watermark, theme toggle MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replaces amateur signals with professional equivalents commonly used by enterprise SaaS surfaces (Vercel/Stripe/Linear-style cards, lucide glyphs, real SVG patterns). - index.tsx WhatIsThis: emoji icons β†’ lucide (ShieldCheck, BadgeCheck, Landmark, Plug) inside a rounded primary-tinted square - index.tsx Hero trust metrics: matching lucide icons above each counter (BadgeCheck, Landmark, ShieldAlert, Clock) - index.tsx Logos section: replaced text-mono partner marquee with a six-card "Works with" grid (Claude Code, Cursor, ChatGPT, Continue, Cline, Any MCP client). Avoids trademarked-logo issues and conveys the same compatibility claim more credibly. - run.\$slug.tsx: rotated-div watermark replaced with an SVG repeating pattern (rotate -22Β°, low opacity, scales to any panel size without aliasing) - ThemeToggle component (lucide Sun/Moon) added to desktop Nav next to the GitHub button; persists choice in localStorage - styles.css: scroll-behavior: smooth on html (reduce-motion users are already handled below) --- src/components/site/Nav.tsx | 2 + src/components/site/ThemeToggle.tsx | 44 +++++++++++++++++++++ src/routes/index.tsx | 61 ++++++++++++++++++----------- src/routes/run.$slug.tsx | 46 ++++++++++++++++------ src/styles.css | 2 +- 5 files changed, 119 insertions(+), 36 deletions(-) create mode 100644 src/components/site/ThemeToggle.tsx diff --git a/src/components/site/Nav.tsx b/src/components/site/Nav.tsx index ce0b5a4f..3468bec6 100644 --- a/src/components/site/Nav.tsx +++ b/src/components/site/Nav.tsx @@ -2,6 +2,7 @@ import { Link } from "@tanstack/react-router"; import { useState } from "react"; import { Menu, Github, ChevronDown } from "lucide-react"; import { Logo } from "./Logo"; +import { ThemeToggle } from "./ThemeToggle"; import { Sheet, SheetContent, SheetTrigger, SheetTitle, SheetHeader } from "@/components/ui/sheet"; import { DropdownMenu, @@ -104,6 +105,7 @@ export function Nav() {
+ ("light"); + + useEffect(() => { + setMode(readMode()); + }, []); + + const toggle = () => { + const next: Mode = mode === "dark" ? "light" : "dark"; + setMode(next); + applyMode(next); + }; + + const Icon = mode === "dark" ? Sun : Moon; + + return ( + + ); +} diff --git a/src/routes/index.tsx b/src/routes/index.tsx index 3c958bf8..6cf3395a 100644 --- a/src/routes/index.tsx +++ b/src/routes/index.tsx @@ -1,5 +1,6 @@ import { createFileRoute, Link } from "@tanstack/react-router"; import { lazy, Suspense, useEffect, useMemo, useRef, useState } from "react"; +import { ShieldCheck, BadgeCheck, Landmark, Plug, ShieldAlert, Layers, Activity, Clock } from "lucide-react"; import { ClientOnly } from "@/components/site/ClientOnly"; import { Nav } from "@/components/site/Nav"; import { Footer } from "@/components/site/Footer"; @@ -187,14 +188,15 @@ function Hero() { {/* Trust metrics β€” proof of the moat, not vanity counts */}
{[ - { v: 100, suffix: "%", label: "Signed at release" }, - { v: 5, suffix: "", label: "Regulated verticals" }, - { v: 7, suffix: "", label: "Injection attack classes blocked" }, - { v: 30, suffix: "s", label: "MCP setup" }, + { Icon: BadgeCheck, v: 100, suffix: "%", label: "Signed at release" }, + { Icon: Landmark, v: 5, suffix: "", label: "Regulated verticals" }, + { Icon: ShieldAlert, v: 7, suffix: "", label: "Injection classes blocked" }, + { Icon: Clock, v: 30, suffix: "s", label: "MCP setup" }, ].map((m) => (
-
- + +
+
{m.label}
@@ -208,25 +210,25 @@ function Hero() { function WhatIsThis() { const items = [ { - icon: "πŸ›‘", + Icon: ShieldCheck, title: "Adversarial harness", plain: "Proven robust", body: "Every skill is tested against prompt injection, jailbreaks, exfiltration, blast-radius and policy bypass before it can publish. Verticalized cases for OWASP LLM, FINRA, HIPAA Safe Harbor, PCI-DSS and SRE.", }, { - icon: "πŸ”", + Icon: BadgeCheck, title: "Signed Trust Score", plain: "Cryptographic + transparent", body: "Releases are Ed25519-signed and air-gap verifiable. Trust Score is a public, weighted formula over adversarial robustness, real-world success, signed releases and age β€” embed the badge in your README.", }, { - icon: "πŸ›", + Icon: Landmark, title: "Verticalized Souls", plain: "Regulator-aware personas", body: "Fintech compliance officer, HIPAA-aware clinical liaison, SOC 2 auditor, Kubernetes SRE β€” Souls that cite the rule before the recommendation and refuse the unsafe defaults.", }, { - icon: "πŸ”Œ", + Icon: Plug, title: "One MCP endpoint", plain: "Plug into any agent", body: "Claude, Cursor, ChatGPT, Continue, Cline. No SDK, no glue code β€” one URL or one `npx super-agent install`. Skills compose into Playbooks at runtime with guardrail middleware.", @@ -253,7 +255,9 @@ function WhatIsThis() { key={it.title} className="rounded-2xl border border-border bg-background p-6 transition-all hover:border-primary/40 hover:shadow-elevated" > -
{it.icon}
+
+ +

{it.title}

{it.plain}

{it.body}

@@ -270,24 +274,37 @@ function WhatIsThis() { ); } -const PARTNERS = ["CLAUDE", "CURSOR", "CODEX", "OPENCLAW", "HERMES", "GROK", "LANGCHAIN", "REPLIT"]; +// Capability claims framed as "works with X" β€” avoids partner-logo trademark +// issues that come with using third-party marks without a brand-use agreement. +const RUNTIMES = [ + { name: "Claude Code", desc: "MCP" }, + { name: "Cursor", desc: "MCP" }, + { name: "ChatGPT", desc: "MCP / GPTs" }, + { name: "Continue", desc: "MCP" }, + { name: "Cline", desc: "MCP" }, + { name: "Any MCP client", desc: "stdio Β· http" }, +]; function Logos() { return ( -
+

- Compatible with every major agent runtime + One endpoint. Every major agent runtime.

-
-
- {[...PARTNERS, ...PARTNERS].map((p, i) => ( - - {p} +
    + {RUNTIMES.map((r) => ( +
  • + {r.name} + + {r.desc} - ))} -
-
+ + ))} +
); diff --git a/src/routes/run.$slug.tsx b/src/routes/run.$slug.tsx index 4bf0cbd5..62abf929 100644 --- a/src/routes/run.$slug.tsx +++ b/src/routes/run.$slug.tsx @@ -101,22 +101,42 @@ function RunPage() { )} {sharedRun && ( -
-
)} diff --git a/src/styles.css b/src/styles.css index 6b7e6d9e..ef5d0b31 100644 --- a/src/styles.css +++ b/src/styles.css @@ -152,7 +152,7 @@ @layer base { * { border-color: var(--color-border); } - html { -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility; } + html { -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility; scroll-behavior: smooth; } body { background-color: var(--color-background); color: var(--color-foreground); From 71b00ab32bff28879c0183cf7fd3dc6c742d85be Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 13 May 2026 17:56:38 +0000 Subject: [PATCH 3/3] ui: empty states, loaders, mobile, forms, lineage, tips, og-image MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes the remaining UI gaps surfaced by the audit. Empty + loading states - src/components/site/EmptyState.tsx: shared dashed-border card with primary-tinted icon, title, body and optional CTA - bounties.tsx, leaderboard.tsx, use-case.\$vertical.\$task.tsx, skill-of-the-week.tsx: replaced bare text fallbacks with EmptyState (Trophy / Users / Sparkles / Crown) and a one-click CTA each - run.\$slug.tsx: spinner inside primary button while running, plus a skeleton block previewing prompt + output panels so the user never stares at a frozen form Mobile - leaderboard.tsx + compare.\$pair.tsx: tables now sit in overflow-x-auto wrappers with min-w-[520px] so they scroll instead of breaking the viewport below ~520px Forms - bounties.new.tsx rebuilt with shadcn Label/Input/Textarea, helper hints under each label, a hint-rich vertical