diff --git a/.claude/CLAUDE.md b/.claude/CLAUDE.md index 23aa980..5710473 100644 --- a/.claude/CLAUDE.md +++ b/.claude/CLAUDE.md @@ -82,16 +82,16 @@ scripts/generate-*.js # Build-time generation scripts scripts/validate-skills.js # Structural validation (CI) src/ # Astro site source data/skills.ts # Build-time skill loader - data/constants.ts # Static data (API endpoints, frameworks) + data/constants.ts # Static data (frameworks list) data/site.ts # Site URL and base path config layouts/BaseLayout.astro # HTML shell, meta tags, JSON-LD layouts/SiteLayout.astro # Shared header/nav/footer for main pages components/BrowseTab.tsx # Preact island: search + skill grid - components/ApiTab.tsx # Preact island: API reference + components/ApiTab.tsx # Preact island: access/endpoints reference components/SkillHeader.tsx # Preact island: skill detail header pages/index.astro # Browse page pages/how-it-works/ # How it works page (fully static) - pages/api/ # API reference page + pages/access/ # Access reference page (real endpoints) pages/skills/[slug]/ # Dynamic skill pages (pre-rendered) pages/skills/[slug].md.ts # Raw .md endpoint per skill pages/llms.txt.ts # Skills index for agents diff --git a/src/components/ApiTab.tsx b/src/components/ApiTab.tsx index 6eaff6e..8e9e7a6 100644 --- a/src/components/ApiTab.tsx +++ b/src/components/ApiTab.tsx @@ -1,5 +1,46 @@ -import { useState } from "preact/hooks"; -import { API_ENDPOINTS, SANS_FONT } from "../data/constants"; +import { SANS_FONT } from "../data/constants"; +import { BASE_PATH, SITE_URL } from "../data/site"; +import CopyButton from "./CopyButton"; + +const RAW_BASE = "https://raw.githubusercontent.com/dfinity/icskills/main/skills"; + +const REAL_ENDPOINTS = [ + { + label: "Single skill (markdown)", + url: `${SITE_URL}/skills/ckbtc.md`, + curl: `curl -sL ${SITE_URL}/skills/ckbtc.md`, + desc: "Raw SKILL.md for one skill. Drop it straight into agent context.", + contentType: "text/markdown", + }, + { + label: "Single skill (GitHub raw)", + url: `${RAW_BASE}/ckbtc/SKILL.md`, + curl: `curl -sL ${RAW_BASE}/ckbtc/SKILL.md`, + desc: "Same content via GitHub raw URLs. Works without the site.", + contentType: "text/plain", + }, + { + label: "Skill index", + url: `${SITE_URL}/llms.txt`, + curl: `curl -sL ${SITE_URL}/llms.txt`, + desc: "Short index with links to every skill. Follows the llms.txt convention.", + contentType: "text/plain", + }, + { + label: "All skills (full)", + url: `${SITE_URL}/llms-full.txt`, + curl: `curl -sL ${SITE_URL}/llms-full.txt`, + desc: "Every skill concatenated into one file. For full context injection.", + contentType: "text/plain", + }, + { + label: "Agent discovery", + url: `${SITE_URL}/.well-known/agent.json`, + curl: `curl -sL ${SITE_URL}/.well-known/agent.json`, + desc: "Machine-readable manifest. Lists all skills and endpoint URLs.", + contentType: "application/json", + }, +]; function TerminalHeader({ title }: { title: string }) { return ( @@ -17,9 +58,7 @@ function TerminalHeader({ title }: { title: string }) { ); } -export default function ApiTab() { - const [expandedEndpoint, setExpandedEndpoint] = useState(null); - +export default function AccessTab() { return (
@@ -27,74 +66,65 @@ export default function ApiTab() { fontSize: "clamp(18px, 3vw, 26px)", fontWeight: 700, color: "var(--text-primary)", letterSpacing: "-0.5px", lineHeight: 1.4, margin: "0 0 12px 0", }}> - REST API. No auth. No keys. + Get skills into your agent.

- Base URL: https://dfinity.github.io/icskills/api/v1 + No auth. No keys. Every skill is a static file you can fetch directly.

