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:
parent
cede485217
commit
7f7f5f0458
|
|
@ -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/
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
@ -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
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue