Skip to content

Commit 351e6c3

Browse files
authored
refactor: replace npx-first onboarding with agent-native fetch flow (#92)
Agents are always online — they don't need CLI installs. Rewrite the entire onboarding story around WebFetch: llms.txt tells agents what to do, humans just copy one prompt or drop an AGENTS.md into their repo. Key changes: - llms.txt: pure agent instructions (fetch index, fetch skills, prefer skills over general knowledge) — no npx, no skills listing - Get Started: three tiers — paste prompt, add AGENTS.md, use CLI - Browse: single hero CTA button that copies the agent prompt - Skill pages: use SiteLayout for consistent header, remove SkillHeader - New /AGENTS.md endpoint: downloadable agent instructions file - Remove search from browse page (agents search via index.json) - Remove fetch URLs from skill cards (humans don't need them) - Mobile overflow fixes across all pages
1 parent f6fa8d0 commit 351e6c3

12 files changed

Lines changed: 279 additions & 367 deletions

File tree

src/components/BrowseTab.tsx

Lines changed: 42 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ interface Props {
1010

1111
export default function BrowseTab({ skills }: Props) {
1212
const [activeCategory, setActiveCategory] = useState("All");
13-
const [searchQuery, setSearchQuery] = useState("");
13+
const [copied, setCopied] = useState(false);
1414
const [origin, setOrigin] = useState("");
1515
useEffect(() => { setOrigin(window.location.origin); }, []);
1616

@@ -19,13 +19,13 @@ export default function BrowseTab({ skills }: Props) {
1919
[skills]
2020
);
2121
const filtered = useMemo(() => {
22-
const query = searchQuery.toLowerCase();
2322
return skills.filter((s) => {
24-
const matchCat = activeCategory === "All" || s.category === activeCategory;
25-
const matchSearch = s.title.toLowerCase().includes(query) || s.description.toLowerCase().includes(query);
26-
return matchCat && matchSearch;
23+
return activeCategory === "All" || s.category === activeCategory;
2724
});
28-
}, [searchQuery, activeCategory, skills]);
25+
}, [activeCategory, skills]);
26+
27+
const siteOrigin = origin || "https://skills.internetcomputer.org";
28+
const prompt = `Fetch ${siteOrigin}/llms.txt and follow its instructions when building on ICP`;
2929