- {/* Collapsible endpoints */} + {/* Real endpoints */}
- {API_ENDPOINTS.map((endpoint, i) => ( -
( +
-
setExpandedEndpoint(expandedEndpoint === i ? null : i)} - onKeyDown={(e) => { if (e.key === "Enter" || e.key === " ") { e.preventDefault(); setExpandedEndpoint(expandedEndpoint === i ? null : i); } }} - style={{ - padding: "14px 20px", - background: expandedEndpoint === i ? "var(--bg-input)" : "var(--bg-card-subtle)", - borderBottom: expandedEndpoint === i ? "1px solid var(--border-subtle)" : "none", - display: "flex", alignItems: "center", gap: "12px", - cursor: "pointer", transition: "background 0.15s", - }} - > +
{endpoint.method} - {endpoint.path} - {endpoint.desc} + }}>GET +
+
+ {ep.label} +
+
+ {ep.desc} +
+
{"\u25BE"} + fontSize: "9px", padding: "2px 8px", + background: `rgba(var(--accent-rgb),0.08)`, + border: `1px solid rgba(var(--accent-rgb),0.15)`, + borderRadius: "3px", color: "var(--accent-text)", + textTransform: "uppercase", letterSpacing: "1px", + whiteSpace: "nowrap", + }}>{ep.contentType} +
+
+ {ep.curl} +
- {expandedEndpoint === i && ( -
-
Response
-
{endpoint.response}
-
- )}
))}
@@ -118,14 +148,14 @@ export default function ApiTab() { color: "var(--text-tertiary)", margin: 0, whiteSpace: "pre-wrap", }}> -# Get a skill as JSON{"\n"} -curl{" dfinity.github.io/icskills/api/v1/skills/ckbtc\n\n"} -# Get raw markdown for agent context{"\n"} -curl{" dfinity.github.io/icskills/api/v1/skills/ckbtc/raw\n\n"} -# Search for a skill{"\n"} -curl{" dfinity.github.io/icskills/api/v1/skills/search?q=token\n\n"} -# Get multiple at once{"\n"} -curl{' -X POST dfinity.github.io/icskills/api/v1/skills/batch \\\n -d \'{"ids":["ckbtc","icrc-ledger","wallet"]}\''} +{"# Fetch a skill and paste into your agent"}{"\n"} +curl{` -sL ${RAW_BASE}/ckbtc/SKILL.md\n\n`} +{"# Get the skill as a served .md file"}{"\n"} +curl{` -sL ${SITE_URL}/skills/ckbtc.md\n\n`} +{"# Get the full skill index"}{"\n"} +curl{` -sL ${SITE_URL}/llms.txt\n\n`} +{"# All skills in one file (for full context injection)"}{"\n"} +curl{` -sL ${SITE_URL}/llms-full.txt`}
@@ -134,9 +164,9 @@ export default function ApiTab() { display: "grid", gridTemplateColumns: "repeat(3, 1fr)", gap: "8px", }}> {[ - { title: "No auth needed", desc: "Open API. No keys, no signup, no rate limits for normal use." }, - { title: "JSON + Markdown", desc: "Structured JSON for programmatic use. Raw markdown for context injection." }, - { title: "Always current", desc: "Skills update when icp-cli or canister IDs change. Versioned." }, + { title: "No auth needed", desc: "Open access. No keys, no signup. Every URL returns content directly." }, + { title: "Plain markdown", desc: "Skills are markdown files. Paste into any agent context, rules file, or system prompt." }, + { title: "Always current", desc: "Skills update when canister IDs or APIs change. Versioned in frontmatter." }, ].map((note) => (
{[ { val: skills.length, label: "Skills" }, - { val: API_ENDPOINTS.length, label: "API Routes" }, { val: TOTAL_ENDPOINTS, label: "Operations" }, + { val: "5", label: "Endpoints" }, { val: "0", label: "Hallucinations" }, ].map(({ val, label }) => (
diff --git a/src/data/constants.ts b/src/data/constants.ts index fb3874d..ed5f75a 100644 --- a/src/data/constants.ts +++ b/src/data/constants.ts @@ -2,113 +2,6 @@ export const SANS_FONT = "'Inter', system-ui, sans-serif"; -export const API_ENDPOINTS = [ - { - method: "GET", - path: "/skills", - desc: "All skills, with metadata.", - response: `{ - "skills": [ - { - "id": "ckbtc", - "name": "ckBTC Integration", - "version": "2.1.0", - "category": "defi", - "dependencies": ["icrc-ledger", "wallet"], - "updated": "2026-02-24" - }, - ... - ] -}`, - }, - { - method: "GET", - path: "/skills/{id}", - desc: "Full skill. This is the main one.", - response: `{ - "id": "ckbtc", - "version": "2.1.0", - "what": "ckBTC is chain-key Bitcoin on the IC...", - "prerequisites": { - "icp-cli": ">=0.1.0", - "language": ["motoko", "rust"], - "skills": ["icrc-ledger", "wallet"] - }, - "pitfalls": [ - "DO NOT use the old minter canister ID", - "Fee is 10 satoshis, not 0", - "Must use subaccounts for user deposits" - ], - "steps": [...], - "verification": [ - { - "run": "icp canister call ckbtc_ledger icrc1_balance_of ...", - "expect": "(nat)" - } - ] -}`, - }, - { - method: "GET", - path: "/skills/{id}/raw", - desc: "Raw SKILL.md. Drop it straight into agent context.", - response: `# ckBTC Integration -## SKILL.md v2.1.0 - -## What this is -ckBTC is chain-key Bitcoin... - -## Prerequisites -- icp-cli >= 0.1.0 -... - -## \u26A0 Agent Mistakes -- DO NOT use the old minter canister ID -...`, - }, - { - method: "GET", - path: "/skills/{id}/deps", - desc: "Dependency tree. What else the agent needs to read first.", - response: `{ - "skill": "ckbtc", - "requires": ["icrc-ledger", "wallet"], - "tree": { - "icrc-ledger": { "requires": [] }, - "wallet": { "requires": [] } - } -}`, - }, - { - method: "GET", - path: "/skills/search?q={query}", - desc: "Search. For when the agent knows the task but not the skill name.", - response: `{ - "query": "bitcoin", - "results": [ - { "id": "ckbtc", "name": "ckBTC Integration", "relevance": 0.97 }, - { "id": "evm-rpc", "name": "EVM RPC Integration", "relevance": 0.31 } - ] -}`, - }, - { - method: "POST", - path: "/skills/batch", - desc: "Multiple skills in one call. Send an array of IDs.", - response: `// Request body: -{ "ids": ["ckbtc", "icrc-ledger", "wallet"] } - -// Response: -{ - "skills": [ - { "id": "ckbtc", "version": "2.1.0", ... }, - { "id": "icrc-ledger", "version": "2.3.0", ... }, - { "id": "wallet", "version": "1.4.0", ... } - ] -}`, - }, -]; - export const FRAMEWORKS = [ { name: "Claude", note: "Skills as context", color: "#D97757" }, { name: "ChatGPT", note: "Function calling", color: "#10a37f" }, @@ -119,7 +12,7 @@ export const FRAMEWORKS = [ { name: "Claude Code", note: "SKILL.md files", color: "#D97757" }, { name: "OpenCode", note: "Remote instructions", color: "#00DC82" }, { name: "OpenClaw", note: "Skills marketplace", color: "#EF4444" }, - { name: "Your Agent", note: "REST API", color: "#fbbf24" }, + { name: "Your Agent", note: "curl + paste", color: "#fbbf24" }, ]; export const FW_LIGHT_COLORS: Record = { diff --git a/src/layouts/SiteLayout.astro b/src/layouts/SiteLayout.astro index 1fbd0c7..02494b5 100644 --- a/src/layouts/SiteLayout.astro +++ b/src/layouts/SiteLayout.astro @@ -10,7 +10,7 @@ interface Props { canonicalUrl?: string; ogTitle?: string; ogDescription?: string; - activeTab: "browse" | "how-it-works" | "api"; + activeTab: "browse" | "how-it-works" | "access"; maxWidth?: string; } @@ -27,7 +27,7 @@ const { const tabs = [ { id: "browse", label: "browse", href: `${BASE_PATH}/` }, { id: "how-it-works", label: "how it works", href: `${BASE_PATH}/how-it-works/` }, - { id: "api", label: "api", href: `${BASE_PATH}/api/` }, + { id: "access", label: "access", href: `${BASE_PATH}/access/` }, ] as const; --- diff --git a/src/pages/access/index.astro b/src/pages/access/index.astro new file mode 100644 index 0000000..a9e7d1f --- /dev/null +++ b/src/pages/access/index.astro @@ -0,0 +1,14 @@ +--- +import SiteLayout from "../../layouts/SiteLayout.astro"; +import AccessTab from "../../components/ApiTab"; +--- + + + + diff --git a/src/pages/api/index.astro b/src/pages/api/index.astro deleted file mode 100644 index d86dcae..0000000 --- a/src/pages/api/index.astro +++ /dev/null @@ -1,14 +0,0 @@ ---- -import SiteLayout from "../../layouts/SiteLayout.astro"; -import ApiTab from "../../components/ApiTab"; ---- - - - -