diff --git a/README.md b/README.md index 5964ed1..c22a733 100644 --- a/README.md +++ b/README.md @@ -26,16 +26,46 @@ A community-built library of professional skills for every field โ€” product man **๐Ÿ†• Latest release (v20.2.0 โ€” Community PRs & New Skill):** a new **YouTube Script Writer** skill (**174 total**), a stdlib **feature-prioritisation** helper, safer installs, and robust frontmatter parsing โ€” all from community contributors. See the [changelog](#-changelog). - ### โ–ถ See it in action โ€” [try the live Skill Playground](https://mohitagw15856.github.io/pm-claude-skills/) -[![Skill Playground demo โ€” pick a skill, fill the form, run it with your own Claude key](web/docs-assets/playground.png)](https://mohitagw15856.github.io/pm-claude-skills/) + +[![Skill Playground demo โ€” pick a skill, fill the form, run it with your own Claude key](web/docs-assets/playground-demo.gif)](https://mohitagw15856.github.io/pm-claude-skills/) + +๐Ÿ‘† Pick any skill, fill a short form, and run it with your own key โ€” no install required. + +--- + +## ๐Ÿ”„ One library, the whole professional workflow + +These 174 skills aren't a random catalog โ€” they cover the **full arc of professional work**, end to end. Wherever you are in the loop, there's a skill for it: + +``` + DISCOVER โ†’ DECIDE โ†’ BUILD โ†’ SHIP โ†’ MEASURE โ†’ COMMUNICATE + โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + frame the prioritise design & launch & track & report up + problem, & spec the engineer release analyse & out + research work the work the work results + โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ feeds the next discovery โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ +``` + +| Phase | What you're doing | Start with these skills | +|-------|-------------------|--------------------------| +| **๐Ÿ” Discover** | Frame the problem, research, validate | `ambiguity-resolver` ยท `user-research-synthesis` ยท `competitive-analysis` ยท `discovery-interview-guide` | +| **๐ŸŽฏ Decide** | Prioritise, spec, set goals | `rice-prioritisation` ยท `prd-template` ยท `okr-builder` ยท `roadmap-narrative` | +| **๐Ÿ”จ Build** | Design & engineer the work | `technical-spec-template` ยท `design-critique` ยท `sprint-planning` ยท `architecture-decision-record` | +| **๐Ÿš€ Ship** | Launch & release | `go-to-market` ยท `launch-readiness` ยท `product-launch-checklist` ยท `runbook-writer` | +| **๐Ÿ“Š Measure** | Track outcomes & analyse | `metrics-framework` ยท `cohort-analysis` ยท `ab-test-planner` ยท `churn-analysis` | +| **๐Ÿ“ฃ Communicate** | Report up and out | `executive-update` ยท `board-deck-narrative` ยท `stakeholder-update` ยท `qbr-deck` | + +> New here? Start with the [**top-tier skills**](#๏ธ-skill-tiers--start-with-the-strongest), or jump straight to [**all 174 skills**](#๏ธ-all-174-skills) grouped by profession. --- ## Contents +- [๐Ÿ”„ One library, the whole professional workflow](#-one-library-the-whole-professional-workflow) - [๐Ÿš€ Quick Install](#-quick-install-2-minutes) - [๐Ÿ”Œ Works With โ€” Cross-Tool Compatibility](#-works-with--cross-tool-compatibility) - [๐Ÿค– Subagents & Slash Commands](#-subagents--slash-commands) diff --git a/web/docs-assets/README.md b/web/docs-assets/README.md index 271690b..1cfb9b8 100644 --- a/web/docs-assets/README.md +++ b/web/docs-assets/README.md @@ -2,9 +2,40 @@ Images used in the main README. -- `playground.png` โ€” current Skill Playground screenshot (shown in the README hero). +- `playground-demo.gif` โ€” animated hero demo (shown in the README). +- `playground.png` โ€” static screenshot / fallback. -## Recording the hero demo GIF +## Re-recording the hero demo GIF (automated) + +`record-demo.mjs` drives the live Playground with Playwright and records a video. +The navigation, skill selection, and form-fill are real; the streamed model output +is a representative mock, so **no API key is needed**. + +```bash +# 1. Serve the playground locally +cd web && python3 -m http.server 8080 & + +# 2. Build the skills data if it is stale +node web/build-skills.mjs + +# 3. Record (Playwright + a matching Chromium must be installed) +# npx playwright install chromium # one-time, if needed +node web/docs-assets/record-demo.mjs # writes a .webm into this folder + +# 4. Convert the .webm to an optimized GIF (two-pass palette) +cd web/docs-assets +V=$(ls *.webm | head -1) +ffmpeg -y -i "$V" -vf "fps=13,scale=1080:-1:flags=lanczos,palettegen=stats_mode=diff" /tmp/palette.png +ffmpeg -y -i "$V" -i /tmp/palette.png \ + -lavfi "fps=13,scale=1080:-1:flags=lanczos[x];[x][1:v]paletteuse=dither=bayer:bayer_scale=3:diff_mode=rectangle" \ + playground-demo.gif +rm -f *.webm +``` + +For a **fully live** recording (real Claude call instead of the mock), comment out the +`window.fetch` override in `record-demo.mjs` and set a key via `localStorage` first. + +## Recording manually (alternative) To replace the static screenshot with a short looping demo: diff --git a/web/docs-assets/playground-demo.gif b/web/docs-assets/playground-demo.gif new file mode 100644 index 0000000..5bacaaa Binary files /dev/null and b/web/docs-assets/playground-demo.gif differ diff --git a/web/docs-assets/record-demo.mjs b/web/docs-assets/record-demo.mjs new file mode 100644 index 0000000..dd753d1 --- /dev/null +++ b/web/docs-assets/record-demo.mjs @@ -0,0 +1,124 @@ +// Records the Skill Playground hero demo as a video, driving the real UI with +// Playwright. The navigation, skill selection, and form-fill are genuine; only +// the streamed model output is mocked (a representative Executive Update) so the +// recording needs no API key. Re-run with a live key to capture a real call. +// +// Usage: node web/docs-assets/record-demo.mjs +// Then convert the .webm to playground-demo.gif (see record-demo.sh). + +import { fileURLToPath } from 'url'; +import path from 'path'; +import { createRequire } from 'module'; + +// Playwright may be installed locally or only in the npx cache; resolve either. +const require = createRequire(import.meta.url); +const pwPath = process.env.PLAYWRIGHT_PATH || 'playwright'; +const pw = await import(pwPath).catch(() => + import(require.resolve('playwright', { paths: [process.env.PLAYWRIGHT_DIR].filter(Boolean) })) +); +const chromium = pw.chromium || (pw.default && pw.default.chromium); + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); +const BASE = process.env.DEMO_URL || 'http://localhost:8080/'; +const VIEWPORT = { width: 1180, height: 760 }; + +// Representative output, streamed in small chunks for a natural typing effect. +const OUTPUT = `# Executive Update โ€” Q2, for the CEO + +**Headline:** Activation is up 14% after the onboarding redesign; we are on track for the Q2 target with one staffing risk to flag. + +## Key metrics +- **Weekly active accounts:** 12,400 (+18% QoQ) +- **Activation rate:** 61% (+14 pts) โ€” best quarter on record +- **Net revenue retention:** 112% (flat) + +## Progress +We shipped the redesigned onboarding flow to 100% of new accounts. Early cohorts show faster time-to-value (median 2.1 days, down from 4.6). + +## Risks & decisions needed +- **Risk:** Backend hiring is two roles behind plan, putting the billing revamp at risk for Q3. +- **Decision:** Approve contractor budget to hold the Q3 date. + +## Next steps +- Roll the activation experiment into the core product (next sprint). +- Bring a Q3 staffing plan to the next leadership review.`; + +function chunk(text) { + // Split into word-ish pieces so the stream renders progressively. + return text.match(/\S+\s*/g) || [text]; +} + +const initScript = ({ chunks }) => { + try { localStorage.setItem('anthropic_api_key', 'sk-ant-demo-key-not-real'); } catch (e) {} + const realFetch = window.fetch.bind(window); + window.fetch = (url, opts) => { + const u = typeof url === 'string' ? url : (url && url.url) || ''; + if (!u.includes('api.anthropic.com')) return realFetch(url, opts); + const enc = new TextEncoder(); + let i = 0; + const stream = new ReadableStream({ + start(controller) { + const push = () => { + if (i >= chunks.length) { + controller.enqueue(enc.encode('data: {"type":"message_stop"}\n\n')); + controller.close(); + return; + } + const evt = { type: 'content_block_delta', delta: { type: 'text_delta', text: chunks[i++] } }; + controller.enqueue(enc.encode('data: ' + JSON.stringify(evt) + '\n\n')); + setTimeout(push, 45); + }; + setTimeout(push, 200); + }, + }); + return Promise.resolve(new Response(stream, { status: 200, headers: { 'content-type': 'text/event-stream' } })); + }; +}; + +const pause = (ms) => new Promise((r) => setTimeout(r, ms)); + +const run = async () => { + const browser = await chromium.launch(); + const context = await browser.newContext({ + viewport: VIEWPORT, + deviceScaleFactor: 2, + recordVideo: { dir: __dirname, size: VIEWPORT }, + }); + const page = await context.newPage(); + await page.addInitScript(initScript, { chunks: chunk(OUTPUT) }); + + await page.goto(BASE, { waitUntil: 'networkidle' }); + await page.waitForSelector('.skill-card'); + await pause(700); + + // Search to surface the featured skill. + await page.fill('#search', 'executive update'); + await pause(600); + + // Open it. + await page.click('.skill-card:has(.card-title:text-is("Executive Update"))'); + await page.waitForSelector('#inputForm input, #inputForm textarea'); + await pause(500); + + // Fill the form like a real user would. + await page.locator('#f_0').type( + 'Shipped onboarding redesign to all new accounts. Activation up sharply. Backend hiring behind plan, billing revamp at risk for Q3.', + { delay: 8 } + ); + await pause(150); + await page.locator('#f_1').type('CEO', { delay: 25 }); + await page.locator('#f_2').type('Q2', { delay: 25 }); + await page.locator('#f_3').type('WAA, activation rate, NRR', { delay: 18 }); + await pause(500); + + // Run โ€” the intercepted stream renders progressively. + await page.click('#runBtn'); + await page.waitForFunction(() => document.querySelector('#status')?.textContent?.includes('Done'), { timeout: 15000 }); + await pause(1600); // hold on the finished result + + await context.close(); // flushes the video file + await browser.close(); + console.log('Recorded video into', __dirname); +}; + +run().catch((e) => { console.error(e); process.exit(1); });