A tool for generating thumbnails, announcement content, and translations — starting with Steam. The architecture separates portable core logic from platform-specific mediums so the same engine can power a Chrome extension, web app, CLI, or bot.
V1 Milestone: Context Capture — automatically detecting and extracting game data from Steam pages.
- Chrome extension detects Steam announcement editor pages and extracts App ID, event title, subtitle, and body
- Fetches game metadata from the Steam Store API (name, description, genres, tags, screenshots, developer, publisher, release status)
- Extracts a structured color palette from game capsule art (k-means clustering with primary/secondary/accent/neutral roles, vibrancy + luminance classification)
- Persists game profiles in extension storage for instant loading on return visits
- Debug view for inspecting all captured context
- Automated validation — full type-check, unit, and E2E test pipeline via
npm run verify
# Install dependencies
npm install
# Install Playwright's Chromium binary (one-time, for E2E tests)
npx playwright install chromium
# Build the Chrome extension
npm run build:ext- Open Chrome and go to
chrome://extensions/ - Enable Developer mode (top-right toggle)
- Click Load unpacked
- Select
extensions/chrome/dist - Navigate to a Steam page and click the extension icon
After loading, refresh any Steam pages that were already open so the content script injects.
Every feature is validated through three layers. One entry point:
npm run verifyThis runs types → unit → e2e and exits non-zero on any failure. Use it before declaring a change done.
| Command | What it runs | Speed |
|---|---|---|
npm run verify |
Full pipeline (types + unit + e2e) | ~15s |
npm run verify:types |
tsc --noEmit on core and chrome |
~2s |
npm run verify:unit |
Vitest contract tests against committed fixtures | ~3s |
npm run verify:e2e |
Builds extension + Playwright tests | ~10s |
Structured JSON reports land in .verify/unit.json and .verify/e2e.json for scripting or agent consumption.
Pure core functions (parseSteamAppDetails, extractPaletteFromImageData, fetchStoreMetadata) are tested in packages/core/tests/ against committed Steam snapshots. No network. Deterministic via seeded k-means++ init + pinned fixture inputs.
Playwright launches Chromium with the built extension loaded, intercepts every Steam network call with committed fixtures, navigates to a mocked Steam app page, and asserts the content-script → service-worker messaging path updates the action badge. No live Steam calls ever.
Tests live in extensions/chrome/tests/e2e/.
All tests use committed snapshots of real Steam responses from packages/core/tests/fixtures/:
api/<appId>.json— appdetails API responseimages/<appId>-capsule.jpg,<appId>-header.jpg— capsule and header artpages/<appId>.html— store page HTML (for DOM-parsing tests)
To refresh from live Steam:
npm run refresh-fixtures -- 1366800 <more-app-ids>Commit the resulting diff. The diff is the signal for Steam schema drift — review it before merging.
Regenerate Vitest snapshot files (__snapshots__/) only when a behavior change is intentional:
npm --prefix packages/core run test:updateAnnounceKit/
├── packages/core/ # Platform-agnostic types, API parsing, palette extraction
│ ├── src/ # Contracts: result, store-metadata, palette, steam-page, cache, ...
│ ├── tests/ # Vitest contract tests + fixtures
│ └── vitest.config.ts
├── extensions/chrome/ # Chrome extension (Manifest V3, React, Tailwind)
│ ├── src/ # Content script, service worker, popup UI, storage
│ └── tests/e2e/ # Playwright extension tests
├── scripts/
│ └── refresh-fixtures.ts # Captures live Steam → commits into packages/core/tests/fixtures/
├── playwright.config.ts
├── CLAUDE.md # Working agreement for AI agents
├── ARCHITECTURE.md # Core vs medium, contracts, data flow, build system
└── package.json # npm workspaces root + verify scripts
| Script | Purpose |
|---|---|
npm run build:ext |
Full extension build with tsc type-check |
npm run build:ext:vite |
Extension build via vite only (skip tsc — for iterating when types are in flux) |
npm run refresh-fixtures -- <appId>... |
Re-capture Steam fixtures |
npm run verify |
Types + unit + e2e |
npm --prefix packages/core run test:watch |
Live Vitest on core |
npm --prefix packages/core run test:update |
Regenerate Vitest snapshots |
- ARCHITECTURE.md — Core vs medium separation, data flow, contract signatures, build system
- CLAUDE.md — Working agreement for AI agents (contract conventions, verify pipeline, fixture discipline)