feat(docs): add Getting Started tutorial and simplify build script

- Add comprehensive Getting Started tutorial with installation as Step 1
- Simplify build-docs.js to read directly from docs/ (no consolidation)
- Remove backup/restore dance that could corrupt docs folder on build failure
- Remove ~150 lines of unused consolidation code

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
forcetrainer 2026-01-03 17:30:56 -05:00 committed by Alex Verkhovsky
parent 5d1f820f82
commit 10d99b17e2
2 changed files with 364 additions and 233 deletions

View File

@ -0,0 +1,343 @@
---
sidebar_label: Getting Started
description: Install BMAD and create your first planning document
---
# Getting Started with BMAD
Learn how to build software with BMAD's AI-powered workflows. By the end of this tutorial, you'll have installed BMAD, initialized a project, and created your first planning document.
## What You'll Learn
- How to install and configure BMAD for your IDE
- How BMAD organizes work into phases and agents
- How to initialize a project and choose a planning track
- How to create your first requirements document
## Prerequisites
Before starting, ensure you have:
- **Node.js 20+** — Required for the installer
- **Git** — Recommended for version control
- **AI-powered IDE** — Claude Code, Cursor, Windsurf, or similar
- **A project idea** — Even a simple one works for learning
---
## Step 1: Install BMAD
Open a terminal in your project directory and run:
```bash
npx bmad-method install
```
The interactive installer guides you through setup:
### 1.1 Choose Installation Location
Select where to install BMAD files:
- **Current directory** — Recommended for new projects
- **Subdirectory** — If you want BMAD isolated
- **Custom path** — For specific project structures
### 1.2 Select Your AI Tool
Choose the IDE you'll be using:
- Claude Code
- Cursor
- Windsurf
- Other
The installer configures BMAD to work with your selected tool.
### 1.3 Choose Modules
For this tutorial, select **BMM** (BMAD Method) — the core module for software development. You can add other modules later:
| Module | Purpose |
| -------- | ----------------------------------------- |
| **BMM** | Core methodology for software development |
| **BMGD** | Game development workflows |
| **CIS** | Creative intelligence and facilitation |
| **BMB** | Building custom agents and workflows |
### 1.4 Accept Default Configuration
For your first project, accept the recommended defaults. You can customize settings later in `_bmad/[module]/config.yaml`.
### 1.5 Verify Installation
After installation completes, verify by checking your project structure:
```
your-project/
├── _bmad/
│ ├── bmm/ # Method module
│ │ ├── agents/ # Agent files
│ │ ├── workflows/ # Workflow files
│ │ └── config.yaml # Module config
│ └── core/ # Core utilities
├── _bmad-output/ # Generated artifacts (created later)
└── .claude/ # IDE configuration (if using Claude Code)
```
> **Having trouble?** See [Install BMAD](../../how-to/installation/install-bmad.md) for troubleshooting common issues.
---
## Step 2: Understand How BMAD Works
Before diving in, let's understand BMAD's core concepts.
### Phases
BMAD organizes work into four phases:
```
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Phase 1 │ │ Phase 2 │ │ Phase 3 │ │ Phase 4 │
│ Analysis │ → │ Planning │ → │ Solutioning │ → │Implementation│
│ (Optional) │ │ (Required) │ │ (Varies) │ │ (Required) │
└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘
Brainstorm Requirements Architecture Build code
Research PRD or tech-spec Design decisions Story by story
```
### Agents
Agents are specialized AI personas, each expert in their domain:
- **Analyst** — Initializes projects, tracks progress, conducts research
- **PM** — Creates requirements (PRD or tech-spec)
- **UX-Designer** — Designs user interfaces and experiences
- **Architect** — Makes technical decisions, designs system architecture
- **SM (Scrum Master)** — Manages sprints, creates stories
- **DEV** — Implements code, reviews work
### Workflows
Workflows are guided processes that agents run. You tell an agent to run a workflow, and it walks you through the process interactively.
### Planning Tracks
Based on your project's complexity, BMAD offers three tracks:
| Track | Best For | Documents Created |
| --------------- | ------------------------------------------ | ------------------------------ |
| **Quick Flow** | Bug fixes, simple features, clear scope | Tech-spec only |
| **BMAD Method** | Products, platforms, complex features | PRD + Architecture + UX |
| **Enterprise** | Compliance, multi-tenant, enterprise needs | PRD + Architecture + Security + DevOps |
---
## Step 3: Initialize Your Project
Now let's set up your project with BMAD.
### 3.1 Load the Analyst Agent
In your IDE, load the Analyst agent. The method depends on your IDE:
- **Claude Code**: Type `/analyst` or load the agent file directly
- **Cursor/Windsurf**: Open the agent file from `_bmad/bmm/agents/`
Wait for the agent's menu to appear. You'll see a list of available workflows.
### 3.2 Run the Initialization Workflow
Tell the agent to initialize your project:
```
Run workflow-init
```
Or use the shorthand:
```
*workflow-init
```
### 3.3 Describe Your Project
The workflow asks you to describe:
- **Your project and goals** — What are you building? What problem does it solve?
- **Existing codebase** — Is this a new project (greenfield) or existing code (brownfield)?
- **Size and complexity** — Roughly how big is this? (You can adjust later)
### 3.4 Choose Your Track
Based on your description, the workflow suggests a planning track. You can accept the suggestion or choose a different one:
- Choose **Quick Flow** if you have a clear, bounded task
- Choose **BMAD Method** for most new products or features
- Choose **Enterprise** if you have compliance or security requirements
For this tutorial, we'll assume you chose **BMAD Method**.
### 3.5 Confirm and Create
Once you confirm, the workflow creates `bmm-workflow-status.yaml` in your project's docs folder. This file tracks your progress through all phases.
> **Important**: Always start a fresh chat for each workflow. This prevents context limitations from causing issues.
---
## Step 4: Create Your Requirements Document
With your project initialized, it's time to create your first planning document — the PRD (Product Requirements Document).
### 4.1 Start a Fresh Chat
Close your current chat and start a new one. This ensures the agent has full context capacity for the workflow.
### 4.2 Load the PM Agent
Load the PM (Product Manager) agent in your IDE.
### 4.3 Run the PRD Workflow
Tell the PM agent:
```
Run prd
```
Or use shortcuts:
- `*prd`
- Select "create-prd" from the menu
- Say "Let's create a new PRD"
### 4.4 Work Through the PRD
The PM agent guides you through creating your PRD interactively:
1. **Project overview** — Refine your project description
2. **Goals and success metrics** — What does success look like?
3. **User personas** — Who uses this product?
4. **Functional requirements** — What must the system do?
5. **Non-functional requirements** — Performance, security, scalability needs
Answer the agent's questions thoughtfully. The PRD becomes the foundation for everything that follows.
### 4.5 Review Your PRD
When complete, you'll have a `PRD.md` file in your `_bmad-output/` folder. Review it to ensure it captures your vision.
---
## Step 5: Check Your Progress
At any point, you can check what to do next.
### 5.1 Load Any Agent
Start a fresh chat and load any BMAD agent.
### 5.2 Ask for Status
Tell the agent:
```
workflow-status
```
The agent reads your `bmm-workflow-status.yaml` and tells you:
- Which phase you're in
- What workflows are complete
- What the next recommended or required step is
Example response:
```
Phase 2 (Planning) complete:
✓ PRD created
Next recommended steps:
- UX Design (optional, if your project has a UI)
- Architecture (required for BMAD Method track)
Agent: architect
Command: create-architecture
```
---
## What You've Accomplished
You've completed the foundation of a BMAD project:
- Installed BMAD and configured it for your IDE
- Initialized a project with your chosen planning track
- Created a PRD that defines your product requirements
Your project now has:
```
your-project/
├── _bmad/ # BMAD configuration
├── _bmad-output/
│ ├── PRD.md # Your requirements document
│ └── bmm-workflow-status.yaml # Progress tracking
└── ...
```
---
## Next Steps
Continue building your project by designing your system's technical foundation (required for BMAD Method) and then starting implementation story by story.
Explore related topics:
- **[What Are Agents?](../../explanation/core-concepts/what-are-agents.md)** — Deep dive into how agents work
- **[What Are Workflows?](../../explanation/core-concepts/what-are-workflows.md)** — Understanding BMAD's workflow system
- **[Workflow Reference](../../reference/workflows/index.md)** — Complete list of available workflows
---
## Quick Reference
Commands you learned in this tutorial:
| Command | Agent | Purpose |
| ---------------- | ------- | ---------------------------------- |
| `*workflow-init` | Analyst | Initialize a new project |
| `*prd` | PM | Create a Product Requirements Document |
| `workflow-status`| Any | Check progress and next steps |
> **Tip**: Agents are flexible with commands. Menu numbers, shortcuts (`*prd`), or natural language ("Let's create a PRD") all work.
---
## Common Questions
**Q: Do I need to create a PRD for every project?**
Only for BMAD Method and Enterprise tracks. Quick Flow projects use a simpler tech-spec instead.
**Q: Can I skip Phase 1 (Analysis)?**
Yes, Phase 1 is optional. If you already know what you're building, start with Phase 2 (Planning).
**Q: What if I want to brainstorm first?**
Load the Analyst agent and run `*brainstorm-project` before `workflow-init`.
**Q: Why start fresh chats for each workflow?**
Workflows are context-intensive. Reusing chats can cause the AI to hallucinate or lose track of details. Fresh chats ensure maximum context capacity.
---
## Getting Help
- **During workflows**: Agents guide you with questions and explanations
- **Check status**: Run `workflow-status` with any agent
- **Community**: [Discord](https://discord.gg/gk8jAdXWmj) — #general-dev, #bugs-issues
- **Video tutorials**: [BMad Code YouTube](https://www.youtube.com/@BMadCode)

View File

@ -28,12 +28,6 @@ const REPO_URL = 'https://github.com/bmad-code-org/BMAD-METHOD';
const LLM_MAX_CHARS = 600_000;
const LLM_WARN_CHARS = 500_000;
const MODULES = ['bmm', 'bmb', 'bmgd', 'cis'];
// No root docs copied - only docs/ folder content goes to site
// README.md, CHANGELOG.md etc. link to GitHub
const ROOT_DOCS = [];
const LLM_EXCLUDE_PATTERNS = ['changelog', 'ide-info/', 'v4-to-v6-upgrade', 'downloads/', 'faq'];
// =============================================================================
@ -50,11 +44,11 @@ async function main() {
cleanBuildDirectory();
const consolidatedDir = consolidateDocs();
const artifactsDir = await generateArtifacts(consolidatedDir);
const siteDir = buildDocusaurusSite(artifactsDir);
const docsDir = path.join(PROJECT_ROOT, 'docs');
const artifactsDir = await generateArtifacts(docsDir);
const siteDir = buildDocusaurusSite();
printBuildSummary(consolidatedDir, artifactsDir, siteDir);
printBuildSummary(docsDir, artifactsDir, siteDir);
}
main().catch((error) => {
@ -66,31 +60,15 @@ main().catch((error) => {
// Pipeline Stages
// =============================================================================
function consolidateDocs() {
printHeader('Consolidating documentation sources');
const outputDir = path.join(BUILD_DIR, 'consolidated');
fs.mkdirSync(outputDir, { recursive: true });
copyMainDocs(outputDir);
copyRootDocs(outputDir);
copyModuleDocs(outputDir);
const mdCount = countMarkdownFiles(outputDir);
console.log();
console.log(` \u001B[32m✓\u001B[0m Consolidation complete: ${mdCount} markdown files`);
return outputDir;
}
async function generateArtifacts(consolidatedDir) {
async function generateArtifacts(docsDir) {
printHeader('Generating LLM files and download bundles');
const outputDir = path.join(BUILD_DIR, 'artifacts');
copyDirectory(consolidatedDir, outputDir);
fs.mkdirSync(outputDir, { recursive: true });
// Generate LLM files reading from docs/, output to artifacts/
generateLlmsTxt(outputDir);
generateLlmsFullTxt(outputDir);
generateLlmsFullTxt(docsDir, outputDir);
await generateDownloadBundles(outputDir);
console.log();
@ -99,21 +77,14 @@ async function generateArtifacts(consolidatedDir) {
return outputDir;
}
function buildDocusaurusSite(artifactsDir) {
function buildDocusaurusSite() {
printHeader('Building Docusaurus site');
const siteDir = path.join(BUILD_DIR, 'site');
const mainDocs = path.join(PROJECT_ROOT, 'docs');
const docsBackup = path.join(BUILD_DIR, 'docs-backup');
backupAndReplaceDocs(mainDocs, docsBackup, artifactsDir);
try {
runDocusaurusBuild(siteDir);
} finally {
restoreDocs(mainDocs, docsBackup);
}
const artifactsDir = path.join(BUILD_DIR, 'artifacts');
// Build directly from docs/ - no backup/restore needed
runDocusaurusBuild(siteDir);
copyArtifactsToSite(artifactsDir, siteDir);
console.log();
@ -122,56 +93,6 @@ function buildDocusaurusSite(artifactsDir) {
return siteDir;
}
// =============================================================================
// Documentation Consolidation
// =============================================================================
function copyMainDocs(destDir) {
console.log(' → Copying main docs...');
const docsDir = path.join(PROJECT_ROOT, 'docs');
// Include modules folder - docs now live in docs/modules/ instead of src/modules/*/docs/
copyDirectory(docsDir, destDir, ['llms.txt', 'llms-full.txt'], true);
}
function copyRootDocs(destDir) {
console.log(' → Copying root documentation files...');
for (const doc of ROOT_DOCS) {
const srcPath = path.join(PROJECT_ROOT, doc.src);
const destPath = path.join(destDir, doc.dest);
if (fs.existsSync(srcPath)) {
let content = fs.readFileSync(srcPath, 'utf-8');
if (!content.startsWith('---')) {
content = `---\ntitle: "${doc.title}"\n---\n\n${content}`;
}
content = transformMarkdownLinks(content);
fs.writeFileSync(destPath, content);
console.log(` ${doc.src}${doc.dest}`);
}
}
}
function copyModuleDocs(destDir) {
fs.mkdirSync(path.join(destDir, 'modules'), { recursive: true });
for (const moduleName of MODULES) {
const srcPath = path.join(PROJECT_ROOT, 'src', 'modules', moduleName, 'docs');
const moduleDest = path.join(destDir, 'modules', moduleName);
if (fs.existsSync(srcPath)) {
console.log(` → Copying ${moduleName} docs...`);
copyDirectory(srcPath, moduleDest, [], false, moduleName);
const count = countMarkdownFiles(moduleDest);
console.log(` ${count} markdown files`);
} else {
console.log(` ⚠ WARNING: ${moduleName} docs not found`);
}
}
}
// =============================================================================
// LLM File Generation
// =============================================================================
@ -220,11 +141,11 @@ function generateLlmsTxt(outputDir) {
console.log(` Generated llms.txt (${content.length.toLocaleString()} chars)`);
}
function generateLlmsFullTxt(outputDir) {
function generateLlmsFullTxt(docsDir, outputDir) {
console.log(' → Generating llms-full.txt...');
const date = new Date().toISOString().split('T')[0];
const files = getAllMarkdownFiles(outputDir);
const files = getAllMarkdownFiles(docsDir);
const output = [
'# BMAD Method Documentation (Full)',
@ -244,7 +165,7 @@ function generateLlmsFullTxt(outputDir) {
continue;
}
const fullPath = path.join(outputDir, mdPath);
const fullPath = path.join(docsDir, mdPath);
try {
const content = readMarkdownContent(fullPath);
output.push(`<document path="${mdPath}">`, content, '</document>', '');
@ -352,18 +273,6 @@ async function generatePromptsBundle(downloadsDir) {
// Docusaurus Build
// =============================================================================
function backupAndReplaceDocs(mainDocs, backupDir, artifactsDir) {
console.log(' → Preparing docs for Docusaurus...');
if (fs.existsSync(mainDocs)) {
copyDirectory(mainDocs, backupDir);
fs.rmSync(mainDocs, { recursive: true });
}
copyDirectory(artifactsDir, mainDocs, ['llms.txt', 'llms-full.txt']);
removeZipFiles(path.join(mainDocs, 'downloads'));
}
function runDocusaurusBuild(siteDir) {
console.log(' → Running docusaurus build...');
execSync('npx docusaurus build --config website/docusaurus.config.js --out-dir ' + siteDir, {
@ -372,16 +281,6 @@ function runDocusaurusBuild(siteDir) {
});
}
function restoreDocs(mainDocs, backupDir) {
console.log(' → Restoring original docs...');
fs.rmSync(mainDocs, { recursive: true });
if (fs.existsSync(backupDir)) {
copyDirectory(backupDir, mainDocs);
fs.rmSync(backupDir, { recursive: true });
}
}
function copyArtifactsToSite(artifactsDir, siteDir) {
console.log(' → Copying artifacts to site...');
@ -394,28 +293,18 @@ function copyArtifactsToSite(artifactsDir, siteDir) {
}
}
function removeZipFiles(dir) {
if (!fs.existsSync(dir)) return;
for (const file of fs.readdirSync(dir)) {
if (file.endsWith('.zip')) {
fs.unlinkSync(path.join(dir, file));
}
}
}
// =============================================================================
// Build Summary
// =============================================================================
function printBuildSummary(consolidatedDir, artifactsDir, siteDir) {
function printBuildSummary(docsDir, artifactsDir, siteDir) {
console.log();
printBanner('Build Complete!');
console.log();
console.log('Build artifacts:');
console.log(` Consolidated docs: ${consolidatedDir}`);
console.log(` Generated files: ${artifactsDir}`);
console.log(` Final site: ${siteDir}`);
console.log(` Source docs: ${docsDir}`);
console.log(` Generated files: ${artifactsDir}`);
console.log(` Final site: ${siteDir}`);
console.log();
console.log(`Deployable output: ${siteDir}/`);
console.log();
@ -461,7 +350,7 @@ function cleanBuildDirectory() {
fs.mkdirSync(BUILD_DIR, { recursive: true });
}
function copyDirectory(src, dest, exclude = [], transformMd = false, moduleName = null) {
function copyDirectory(src, dest, exclude = []) {
if (!fs.existsSync(src)) return false;
fs.mkdirSync(dest, { recursive: true });
@ -472,12 +361,7 @@ function copyDirectory(src, dest, exclude = [], transformMd = false, moduleName
const destPath = path.join(dest, entry.name);
if (entry.isDirectory()) {
copyDirectory(srcPath, destPath, exclude, transformMd, moduleName);
} else if (entry.name.endsWith('.md')) {
// Always transform markdown links, use module context if provided
let content = fs.readFileSync(srcPath, 'utf-8');
content = transformMarkdownLinks(content, moduleName);
fs.writeFileSync(destPath, content);
copyDirectory(srcPath, destPath, exclude);
} else {
fs.copyFileSync(srcPath, destPath);
}
@ -485,102 +369,6 @@ function copyDirectory(src, dest, exclude = [], transformMd = false, moduleName
return true;
}
function transformMarkdownLinks(content, moduleName = null) {
// Transform HTML img src attributes for module docs images
content = content.replaceAll(/src="\.\/src\/modules\/([^/]+)\/docs\/images\/([^"]+)"/g, (match, mod, file) => {
return `src="./modules/${mod}/images/${file}"`;
});
return content.replaceAll(/\]\(([^)]+)\)/g, (match, url) => {
// src/modules/{mod}/docs/{path}.md → ./modules/{mod}/{path}.md
// Keeps .md - Docusaurus handles .md → page conversion
const docsMatch = url.match(/^\.\.?\/src\/modules\/([^/]+)\/docs\/(.+\.md)$/);
if (docsMatch) return `](./modules/${docsMatch[1]}/${docsMatch[2]})`;
// src/modules/{mod}/docs/ → ./modules/{mod}/
const docsDirMatch = url.match(/^\.\.?\/src\/modules\/([^/]+)\/docs\/$/);
if (docsDirMatch) return `](./modules/${docsDirMatch[1]}/)`;
// src/modules/{mod}/docs/images/{file} → ./modules/{mod}/images/{file}
const docsImageMatch = url.match(/^\.\.?\/src\/modules\/([^/]+)\/docs\/images\/(.+)$/);
if (docsImageMatch) return `](./modules/${docsImageMatch[1]}/images/${docsImageMatch[2]})`;
// src/modules/{mod}/README.md → GitHub (not in docs folder)
const readmeMatch = url.match(/^\.\.?\/src\/modules\/([^/]+)\/README\.md$/i);
if (readmeMatch) return `](${REPO_URL}/blob/main/src/modules/${readmeMatch[1]}/README.md)`;
// src/modules/* (non-docs) → GitHub
const srcMatch = url.match(/^\.\.?\/src\/modules\/(.+)$/);
if (srcMatch) return `](${REPO_URL}/tree/main/src/modules/${srcMatch[1]})`;
// Relative paths escaping docs/ folder → GitHub (when module context is known)
// e.g., ../workflows/foo/bar.md from within docs/ → src/modules/{mod}/workflows/foo/bar.md
if (moduleName) {
const relativeEscapeMatch = url.match(/^\.\.\/([^.][^)]+)$/);
if (relativeEscapeMatch && !relativeEscapeMatch[1].startsWith('src/')) {
const relativePath = relativeEscapeMatch[1];
return `](${REPO_URL}/blob/main/src/modules/${moduleName}/${relativePath})`;
}
}
// ./docs/{path}.md → ./{path}.md (docs folder contents are at root in build)
// Keeps .md - Docusaurus handles .md → page conversion
const rootDocsMatch = url.match(/^\.\/docs\/(.+\.md)$/);
if (rootDocsMatch) return `](./${rootDocsMatch[1]})`;
// Root docs → GitHub (not part of docs site)
if (url === '../README.md' || url === './README.md' || url === './project-readme') {
return `](${REPO_URL}/blob/main/README.md)`;
}
if (url === '../CHANGELOG.md' || url === './CHANGELOG.md' || url === './changelog') {
return `](${REPO_URL}/blob/main/CHANGELOG.md)`;
}
// Root files → GitHub (CONTRIBUTING, LICENSE, CODE_OF_CONDUCT, etc.)
const contributingMatch = url.match(/^(\.\.\/)?CONTRIBUTING\.md(#.*)?$/);
if (contributingMatch) {
const anchor = contributingMatch[2] || '';
return `](${REPO_URL}/blob/main/CONTRIBUTING.md${anchor})`;
}
if (url === 'LICENSE' || url === '../LICENSE') {
return `](${REPO_URL}/blob/main/LICENSE)`;
}
if (url === '.github/CODE_OF_CONDUCT.md' || url === '../.github/CODE_OF_CONDUCT.md') {
return `](${REPO_URL}/blob/main/.github/CODE_OF_CONDUCT.md)`;
}
// Other root .md files → GitHub
const rootFileMatch = url.match(/^\.\.\/([A-Z][^/]+\.md)$/);
if (rootFileMatch) return `](${REPO_URL}/blob/main/${rootFileMatch[1]})`;
// Cross-module doc links: ../../{mod}/docs/{path}.md → ../{mod}/{path}.md
// Fixes path structure but keeps .md (Docusaurus handles .md → page conversion)
const crossModuleDocsMatch = url.match(/^\.\.\/\.\.\/([^/]+)\/docs\/(.+\.md)$/);
if (crossModuleDocsMatch) return `](../${crossModuleDocsMatch[1]}/${crossModuleDocsMatch[2]})`;
// Root-level folders (samples/) → GitHub
const rootFolderMatch = url.match(/^\.\.\/((samples)\/.*)/);
if (rootFolderMatch) return `](${REPO_URL}/blob/main/${rootFolderMatch[1]})`;
return match;
});
}
function countMarkdownFiles(dir) {
let count = 0;
if (!fs.existsSync(dir)) return 0;
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
const fullPath = path.join(dir, entry.name);
if (entry.isDirectory()) {
count += countMarkdownFiles(fullPath);
} else if (entry.name.endsWith('.md')) {
count++;
}
}
return count;
}
function createZipArchive(sourceDir, outputPath, exclude = []) {
return new Promise((resolve, reject) => {
const output = fs.createWriteStream(outputPath);