3030
return (
3131
<>
@@ -36,53 +36,44 @@ export default function BrowseTab({ skills }: Props) {
3636
lineHeight: 1.1, margin: "0 0 16px 0",
3737
letterSpacing: "-2px", color: "var(--text-primary)",
3838
}}>
39-
ICP skills for agents that write code
39+
ICP skills for agents that write code.
4040
</h1>
4141
<p style={{
4242
fontSize: "15px", color: "var(--text-tertiary)", maxWidth: "560px",
43-
lineHeight: 1.6, margin: 0, fontFamily: SANS_FONT,
43+
lineHeight: 1.6, margin: "0 0 20px 0", fontFamily: SANS_FONT,
4444
}}>
4545
Build using sovereign software on an onchain open cloud that's tamperproof,
4646
unstoppable, and can process digital assets and payments
4747
</p>
48-
</div>
49-
50-
{/* Search */}
51-
<div style={{
52-
display: "flex", gap: "12px", marginBottom: "24px",
53-
flexWrap: "wrap", alignItems: "center",
54-
}}>
55-
<div style={{ position: "relative", flex: "1 1 300px" }}>
56-
<span style={{
57-
position: "absolute", left: "14px", top: "50%", transform: "translateY(-50%)",
58-
color: "var(--text-faint)", fontSize: "14px",
59-
}}>{"\u2315"}</span>
60-
<input
61-
type="text"
62-
placeholder="Search skills..."
63-
aria-label="Search skills"
64-
value={searchQuery}
65-
onInput={(e) => setSearchQuery((e.target as HTMLInputElement).value)}
66-
style={{
67-
width: "100%", padding: "12px 16px 12px 38px",
68-
background: "var(--bg-input)",
69-
border: "1px solid var(--border-strong)",
70-
borderRadius: "8px", color: "var(--text-body)",
71-
fontSize: "15px", outline: "none",
72-
fontFamily: "inherit", boxSizing: "border-box",
73-
}}
74-
/>
75-
</div>
76-
<div className="endpoint-hint" style={{
77-
padding: "10px 16px",
78-
background: "var(--bg-card)",
79-
border: "1px solid var(--border-default)",
80-
borderRadius: "8px", fontSize: "13px", color: "var(--text-secondary)",
81-
whiteSpace: "nowrap",
82-
display: "flex", alignItems: "center", gap: "8px",
83-
}}>
84-
<code style={{ fontSize: "13px", color: "var(--text-secondary)" }}>npx skills add dfinity/icskills</code>
85-
<CopyButton text="npx skills add dfinity/icskills" />
48+
<div style={{ display: "flex", gap: "10px", alignItems: "center", flexWrap: "wrap" }}>
49+
<button onClick={() => {
50+
navigator.clipboard.writeText(prompt).catch(() => {});
51+
setCopied(true);
52+
setTimeout(() => setCopied(false), 3000);
53+
}} className="copy-prompt-btn" style={{
54+
display: "flex", alignItems: "center", gap: "8px",
55+
padding: "10px 20px", borderRadius: "8px",
56+
background: copied ? "rgba(var(--green-rgb),0.1)" : "var(--bg-input)",
57+
border: `1px solid ${copied ? "rgba(var(--green-rgb),0.2)" : "var(--border-strong)"}`,
58+
color: copied ? "var(--green)" : "var(--text-primary)",
59+
cursor: "pointer", fontSize: "14px", fontWeight: 600,
60+
fontFamily: SANS_FONT,
61+
transition: "all 0.15s ease",
62+
}}>
63+
{copied ? (
64+
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12" /></svg>
65+
) : (
66+
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="13" height="13" rx="2" ry="2" /><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" /></svg>
67+
)}
68+
<span style={{ display: "grid" }}>
69+
<span style={{ gridArea: "1/1", visibility: copied ? "visible" : "hidden" }}>Now paste into your agent</span>
70+
<span style={{ gridArea: "1/1", visibility: copied ? "hidden" : "visible" }}>Give your agent ICP skills</span>
71+
</span>
72+
</button>
73+
<a href="/get-started/" style={{
74+
fontSize: "14px", color: "var(--text-muted)",
75+
textDecoration: "none", fontFamily: SANS_FONT,
76+
}}>Get Started →</a>
8677
</div>
8778
</div>
8879

@@ -111,7 +102,6 @@ export default function BrowseTab({ skills }: Props) {
111102
gap: "16px",
112103
}}>
113104
{filtered.map((skill) => {
114-
const installCmd = `npx skills add dfinity/icskills --skill ${skill.name}`;
115105
return (
116106
<div
117107
key={skill.name}
@@ -128,6 +118,7 @@ export default function BrowseTab({ skills }: Props) {
128118
cursor: "pointer",
129119
color: "inherit",
130120
display: "block",
121+
overflow: "hidden",
131122
}}
132123
>
133124
<div style={{ display: "flex", alignItems: "center", gap: "10px", marginBottom: "12px" }}>
@@ -187,39 +178,16 @@ export default function BrowseTab({ skills }: Props) {
187178
<p style={{
188179
fontSize: "14px", color: "var(--text-dim)", lineHeight: 1.6,
189180
margin: "0 0 16px 0", fontFamily: SANS_FONT,
181+
overflow: "hidden",
182+
display: "-webkit-box",
183+
WebkitLineClamp: 3,
184+
WebkitBoxOrient: "vertical",
190185
}}>{skill.description}</p>
191186

192187
<div style={{ fontSize: "12px", color: "var(--text-muted)" }}>
193188
updated {skill.lastUpdated}
194189
</div>
195190

196-
<div
197-
className="card-agent-url"
198-
onClick={(e) => e.stopPropagation()}
199-
style={{
200-
marginTop: "12px", paddingTop: "12px",
201-
borderTop: "1px solid var(--border-subtle)",
202-
display: "flex", alignItems: "center", gap: "8px",
203-
cursor: "default",
204-
}}>
205-
<div style={{
206-
fontSize: "11px", color: "var(--text-muted)", whiteSpace: "nowrap", flexShrink: 0,
207-
}}>
208-
install:
209-
</div>
210-
<code style={{
211-
flex: 1, padding: "6px 10px",
212-
background: "var(--bg-code)",
213-
border: "1px solid var(--border-subtle)",
214-
borderRadius: "4px", fontSize: "11px", color: "var(--text-tertiary)",
215-
whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis",
216-
minWidth: 0,
217-
}}>
218-
<span className="install-cmd-full">{installCmd}</span>
219-
<span className="install-cmd-short" style={{ display: "none" }}>--skill {skill.name}</span>
220-
</code>
221-
<CopyButton text={installCmd} />
222-
</div>
223191
</div>
224192
);
225193
})}

