Ship a share-react skill for social-media-tools that turns any React component into one dark-mode social card — a rendered static preview (up to three states), the implementation code, and a full typed props table — then wire it into the router, templates, reference docs, README, tests, and release metadata so it ships as a first-class share-* skill.
Read and implement all steps in the plan at docs/plans/add-share-react-skill.html — Ship a share-react skill: preview, implementation, and props card
Run as workflow — launch parallel subagents
Run a workflow to implement the plan at docs/plans/add-share-react-skill.html — Ship a share-react skill: preview, implementation, and props card
add-share-react-skill.html
docs/plans/add-share-react-skill.html
Context
social-media-tools ships eleven share-* skills built on one skeleton: locate plugin assets, load SOCIAL.md, capture input, reuse-check, run the security-scrub gate, draft platform-aware copy, populate a {{VARIABLE}} card template, persistent-save to docs/media/social/, Playwright-screenshot the card, and deliver. The closest siblings — share-github and share-selection — render code into snippet-card.html. None of them shows a component's rendered appearance or its API.
React developers want to share a component as three things at once: what it looks like, how it is built, and how to use it (its props). share-react fills that gap by combining a visual preview, the implementation, and a typed props table in a single card.
Design decisions locked during clarify and the alignment stress-test:
- Preview = static mockup. Claude reads the component and hand-builds an HTML/CSS approximation of its rendered output (up to three states). There is no React or Babel runtime, so the existing static screenshot pipeline works unchanged. The two live-render approaches become Wish List flags.
- Input = path or selection, equal footing. Accept a
.tsx/.jsxfile path argument or an IDE selection / pasted code block (mirroringshare-selection's capture). - Props = full API, types first. Parse the component's TypeScript Props interface / type alias or
propTypesfor name · type · required · default · description, falling back to inference from JSX usage when no explicit types exist. - Router = any React file. The
social-sharerouter sends any.tsx/.jsxselection toshare-react. This intentionally makes share-react the default for React files, intercepting the generic snippet path; a plain non-React snippet still falls through toshare-selection.
A new skill is not a single file: it touches the SKILL.md, a new card template, a props reference, the social-share router, references/variables.md, the README, the repo-root CLAUDE.md row, the CHANGELOG.md, plugin.json keywords, the marketplace.json version, and committed tests.
Files to Modify
- kit/plugins/social-media-tools/skills/share-react/
SKILL.mdnew share-react skill workflowreferences/props-extraction.mdnew props parsing + row renderingkit/plugins/social-media-tools/templates/react-card.htmlnew preview + code + props cardkit/plugins/social-media-tools/skills/social-share/SKILL.mdmodified add .tsx/.jsx router rulekit/plugins/social-media-tools/references/variables.mdmodified document react-card variableskit/plugins/social-media-tools/README.mdmodified skill + card-type tables, treekit/plugins/social-media-tools/CHANGELOG.mdmodified v2.11.0 entrykit/plugins/social-media-tools/.claude-plugin/plugin.jsonmodified add react keywords.claude-plugin/marketplace.jsonmodified bump to 2.11.0 + tagsCLAUDE.mdmodified update plugin table row- tests/social-media-tools/
test-react-card-smoke.shnew objective smoke testtest-share-react-registration.shnew wiring / registration testREADME.mdnew manual E2E run instructions
Diagram
path or selectionsecurity-scrub gatetypes → inferstatic mockuptakeaway-first copyreact-card.htmlPlaywrightcopy + PNG + save- No runtime or build
- Works for any component
- Claude hand-builds states
- Unchanged screenshot pipeline
- React + Babel via CDN
- True render
- Breaks on imports
- Wish List: --live flag
- Most accurate
- Needs running server
- Needs story URL / id
- Wish List: --story mode
Steps
skills/share-react/SKILL.md with the full phase workflow
Verify
kit/plugins/social-media-tools/skills/share-react/SKILL.md with three-part frontmatter and the phases: Locate assets, load SOCIAL.md, capture (a .tsx/.jsx path or IDE selection/paste), reuse-check, security-scrub, extract props, build static preview (up to 3 states), draft takeaway-first copy, populate react-card.html, persistent-save, screenshot, deliver. Verify: head -6 SKILL.md shows valid frontmatter; the description is the three-part format ≤200 chars; allowed-tools lists AskUserQuestion, Read, Write, Bash, Glob, Grep, ToolSearch, ExitPlanMode, Skill, SendUserFile; the body names every phase and the GATE RESULT scrub check.templates/react-card.html card template
{{COPY_PANELS}} keeps its standard plugin semantics: the social post copy panel(s) rendered below the card — platform post text plus a copy button — populated per references/copy-panels.md, exactly as in snippet-card.html.Verify
kit/plugins/social-media-tools/templates/react-card.html with four zones — header ({{COMPONENT_NAME}} + {{FRAMEWORK_BADGE}}), a preview pane that injects {{PREVIEW_MARKUP}} as raw skill-authored HTML, an implementation block ({{COMPONENT_CODE}}, highlight.js language-tsx), and a semantic props table ({{PROPS_ROWS}}: name · type · required · default · description) — plus {{REPO_SLUG}}, {{SOURCE_PATH}}, and {{COPY_PANELS}}. Reuse snippet-card's dark-mode tokens, --card-width, and highlight.js CDN. Verify: open the file; all {{…}} variables present; the --card-width CSS custom property is declared in the template's :root; the props table uses <th scope="col">; a header comment states that {{PREVIEW_MARKUP}} is injected raw while {{COMPONENT_CODE}}/{{PROPS_ROWS}}/name/path are HTML-escaped by the skill.references/props-extraction.md reference
Verify
kit/plugins/social-media-tools/skills/share-react/references/props-extraction.md describing how to build the full-API props table: parse a TS interface/type Props or propTypes for name · type · required · default · description; fall back to inferring the list from JSX destructuring/usage when no types exist; emit HTML-escaped <tr> rows for {{PROPS_ROWS}}. Verify: file exists; documents both the typed path and the inference fallback; shows the <tr> row template and the mandatory ampersand-first & < > " escaping order; SKILL.md links to it by relative path.social-share router
Verify
kit/plugins/social-media-tools/skills/social-share/SKILL.md Phase 1 classification table: add a rule that routes any selected/open/path .tsx/.jsx React file to share-react, placed above the existing selection rule (#4) so React files prefer the component card. Verify: re-read the table; a .tsx/.jsx row targets share-react and sits above the share-selection row; renumber the rules and confirm first-match-wins still falls through to share-selection for non-React code.react-card.html in references/variables.md
Verify
react-card.html section to kit/plugins/social-media-tools/references/variables.md — a Contents link plus a variable table for {{COMPONENT_NAME}}, {{FRAMEWORK_BADGE}}, {{PREVIEW_MARKUP}}, {{COMPONENT_CODE}}, {{PROPS_ROWS}}, {{REPO_SLUG}}, {{SOURCE_PATH}}, {{COPY_PANELS}}, with an explicit escaped-vs-raw note. Verify: open variables.md; the Contents list links #react-cardhtml; the table lists all eight variables and flags {{PREVIEW_MARKUP}} as raw and everything else as HTML-escaped.CLAUDE.md)
Verify
share-react to the README's Features table, Skills activation table, and Card Types table, and add the new files to the Plugin Structure tree in kit/plugins/social-media-tools/README.md; update the social-media-tools row in the repo-root CLAUDE.md plugin table to mention share-react. Verify: grep -n share-react kit/plugins/social-media-tools/README.md returns hits in all three tables and the tree; the CLAUDE.md social-media-tools row names share-react.Verify
social-media-tools version in .claude-plugin/marketplace.json from 2.10.1 to 2.11.0 and add react/component/jsx tags; add matching react, component, jsx keywords to kit/plugins/social-media-tools/.claude-plugin/plugin.json; add a ## v2.11.0 — 2026-06-09 entry to kit/plugins/social-media-tools/CHANGELOG.md under an ### Added heading. Verify: a python3 -c read of marketplace.json prints version 2.11.0; the CHANGELOG top entry is v2.11.0; plugin.json keywords include react; marketplace.json still parses.tests/social-media-tools/
tests/<area>/; committing these makes the objective and the wiring re-checkable on every change.Verify
tests/social-media-tools/test-react-card-smoke.sh (populate react-card.html with a sample component + a 3-row props table + a preview block, serve it, assert the preview pane, highlighted code block, and props rows render and no {{…}} placeholders remain) and tests/social-media-tools/test-share-react-registration.sh (assert marketplace version 2.11.0, a share-react router rule, valid skill frontmatter, and README listing). Also add tests/social-media-tools/README.md documenting the manual E2E run procedure (load the plugin, invoke share-react on a sample component, confirm the saved HTML + PNG). Verify: bash tests/social-media-tools/test-react-card-smoke.sh and bash tests/social-media-tools/test-share-react-registration.sh both exit 0, and tests/social-media-tools/README.md exists with the E2E procedure.Tests
File: tests/social-media-tools/test-react-card-smoke.sh
Type: smoke test
Asserts: populating react-card.html with a sample Button.tsx (implementation code + a 3-row props table + a static preview block) yields rendered HTML containing a preview pane, a language-tsx code block, and ≥1 props <tr> row — and zero {{…}} placeholders remain — directly proving the card "shares a React component with a preview of the component and its implementation with props".
Run: bash tests/social-media-tools/test-react-card-smoke.sh
File: tests/social-media-tools/test-share-react-registration.sh
Targets: marketplace.json version, the social-share router table, share-react/SKILL.md frontmatter, the README listing.
Key cases: social-media-tools version equals 2.11.0; the router table contains a .tsx/.jsx → share-react rule above rule #4; SKILL.md frontmatter has name + description + allowed-tools; the README Skills table lists share-react.
File: manual / agent E2E against the loaded plugin (run instructions documented in tests/social-media-tools/README.md, created in Step 8; uses the existing shared references/rendering-pipeline.md plugin reference).
Targets: the full Locate → Capture → Scrub → Extract → Preview → Populate → Screenshot → Deliver path on a real component.
Key cases: invoking share-react on a sample Button.tsx saves both react-<slug>-<date>.html and a matching .png to docs/media/social/; the saved filename follows the react-<slug>-<date> convention matching other share-* outputs; the scrub gate fired; the local HTTP server is killed afterward (no dangling process).
Acceptance Criteria
Verification
Load the plugin with claude --plugin-dir ./kit/plugins/social-media-tools, then confirm end-to-end:
- Typed component. Run share-react against a sample
Button.tsxwith a TS Props interface and confirm one card shows a rendered preview (up to 3 states), the implementation code, and a full props table; a matchingreact-*.html+.pngland indocs/media/social/; copy panels are present; and the security-scrub gate fired in the transcript. - Inference fallback. Run it against an untyped
.jsxcomponent and confirm the props table is inference-populated without crashing. - Router. Ask "share this component" with a
.tsxselected and confirm the router dispatches toshare-react, notshare-selection. - Tests. Run
bash tests/social-media-tools/test-react-card-smoke.shandbash tests/social-media-tools/test-share-react-registration.sh— both exit 0. - Release metadata. Run
/validate-plugin social-media-toolsand confirm marketplace.json parses and the version reads2.11.0.
Completion Checklist
Completion Report
No items to report — all requirements met.
Unresolved Questions
-
How should the props table handle very large prop sets?
The share-react card (kit/plugins/social-media-tools/templates/react-card.html) shows a props table. Decide how to handle components with many props (15+): cap the table to the N most important props with a "+M more" row, scroll the table within a fixed card height, or split into a second card. Recommend one approach consistent with snippet-card's 80-line code cap, specify how the skill signals truncation, and implement it in the template and the props-extraction reference.
-
What should the preview pane show for components with no visual output?
Some React components render nothing visible (context providers, hooks-only wrappers, render-prop components). Decide what share-react's preview pane should show for them: a labeled "no visual output" state, a rendered example of a child/consumer, or a schematic of the provided context. Recommend one default and implement it in the build-static-preview phase of kit/plugins/social-media-tools/skills/share-react/SKILL.md.
Team Review (2026-06-09)
Executive Summary: The plan is well-structured and follows established share-* plugin conventions. All eight steps are actionable and verifiable. Three medium-severity gaps were identified and addressed inline: (1) {{COPY_PANELS}} lacked a population description; (2) --card-width CSS token was not explicitly required in the template verify clause; (3) the E2E test card referenced a tests-directory README that was not in the file list or steps — now resolved in place (README added to Files and Step 8). Note: references/rendering-pipeline.md already exists as a shared plugin reference and needs no creation.
Architecture (fit: sound): Skill follows the share-* skeleton correctly. The raw-inject/escape boundary for {{PREVIEW_MARKUP}} is documented. The router placement (above share-selection) is correct. Gap: persistent-save helper reference is implicit rather than stated; low severity.
Completeness (mostly complete): File tree matches steps. Gap: tests/social-media-tools/README.md was referenced in the E2E test card but not created by any step — resolved: added to the Files tree and Step 8. (references/rendering-pipeline.md already exists at the plugin root and is used as-is.) Gap: {{COPY_PANELS}} had no population description — addressed in Step 2 why clause per references/copy-panels.md.
Testability (good): Objective smoke test and registration test are well-specified. E2E is correctly marked manual. Minor gap: smoke test does not verify --card-width token presence — addressed in Step 2 verify clause.
Risk (low-medium): Router ordering risk is mitigated by the verify clause. Raw HTML injection risk is low (Claude-authored markup). Version bump is verifiable. Saved filename convention (react-<slug>-<date>) clarified in E2E test card.
Conventions (consistent): Naming, file placement, changelog format, tag style all match sibling skills and marketplace rules. No issues.
UX (good): Three-state preview is a meaningful improvement. {{COPY_PANELS}} gap addressed. Platform-aware copy rules are inherited from SOCIAL.md skeleton — acceptable.
Accessibility (good): Props table uses <th scope="col">. Dark-mode tokens reused from validated siblings. Gap: preview markup should include alt attributes for images and aria-label for icon-only elements — low severity, noted for implementer awareness. --card-width token verify clause added.
Inline edits applied:
- Step 2 why clause: added
{{COPY_PANELS}}population description (standard social-copy panels perreferences/copy-panels.md, as in snippet-card.html). - Step 2 verify clause: added explicit check that
--card-widthCSS custom property is declared in the template:root. - E2E test card: added saved filename convention note (
react-<slug>-<date>) and pointed run instructions attests/social-media-tools/README.md(created in Step 8). - Post-review correction: the review's scope question about
references/rendering-pipeline.md+ tests README was resolved in place — the pipeline reference already exists; the tests README was added to Files and Step 8, and the question removed.