feat(web-bundles): add release packager + bundle manifest

Adds the infrastructure for shipping web bundles as downloadable ZIPs
attached to a GitHub Release, consumed by the upcoming
bmadcode.com/web-bundles/ page.

- web-bundles/bundles.json — manifest with persona, tagline, description,
  accent color, motif key, knowledge files, and feature flags
  (web-browsing, deep-research, stitch integration) for each of the 6
  bundles. Top-level releaseTag and downloadUrlPattern so the
  consuming page can construct download URLs without hardcoding.
- tools/bundle-web-bundles.js — packager that zips each bundle dir into
  dist/web-bundles/{slug}.zip and prints the gh release create command.
  Zero dependencies; uses system zip.
- .gitignore — exclude dist/web-bundles/ build artifacts.

The web-bundles-v1.0.0 release on GitHub is currently in draft state
with the 6 zips attached; it'll be published in coordination with the
Ghost site page going live.
This commit is contained in:
Brian Madison 2026-05-25 11:30:30 -05:00
parent cede485217
commit 7f7f5f0458
3 changed files with 211 additions and 0 deletions

3
.gitignore vendored
View File

@ -81,3 +81,6 @@ _bmad/custom/*.user.toml
website/.astro/ website/.astro/
website/dist/ website/dist/
build/ build/
# Web bundle release artifacts
dist/web-bundles/

View File

@ -0,0 +1,68 @@
/**
* Web Bundle Release Packager
*
* Zips each bundle under web-bundles/ into dist/web-bundles/{slug}.zip
* for attachment to a GitHub Release.
*
* Usage:
* node tools/bundle-web-bundles.js
*
* Then upload the resulting zips to a GitHub Release:
* gh release create web-bundles-v1 dist/web-bundles/*.zip \
* --title "Web Bundles v1" \
* --notes "BMad web bundles for Gemini Gems and ChatGPT Custom GPTs"
*/
const fs = require('node:fs');
const path = require('node:path');
const { execSync } = require('node:child_process');
const REPO_ROOT = path.resolve(__dirname, '..');
const BUNDLES_DIR = path.join(REPO_ROOT, 'web-bundles');
const DIST_DIR = path.join(REPO_ROOT, 'dist', 'web-bundles');
const MANIFEST = path.join(BUNDLES_DIR, 'bundles.json');
function main() {
if (!fs.existsSync(MANIFEST)) {
console.error(`Error: bundles.json not found at ${MANIFEST}`);
process.exit(1);
}
const manifest = JSON.parse(fs.readFileSync(MANIFEST, 'utf-8'));
const releaseTag = manifest.releaseTag || 'web-bundles-v1';
fs.mkdirSync(DIST_DIR, { recursive: true });
console.log(`Packaging ${manifest.bundles.length} bundles for release ${releaseTag}\n`);
const zipped = [];
for (const bundle of manifest.bundles) {
const src = path.join(BUNDLES_DIR, bundle.slug);
if (!fs.existsSync(src)) {
console.warn(` [SKIP] ${bundle.slug} — directory not found`);
continue;
}
const out = path.join(DIST_DIR, `${bundle.slug}.zip`);
if (fs.existsSync(out)) fs.unlinkSync(out);
execSync(`zip -r -X -q "${out}" "${bundle.slug}" -x "*.DS_Store"`, {
cwd: BUNDLES_DIR,
stdio: 'inherit',
});
const size = (fs.statSync(out).size / 1024).toFixed(1);
console.log(` [OK] ${bundle.slug}.zip (${size} KB)`);
zipped.push(bundle.slug);
}
console.log(`\nWrote ${zipped.length} bundles to ${path.relative(REPO_ROOT, DIST_DIR)}/`);
console.log('\nNext step — create or update the GitHub Release:\n');
console.log(` gh release create ${releaseTag} dist/web-bundles/*.zip \\`);
console.log(` --title "Web Bundles v1" \\`);
console.log(` --notes "BMad web bundles for Gemini Gems and ChatGPT Custom GPTs. See https://bmadcode.com/web-bundles/"\n`);
console.log('Or, to refresh an existing release:\n');
console.log(` gh release upload ${releaseTag} dist/web-bundles/*.zip --clobber\n`);
}
main();

140
web-bundles/bundles.json Normal file
View File