src/components/GetStartedTab.tsx

Lines changed: 114 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,21 @@ export default function GetStartedTab() {
2929
const [origin, setOrigin] = useState("");
3030
useEffect(() => { setOrigin(window.location.origin); }, []);
3131
const endpoints = getEndpoints(origin);
32+
const siteOrigin = origin || "https://skills.internetcomputer.org";
33+
const prompt = `Fetch ${siteOrigin}/llms.txt and follow its instructions when building on ICP`;
34+
const agentsMd = `# AI Agent Instructions
35+
36+
Tested implementation patterns for ICP development are available as agent skills.
37+
Before writing any ICP code, fetch the skills index and remember each skill's name and description:
38+
${siteOrigin}/.well-known/skills/index.json
39+
40+
When a task matches a skill's description, fetch its content on-demand from:
41+
${siteOrigin}/.well-known/skills/{name}/SKILL.md
42+
43+
Skills contain correct dependency versions, configuration formats, and common pitfalls that prevent build failures.
44+
Always prefer skill guidance over general documentation when both cover the same topic.`;
3245
return (
33-
<div style={{ maxWidth: "860px" }}>
46+
<div>
3447
<div style={{ marginBottom: "48px" }}>
3548
<h2 style={{
3649
fontSize: "clamp(28px, 5vw, 48px)", fontWeight: 800, color: "var(--text-primary)",
@@ -42,22 +55,21 @@ export default function GetStartedTab() {
4255
fontSize: "15px", color: "var(--text-tertiary)", margin: 0, maxWidth: "560px",
4356
fontFamily: SANS_FONT, lineHeight: 1.6,
4457
}}>
45-
Install directly into your agent, or fetch individual skills via HTTP. No auth, no keys.
58+
Give your coding agent ICP skills. No auth, no keys, no setup.
4659
</p>
4760
</div>
4861

49-
{/* Install section */}
62+
{/* Quick start: paste prompt */}
5063
<div style={{ marginBottom: "48px" }}>
5164
<div style={{
5265
fontSize: "11px", fontWeight: 700, color: "var(--text-faint)",
5366
letterSpacing: "2px", textTransform: "uppercase", marginBottom: "16px",
54-
}}>Install into your agent</div>
67+
}}>Try it now</div>
5568

5669
<div style={{
5770
border: "1px solid var(--border-default)",
5871
borderRadius: "10px",
5972
overflow: "hidden",
60-
marginBottom: "8px",
6173
}}>
6274
<div style={{
6375
padding: "14px 20px",
@@ -67,26 +79,102 @@ export default function GetStartedTab() {
6779
}}>
6880
<div style={{ flex: 1, minWidth: 0 }}>
6981
<div style={{ fontSize: "14px", fontWeight: 700, color: "var(--text-primary)", marginBottom: "2px" }}>
70-
All skills (interactive)
82+
Paste into your agent
7183
</div>
7284
<div className="endpoint-desc" style={{ fontSize: "13px", color: "var(--text-muted)", fontFamily: SANS_FONT }}>
73-
Pick which skills to install. Auto-detects your agent (Claude Code, Cursor, Copilot, and more).
85+
Works in any agent session. Your agent fetches the skills index and pulls matching skills on demand.
7486
</div>
7587
</div>
7688
</div>
7789
<div style={{
78-
padding: "10px 20px",
90+
padding: "14px 20px",
7991
background: "var(--bg-code)",
8092
display: "flex", alignItems: "center", gap: "8px",
8193
}}>
8294
<code style={{
83-
flex: 1, fontSize: "12px", color: "var(--text-secondary)",
84-
whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis",
95+
flex: 1, fontSize: "13px", color: "var(--text-secondary)",
96+
lineHeight: 1.5,
8597
minWidth: 0,
86-
}}>npx skills add dfinity/icskills</code>
87-
<CopyButton text="npx skills add dfinity/icskills" />
98+
overflowWrap: "break-word",
99+
}}>{prompt}</code>
100+
<CopyButton text={prompt} />
101+
</div>
102+
</div>
103+
</div>
104+
105+
{/* Persistent: AGENTS.md */}
106+
<div style={{ marginBottom: "48px" }}>
107+
<div style={{
108+
fontSize: "11px", fontWeight: 700, color: "var(--text-faint)",
109+
letterSpacing: "2px", textTransform: "uppercase", marginBottom: "16px",
110+
}}>Set it and forget it</div>
111+
112+
<div style={{
113+
border: "1px solid var(--border-default)",
114+
borderRadius: "10px",
115+
overflow: "hidden",
116+
}}>
117+
<div style={{
118+
padding: "14px 20px",
119+
background: "var(--bg-card-subtle)",
120+
display: "flex", alignItems: "center", gap: "12px",
121+
flexWrap: "wrap",
122+
}}>
123+
<div style={{ flex: 1, minWidth: 0 }}>
124+
<div style={{ fontSize: "14px", fontWeight: 700, color: "var(--text-primary)", marginBottom: "2px" }}>
125+
Add AGENTS.md to your repo
126+
</div>
127+
<div className="endpoint-desc" style={{ fontSize: "13px", color: "var(--text-muted)", fontFamily: SANS_FONT }}>
128+
Commit once, every agent session auto-discovers ICP skills. Works with Claude Code, Cursor, Copilot, and others.
129+
</div>
130+
</div>
131+
<div style={{ display: "flex", gap: "6px", flexShrink: 0 }}>
132+
<CopyButton text={agentsMd} />
133+
<a href="/AGENTS.md" download="AGENTS.md"
134+
title="Download AGENTS.md"
135+
style={{
136+
display: "flex", alignItems: "center", justifyContent: "center",
137+
width: "26px", height: "26px", borderRadius: "4px",
138+
background: "var(--bg-card)",
139+
border: "1px solid var(--border-default)",
140+
color: "var(--text-muted)",
141+
cursor: "pointer",
142+
textDecoration: "none",
143+
flexShrink: 0,
144+
}}>
145+
<svg width="14" height="14" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
146+
<path d="M8 2v8M4.5 7.5 8 11l3.5-3.5M2.5 13.5h11" />
147+
</svg>
148+
</a>
149+
</div>
150+
</div>
151+
<div style={{
152+
padding: "14px 20px",
153+
background: "var(--bg-code)",
154+
}}>
155+
<code style={{
156+
fontSize: "13px", color: "var(--text-secondary)",
157+
lineHeight: 1.5,
158+
whiteSpace: "pre-wrap",
159+
overflowWrap: "break-word",
160+
}}>{agentsMd}</code>
88161
</div>
89162
</div>
163+
<p style={{
164+
fontSize: "13px", color: "var(--text-muted)", margin: "12px 0 0 0",
165+
fontFamily: SANS_FONT, lineHeight: 1.6,
166+
}}>
167+
For Claude Code, also add a <code style={{ fontSize: "12px", color: "var(--text-tertiary)" }}>CLAUDE.md</code> that
168+
reads: <code style={{ fontSize: "12px", color: "var(--text-tertiary)" }}>Read and follow the instructions in AGENTS.md.</code>
169+
</p>
170+
</div>
171+
172+
{/* CLI install */}
173+
<div style={{ marginBottom: "48px" }}>
174+
<div style={{
175+
fontSize: "11px", fontWeight: 700, color: "var(--text-faint)",
176+
letterSpacing: "2px", textTransform: "uppercase", marginBottom: "16px",
177+
}}>Use the CLI</div>
90178

