Skip to content

starter-series/shotkit

shotkit

Capture store + social promo assets from a built browser extension — with Playwright.

Screenshots · promo images · demo screencast · listing copy. One command.

npm License: MIT Node ≥ 22

English | 한국어


Part of Starter Series — reusable tooling, not just clone-templates. shotkit is the first capability extracted into an installable package so any repo (and any agent) can use it without copy-paste.


Status & Scope

  • Currently implemented — A Playwright capture engine (build → launch the built extension via launchPersistentContext(--load-extension) → drive scenes → screenshot → caption/disclaimer band → promo tile from HTML → demo webm → listing copy from STORE_LISTING.md), a CLI (shotkit) with an agent contract (--json machine output, optional path argument, 0/1/2 exit codes), size presets for both audiences (CWS 1280×800/440×280, SNS 1200×675/1200×630/1080×1080), a path-traversal-safe localhost fixture server, a programmatic API (capture()), a Claude Code skill (skills/capture/), an AGENTS.md run-block so any shell-having coding agent can invoke it, and the npm package @starter-series/shotkit. Consumed by browser-extension-starter and skillBridge.
  • Planned — a listing in the starter-series plugin marketplace; video editing (webm → mp4, trim, captions) for SNS.
  • Design intentOne engine, many surfaces — matched to the tool's nature. shotkit is a heavy, file-producing build tool, so its surfaces are CLI (+--json), skill, and CI — not MCP (see Non-goals). Captures are deterministic (login-free fixtures, frozen data) and the run doubles as a real-bundle smoke test — a screenshot only appears if that feature rendered from the shipped code. Trademark-safe by construction: a disclaimer band is composited onto every shot.
  • Non-goals — An MCP server (dropped by design: agents with a shell get a better contract from --json + the skill, without MCP's per-session context cost; nothing here is a fast structured query). Removing the per-repo scene config (which screens are your money shots is irreducible intent — it lives in your shotkit.config.js). A general-purpose video editor (v1 records a clean screencast; editing is Planned). A hosted service (file-touching capture is local by nature).
  • Redacted — none. Ships no private data, credentials, or third-party identifiers.

Install

npm i -D @starter-series/shotkit
npx playwright install chromium    # one-time: the browser shotkit drives

Zero-install in any repo that has a config:

npx @starter-series/shotkit

shotkit launches the full Chromium (channel: 'chromium') — never the default headless-shell, which strips the extension subsystem. Headless works (HEADED=0; verified on macOS and Linux CI, video included) and is the CI default in the starter's capture workflow; the local default stays headed for easy debugging. Headed-under-xvfb proved unreliable on CI runners (the 8-bit default breaks Chromium's screenshot capture, and a 24-bit screen still failed silently) — run headless in CI.

Usage

Add a shotkit.config.js (the per-repo seam — see the contract below), then:

shotkit                         # produce everything into outDir
shotkit --scene 01-feature      # just one scene/promoTile/demo, or "description"
shotkit --no-video              # skip the screencast (faster/CI)
shotkit --no-build              # use an already-built bundle
shotkit ../my-extension --json  # run against another checkout; JSON result on stdout

Outputs land in outDir (default store-assets/): <scene>.png, <promoTile>.png, <demo>.webm, description.md.

Agent contract (--json)

shotkit [path] --json prints exactly one JSON object to stdout (progress logs move to stderr):

{ "ok": true, "outDir": "/abs/store-assets", "produced": ["/abs/store-assets/01-popup.png"] }

Exit codes: 0 ok · 1 runtime failure (stderr carries {"ok":false,"error":…}) · 2 usage / no config found. Drop-in agent wiring: the run-block in AGENTS.md (read by Claude Code, Codex, Cursor, Gemini CLI, …) and the skills/capture/ skill (Agent Skills format — copy the folder into any compatible tool's skills directory).

Config contract (shotkit.config.js)

const { serveDirectory, stageExtension, patchManifestForLocalhost } = require('@starter-series/shotkit');

module.exports = {
  build: 'npm run build',                 // run first → real-bundle smoke test (optional)
  prepareExtension: () => '<unpacked dir>', // dir to --load-extension (often a patched temp copy)
  outDir: 'store-assets',
  disclaimer: 'Unofficial · not affiliated with …', // composited onto every shot (optional)
  description: { from: 'store-assets/STORE_LISTING.md' }, // → description.md (optional)

  async setup({ context, extensionId, flags }) {  // e.g. start a fixture server / stubs
    return { env: { baseUrl }, teardown: async () => {} };
  },

  scenes: [
    { name: '01-feature', preset: 'cws-screenshot', caption: 'What this shows',
      async run({ page, context, extensionId, env, baseUrl, flags }) {
        await page.goto(`${env.baseUrl}/page`);  // drive the UI, wait until rendered
      } },
  ],

  promoTiles: [{ name: 'promo', template: 'path/to/promo.html', preset: 'cws-promo-small',
                 replacements: { NAME: 'My Ext' } }],

  demo: { name: 'demo', preset: 'cws-screenshot', async run({ page, env }) { /* walkthrough */ } },
};
  • A scene/tile takes a preset name or an explicit { width, height } (see PRESETS).
  • The harness reduces a captioned scene's capture height by the band height and stacks the band under it, so the final image is exactly the preset size and no UI is hidden.

Public API

require('@starter-series/shotkit')capture(config, opts) · serveDirectory · stageExtension · patchManifestForLocalhost · launchWithExtension · closeContext · compositeCaption · renderPromoTile · extractListing · renderDescriptionDoc · PRESETS · resolveSize.

Roadmap — one engine, many surfaces

Surface Status For
CLI (shotkit, npx) with --json + path ✅ now humans / CI / shell-having agents
Programmatic capture() ✅ now embedding
Claude Code skill (skills/capture/) ✅ now Claude Code (portable to Codex/Cursor/Gemini via the Agent Skills format)
AGENTS.md run-block ✅ now every agent that reads AGENTS.md
npm package (@starter-series/shotkit) ✅ now npx zero-install
Capture-in-CI GitHub Action ✅ now — ships in browser-extension-starter's capture.yml (headless) zero-local-browser runs + CI smoke test
starter-series marketplace entry planned discovery
Video editing (webm→mp4, trim, captions) planned SNS clips

An MCP stdio tool was considered and dropped — see Non-goals: shotkit is a heavy, file-producing build tool, so a --json CLI + skill serves agents better than an MCP server's per-session context cost.

Generalization rule (for the next capability in the series): one npm package (engine + thin CLI), one *.config.js seam for irreducible per-repo intent, agent surfaces matched to the tool's nature (fast/structured: an MCP tool taking a path; heavy/build-time: a --json CLI + skill + AGENTS.md run-block), one marketplace entry. The engine never reads project specifics except through the config seam.

License

MIT © heznpc

About

Capture Chrome Web Store + social promo assets (screenshots, promo images, demo video) from a built browser extension with Playwright.

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors