Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion content/docs/api/index.mdx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: "API"
icon: "Braces"
description: "Every way to reach Stunt Double from code or an agent: the MCP server for your workspace, the no-account Index and docs servers, Markdown docs and llms.txt, and the public discovery files."
description: "Every way to reach Stunt Double from code or an agent: the workspace MCP server, the no-account Index and docs servers, Markdown docs and llms.txt."
---

# API and agent access
Expand Down
2 changes: 1 addition & 1 deletion content/docs/concepts/index.mdx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: "Concepts"
icon: "compass"
description: "Short definitions of Stunt Double's building blocks (workspaces, actors, checklists, interviews, automations, issues and more) and how they relate, with a link to the page that goes deeper on each."
description: "Short definitions of Stunt Double's building blocks (workspaces, actors, checklists, interviews, automations, issues) and how they relate."
---

# Core concepts
Expand Down
2 changes: 1 addition & 1 deletion content/docs/index-ranking/index.mdx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: "Stunt Double Index"
icon: "Gauge"
description: "What the Stunt Double Index is: a public ranking of how well AI agents can use a website, how a score is made, what it measures, and how to add, claim and share a site."
description: "The Stunt Double Index ranks how well AI agents can use a website: how a score is made, what it measures, and how to add, claim and share a site."
---

# Stunt Double Index
Expand Down
2 changes: 1 addition & 1 deletion content/docs/stuntkit/browser-toolset/index.mdx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: "Browser toolset"
icon: "Globe"
description: "Use @stunt-double/browser-toolset to let Claude or any function-calling model read and act on real pages, with guards that refuse payments, sign-ups, passwords and card numbers."
description: "Let Claude or any function-calling model read and act on real pages with @stunt-double/browser-toolset, with guards that refuse payments and sign-ups."
---

# Give an AI agent a safe browser
Expand Down
2 changes: 1 addition & 1 deletion content/docs/stuntkit/index.mdx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: "StuntKit"
icon: "Package"
description: "What StuntKit is and which package to use: the open source browser toolset, Web Agent Optimiser, icons and Localeizer behind Stunt Double, plus agent skills and how to contribute."
description: "StuntKit, the open source toolkit behind Stunt Double: the browser toolset, Web Agent Optimiser, icons and Localeizer, plus agent skills."
---

# StuntKit
Expand Down
2 changes: 1 addition & 1 deletion content/docs/stuntkit/localeizer/index.mdx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: "Localeizer"
icon: "SpellCheck"
description: "Use Localeizer (@stunt-double/localeizer) to rewrite text into American, British, Australian or Canadian spelling, whole words only, from American or British source text."
description: "Rewrite text into American, British, Australian or Canadian spelling with @stunt-double/localeizer, whole words only."
---

# Localeizer
Expand Down
301 changes: 273 additions & 28 deletions content/docs/stuntkit/wao/index.mdx

Large diffs are not rendered by default.

18 changes: 17 additions & 1 deletion scripts/generate.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,22 @@ export function slugify(heading) {
const INTERNAL = /\.cursor-plugin|plugin validation|plugin layout|mcp-publisher|CONTRIBUTING\.md|validate-json/i;

/** Drop internal paragraphs, point old marketing docs URLs at this site and take out em dashes. */
/**
* A meta description from a long one (a skill's trigger text): its first
* sentence, cut back to a clause boundary if that still runs past `max`, so
* search snippets and the OG card never end mid-word.
*/
export function summary(text, max = 160) {
if (text.length <= max) return text;
const first = text.match(/^.*?[.!?](?=\s|$)/)?.[0] ?? text;
if (first.length <= max) return first;
const head = first.slice(0, max);
// A colon or bracket ends the main clause; a comma may sit inside a list.
const clause = Math.max(head.lastIndexOf(': '), head.lastIndexOf(' ('));
const cut = clause > 40 ? clause : head.lastIndexOf(', ') > 60 ? head.lastIndexOf(', ') : head.lastIndexOf(' ');
return `${head.slice(0, cut).replace(/[,:;]$/, '')}.`;
}

export function clean(markdown) {
return markdown
.split(/\n{2,}/)
Expand Down Expand Up @@ -261,7 +277,7 @@ export function mcpPages(src, at) {
);
for (const s of skills) {
out[`skills/${s.name}.mdx`] = page(
{ title: s.title, description: s.description },
{ title: s.title, description: summary(s.description) },
mdx(s.body, s.file.replace(/[^/]+$/, '')),
[s.file]
);
Expand Down
10 changes: 9 additions & 1 deletion scripts/generate.test.mjs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import assert from 'node:assert/strict';
import { test } from 'node:test';

import { clean, mcpPages, readmeToMdx } from './generate.mjs';
import { clean, mcpPages, readmeToMdx, summary } from './generate.mjs';

const at = { repo: 'stunt-double/x', tag: 'v1.0.0' };

Expand Down Expand Up @@ -122,3 +122,11 @@ test('mcpPages splits the README by client and ends every page with an edit link
assert.doesNotMatch(content, /\u2014/, path);
}
});

test('summary keeps short text and cuts long text at a sentence or clause', () => {
assert.equal(summary('Short.'), 'Short.');
assert.equal(summary(`${'a'.repeat(100)}. ${'b'.repeat(100)}.`), `${'a'.repeat(100)}.`);
const long = `Check a product (${'x'.repeat(40)}), ${'y'.repeat(60)}, ${'z'.repeat(80)}.`;
const out = summary(long);
assert.ok(out.length <= 161 && out.endsWith('.') && !out.includes('z'), out);
});
Loading