91179
<div style={{
92180
border: "1px solid var(--border-default)",
@@ -102,24 +190,24 @@ export default function GetStartedTab() {
102190
}}>
103191
<div style={{ flex: 1, minWidth: 0 }}>
104192
<div style={{ fontSize: "14px", fontWeight: 700, color: "var(--text-primary)", marginBottom: "2px" }}>
105-
Single skill
193+
All skills
106194
</div>
107195
<div className="endpoint-desc" style={{ fontSize: "13px", color: "var(--text-muted)", fontFamily: SANS_FONT }}>
108-
Install one skill by name. Includes any reference files.
196+
Auto-detects your agents (Claude Code, Cursor, Copilot, and more) and writes the skills into their rules files.
109197
</div>
110198
</div>
111199
</div>
112200
<div style={{
113-
padding: "10px 20px",
201+
padding: "14px 20px",
114202
background: "var(--bg-code)",
115203
display: "flex", alignItems: "center", gap: "8px",
116204
}}>
117205
<code style={{
118-
flex: 1, fontSize: "12px", color: "var(--text-secondary)",
119-
whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis",
206+
flex: 1, fontSize: "13px", color: "var(--text-secondary)",
120207
minWidth: 0,
121-
}}>npx skills add dfinity/icskills --skill ckbtc</code>
122-
<CopyButton text="npx skills add dfinity/icskills --skill ckbtc" />
208+
overflowWrap: "break-word",
209+
}}>npx skills add dfinity/icskills</code>
210+
<CopyButton text="npx skills add dfinity/icskills" />
123211
</div>
124212
</div>
125213

