Skip to content

Commit 146f7cb

Browse files
amacsmithclaude
andcommitted
feat(pages): per-entry "Use this entry" install snippets
Every winner of the registry-adoption race ships a one-line install string per entry (HF Hub from_pretrained, npm npx, PyPI pip install, crates.io cargo add). We had a single MCP snippet on the hero, but every entry's detail panel made the reader figure out for themselves how to feed that specific entry's graph_url to their agent. This adds a "Use this entry" section to the entry detail panel with four copy-paste-ready snippets, each populated with the entry's id and graph_url so it works without further editing: 1. MCP tool call — `find_graph_for_repo({ repo: "<id>" })` for agents already running understand-quickly-mcp. 2. Python SDK — `Registry().get_graph("<id>")`. 3. Python CLI — `uvx understand-quickly get-graph <id>` for shell users who don't want to install the SDK. 4. cURL — `curl -sL <graph_url>` for the lowest-common-denominator HTTP client (skipped if the entry has no graph_url). Each snippet renders in a small monospace block with its own Copy button that flashes "Copied" / "Failed" for 1.4s. Reused the existing copyText() helper rather than building new clipboard plumbing. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 65bfb17 commit 146f7cb

3 files changed

Lines changed: 130 additions & 2 deletions

File tree

site/app.js

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -753,6 +753,9 @@ function showDetail(entry) {
753753
actions.appendChild(raw);
754754
}
755755