@ -0,0 +1,140 @@
{
"schemaVersion": "1.0",
"releaseTag": "web-bundles-v1.0.0",
"releasedAt": "2026-05-25",
"downloadUrlPattern": "https://github.com/bmad-code-org/BMAD-METHOD/releases/download/web-bundles-v1.0.0/{slug}.zip",
"bundles": [
{
"slug": "brainstorming-coach",
"name": "Brainstorming Coach",
"tagline": "Facilitated ideation across 60+ techniques",
"description": "Unlock creativity through guided exploration. The coach walks you through proven brainstorming methods — divergent, convergent, lateral — and helps you converge to a decision worth acting on.",
"defaultPersona": {
"name": "Carson",
"title": "Elite Brainstorming Specialist",
"lineage": "Osborn lineage"
},
"swapPersona": {
"name": "Mary",
"title": "Strategic Business Analyst",
"lineage": "BMad analyst — research-first rigor"
},
"accentColor": "#3b82f6",
"motif": "constellation",
"knowledgeFiles": ["SKILL.md", "brain-methods.csv"],
"needsWebBrowsing": true,
"needsDeepResearch": false,
"stitchIntegration": false
},
{
"slug": "product-brief-coach",
"name": "Product Brief Coach",
"tagline": "Build a one-page product brief through guided discovery",
"description": "Shape a raw idea, evolve an existing brief, or pressure-test a draft before it goes downstream. The coach mirrors before pushing, names the assumption hiding under your confident sentence, and refuses to write the brief for you.",
"defaultPersona": {
"name": "Mary",
"title": "Strategic Business Analyst",
"lineage": "BMad analyst"
},
"swapPersona": {
"name": "Iris",
"title": "Senior Product Strategist",
"lineage": "Mirror-then-push, unhurried thinking-partner voice"
},
"accentColor": "#d4a853",
"motif": "single-page",
"knowledgeFiles": ["SKILL.md"],
"needsWebBrowsing": true,
"needsDeepResearch": false,
"stitchIntegration": false
},
{
"slug": "prfaq-coach",
"name": "PRFAQ Coach",
"tagline": "Working Backwards challenge to forge product concepts",
"description": "Write the press release first. Stress-test a product concept against the customer who will actually buy it, before any building begins. Customer-first by force of method.",
"defaultPersona": {
"name": "Mary",
"title": "Strategic Business Analyst",
"lineage": "BMad analyst"
},
"swapPersona": {
"name": "Bezos",
"title": "Working Backwards Coach",
"lineage": "Amazon discipline — direct, dry, customer-first"
},
"accentColor": "#dc2626",
"motif": "document-ribbon",
"knowledgeFiles": ["SKILL.md"],
"needsWebBrowsing": true,
"needsDeepResearch": false,
"stitchIntegration": false
},
{
"slug": "prd-coach",
"name": "PRD Coach",
"tagline": "Product Requirements with built-in validation",
"description": "Coach a PRD that engineering can actually build from. Capabilities go in the PRD, mechanism in the Addendum. Validation pass surfaces the gap between what you said and what you meant.",
"defaultPersona": {
"name": "John",
"title": "Product Manager",
"lineage": "BMad PM — Cagan lineage"
},
"swapPersona": {
"name": "Ezra",
"title": "Principal Product Manager",
"lineage": "Calmer, slower-tempo coaching"
},
"accentColor": "#6366f1",
"motif": "section-stack",
"knowledgeFiles": ["SKILL.md", "prd-template.md", "prd-validation-checklist.md"],
"needsWebBrowsing": true,
"needsDeepResearch": false,
"stitchIntegration": false
},
{
"slug": "ux-coach",
"name": "UX Coach",
"tagline": "UX patterns, flows, and design specifications",
"description": "Build spines engineering can take and ship. Pressure-test hierarchy, behavior, and visual logic. Hand-off-ready specs with optional Stitch integration for editable mockups.",
"defaultPersona": {
"name": "Sally",
"title": "UX Designer",
"lineage": "BMad UX designer"
},
"swapPersona": {
"name": "Kenji",
"title": "Principal Product Designer",
"lineage": "Rams restraint + Zhuo systems discipline"
},
"accentColor": "#10b981",
"motif": "nested-layers",
"knowledgeFiles": ["SKILL.md", "ux-validation.md"],
"needsWebBrowsing": true,
"needsDeepResearch": false,
"stitchIntegration": true
},
{
"slug": "market-and-industry-research",
"name": "Market & Industry Research",
"tagline": "Competitive landscape, JTBD, segments — Deep Research integrated",
"description": "Market research that drives a positioning decision, not a deliverable. Segments, competitive alternatives, regulatory and technical lenses. Uses Deep Research for the heavy lift.",
"defaultPersona": {
"name": "Mary",
"title": "Strategic Business Analyst",
"lineage": "BMad analyst"
},
"swapPersona": {
"name": "Geoff",
"title": "Market Strategist",
"lineage": "Geoffrey Moore + April Dunford lineage"
},
"accentColor": "#f59e0b",
"motif": "positioning-rings",
"knowledgeFiles": ["SKILL.md"],
"needsWebBrowsing": true,
"needsDeepResearch": true,
"stitchIntegration": false
}
]
}