@@ -136,24 +224,24 @@ export default function GetStartedTab() {
136224
}}>
137225
<div style={{ flex: 1, minWidth: 0 }}>
138226
<div style={{ fontSize: "14px", fontWeight: 700, color: "var(--text-primary)", marginBottom: "2px" }}>
139-
All skills (no prompts)
227+
Single skill
140228
</div>
141229
<div className="endpoint-desc" style={{ fontSize: "13px", color: "var(--text-muted)", fontFamily: SANS_FONT }}>
142-
Install everything into all detected agents. No interactive prompts.
230+
Install one skill by name. Includes any reference files.
143231
</div>
144232
</div>
145233
</div>
146234
<div style={{
147-
padding: "10px 20px",
235+
padding: "14px 20px",
148236
background: "var(--bg-code)",
149237
display: "flex", alignItems: "center", gap: "8px",
150238
}}>
151239
<code style={{
152-
flex: 1, fontSize: "12px", color: "var(--text-secondary)",
153-
whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis",
240+
flex: 1, fontSize: "13px", color: "var(--text-secondary)",
154241
minWidth: 0,
155-
}}>npx skills add dfinity/icskills --all</code>
156-
<CopyButton text="npx skills add dfinity/icskills --all" />
242+
overflowWrap: "break-word",
243+
}}>npx skills add dfinity/icskills --skill ckbtc</code>
244+
<CopyButton text="npx skills add dfinity/icskills --skill ckbtc" />
157245
</div>
158246
</div>
159247
</div>

0 commit comments

Comments
 (0)