README, docs and site: one story (the whole job, no avoidable rejections, the desktop app, your AI, install)

README is a short front page (about 120 lines) with one real visual per section; every former section moved
unchanged into docs/*.md with a docs/README.md index (journey, rejections, getting-started, commands, growth,
studios, store-art, listing-languages, api, skills, mcp, safety, faq, project). The site tells the same story on one
page: the teaser in the hero, real CLI output as text, the desktop app as a section with light/dark captures of eight
screens and the per-system downloads (desktop/latest.json); /desktop/ redirects to /#download. New capture tools:
tools/site-desktop-shots.ts (fixture-mode desktop frames) and tools/site-term-shots.ts (real CLI output as text and
WebP). tests/docs-links.test.ts checks README, docs and site links resolve.
This commit is contained in:
CRTkafa 2026-10-13 03:29:59 +08:00
parent deb218943c
commit 710c3a53d0
63 changed files with 2742 additions and 1782 deletions

View file

@ -23,10 +23,11 @@ describe("first rule: do it, don't ask", () => {
test('reaches every generated adapter, README and the lead of store-pitfalls', () => {
for (const f of ['AGENTS.md', 'GEMINI.md', '.github/copilot-instructions.md', '.cursor/rules/storebound.mdc'])
expect(read(f).toLowerCase()).toContain(RULE);
// the first section of README carries the rule; the full text lives in docs/journey.md
const readme = read('README.md');
const at = readme.indexOf('## How agents use storebound');
expect(at).toBeGreaterThan(0);
expect(readme.slice(0, at).split('\n## ').length).toBe(1); // the first section of README
const first = readme.split('\n## ')[1] ?? '';
expect(first.toLowerCase()).toContain(RULE);
expect(read('docs/journey.md')).toContain('## How agents use storebound');
const pit = read('skills/store-pitfalls/SKILL.md');
expect(/^## (.*)$/m.exec(pit)?.[1]?.toLowerCase()).toContain(RULE);
for (const s of ['console-autofill', 'play-first-release', 'appstore-first-release', 'store-declarations'])
@ -43,7 +44,8 @@ describe("first rule: do it, don't ask", () => {
/\b(do|fill|finish) (that|this) (part )?by hand\b/i,
/\bfor the owner to copy\b/i,
];
const files = ['docs/agents-core.md', 'README.md',
const files = ['docs/agents-core.md', 'README.md', // the README's former sections, now in docs/
...['journey', 'getting-started', 'commands', 'rejections', 'growth', 'studios', 'store-art', 'faq', 'safety', 'mcp', 'skills', 'listing-languages', 'api', 'project'].map(n => `docs/${n}.md`),
...readdirSync(join(root, 'skills')).map(n => `skills/${n}/SKILL.md`).filter(f => { try { read(f); return true; } catch { return false; } })];
test('no skill or rule hands navigation, exports, uploads or forms to the owner', () => {