756+
const useSection = renderUseSection(entry);
757+
if (useSection) body.appendChild(useSection);
758+
756759
body.appendChild(el('section', { className: 'detail-section' }, [
757760
el('h3', { text: 'Actions' }),
758761
actions,
@@ -804,6 +807,73 @@ function renderSelectedNodeCard(entry) {
804807
return card;
805808
}
806809

810+
// Build the "Use this entry" section — copy-paste snippets that route an
811+
// agent or human to *this specific entry*. The snippets are populated with
812+
// the entry's id and graph_url so a reader gets value in three seconds
813+
// without re-typing identifiers. We surface four channels:
814+
// 1. MCP tool call — for agents already running our MCP server.
815+
// 2. Python SDK — for scripted consumers.
816+
// 3. Python CLI — for shell/Makefile users.
817+
// 4. cURL — for the lowest-common-denominator HTTP client.
818+
// Section is skipped entirely if the entry has no id; without an id no
819+
// snippet is meaningful.
820+
function renderUseSection(entry) {
821+
if (!entry || !entry.id) return null;
822+
const id = String(entry.id);
823+
const graphUrl = entry.graph_url || '';
824+
const snippets = [
825+
{
826+
label: 'MCP (in any agent running understand-quickly-mcp)',
827+
body: `find_graph_for_repo({ repo: "${id}" })`,
828+
},
829+
{
830+
label: 'Python SDK',
831+
body: `from understand_quickly import Registry\ngraph = Registry().get_graph("${id}")`,
832+
},
833+
{
834+
label: 'CLI',
835+
body: `uvx understand-quickly get-graph ${id}`,
836+
},
837+
];
838+
if (graphUrl) {
839+
snippets.push({
840+
label: 'cURL (raw JSON)',
841+
body: `curl -sL ${graphUrl}`,
842+
});
843+
}
844+
const section = el('section', { className: 'detail-section detail-use' }, [
845+
el('h3', { text: 'Use this entry' }),
846+
el('p', { className: 'detail-use-hint', text: 'Copy-paste into your agent or shell. Routes straight to this entry.' }),
847+
]);
848+
for (const s of snippets) section.appendChild(renderSnippetBlock(s.label, s.body));
849+
return section;
850+
}
851+
852+
function renderSnippetBlock(label, body) {
853+
const block = el('div', { className: 'use-snippet' });
854+
const head = el('div', { className: 'use-snippet-head' }, [
855+
el('span', { className: 'use-snippet-label', text: label }),
856+
]);
857+
const copyBtn = el('button', {
858+
className: 'use-snippet-copy',
859+
attrs: { type: 'button', 'aria-label': `Copy ${label}` },
860+
text: 'Copy',
861+
});
862+
copyBtn.addEventListener('click', async () => {
863+
const ok = await copyText(body);
864+
const prev = copyBtn.textContent;
865+
copyBtn.textContent = ok ? 'Copied' : 'Failed';
866+
setTimeout(() => { copyBtn.textContent = prev; }, 1400);
867+
});
868+
head.appendChild(copyBtn);
869+
const pre = el('pre', { className: 'use-snippet-body' }, [
870+
el('code', { text: body }),
871+
]);
872+
block.appendChild(head);
873+
block.appendChild(pre);
874+
return block;
875+
}
876+
807877
function buildGithubUrlForNode(entry, normNode) {
808878
if (!entry || !entry.id || !normNode) return null;
809879
const raw = normNode._raw || {};

site/index.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@
7575
<link rel="stylesheet"
7676
href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600&family=DM+Serif+Display&family=JetBrains+Mono:wght@400;500&display=swap">
7777

78-
<link rel="stylesheet" href="./styles.css?v=20260511a">
78+
<link rel="stylesheet" href="./styles.css?v=20260511b">
7979
</head>
8080
<body>
8181
<div class="app">
@@ -438,7 +438,7 @@ <h2>Keyboard shortcuts</h2>
438438
</div>
439439
</div>
440440

441-
<script type="module" src="./app.js?v=20260511a"></script>
441+
<script type="module" src="./app.js?v=20260511b"></script>
442442
<script
443443
defer
444444
src="https://static.cloudflareinsights.com/beacon.min.js"

site/styles.css

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1301,6 +1301,64 @@ button { font-family: inherit; }
13011301
color: var(--color-text-secondary);
13021302
word-break: break-all;
13031303
}
1304+
.detail-use .detail-use-hint {
1305+
color: var(--color-text-secondary);
1306+
font-size: 12px;
1307+
margin: 4px 0 10px;
1308+
}
1309+
.use-snippet {
1310+
background: var(--color-surface-2, rgba(255, 255, 255, 0.03));
1311+
border: 1px solid var(--color-border, rgba(255, 255, 255, 0.08));
1312+
border-radius: 8px;
1313+
padding: 8px 10px;
1314+
margin-bottom: 10px;
1315+
}
1316+
.use-snippet-head {
1317+
display: flex;
1318+
justify-content: space-between;
1319+
align-items: center;
1320+
gap: 8px;
1321+
margin-bottom: 6px;
1322+
}
1323+
.use-snippet-label {
1324+
color: var(--color-text-secondary);
1325+
font-size: 11px;
1326+
text-transform: uppercase;
1327+
letter-spacing: 0.04em;
1328+
}
1329+
.use-snippet-copy {
1330+
background: transparent;
1331+
border: 1px solid var(--color-border, rgba(255, 255, 255, 0.18));
1332+
color: var(--color-text-primary);
1333+
font-size: 11px;
1334+
padding: 2px 8px;
1335+
border-radius: 4px;
1336+
cursor: pointer;
1337+
transition: background 120ms ease, border-color 120ms ease;
1338+
}
1339+
.use-snippet-copy:hover {
1340+
background: rgba(255, 255, 255, 0.05);
1341+
}
1342+
.use-snippet-body {
1343+
background: rgba(0, 0, 0, 0.25);
1344+
border-radius: 6px;
1345+
padding: 8px 10px;
1346+
margin: 0;
1347+
font-family: var(--font-mono);
1348+
font-size: 12px;
1349+
line-height: 1.5;
1350+
color: var(--color-text-primary);
1351+
white-space: pre-wrap;
1352+
word-break: break-all;
1353+
overflow-x: auto;
1354+
}
1355+
.use-snippet-body code {
1356+
background: transparent;
1357+
padding: 0;
1358+
font-family: inherit;
1359+
font-size: inherit;
1360+
color: inherit;
1361+
}
13041362
.detail-tags {
13051363
display: flex;
13061364
flex-wrap: wrap;

0 commit comments

Comments
 (0)