Simplify installer to 2 questions and update folder structure

- Reduce installer to minimal config: project_name + starting_point
- Remove design_experience, project_type, IDE selection questions
- Standardize on design-process/ output folder
- Update folder structure: A-E (remove F-G phases)
- Change D-Design-System → E-Design-System
- Add _progress/agent-dialogs/ folder
- Update success message to point to Saga (not Mimir)
- Auto-include learning material (no prompt)
- Get user_name from git config
- Remove IDE setup step

Workshop finding: 0/4 participants completed workflows with complex installer.
Simplification improves first-time user experience.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Mårten Angner 2026-02-24 10:42:13 +01:00
parent 95945ffe61
commit 5c6449d001
2 changed files with 62 additions and 121 deletions

View File

@ -10,7 +10,6 @@ const ora = require('ora');
const yaml = require('js-yaml');
const inquirer = require('inquirer').default || require('inquirer');
const { compileAgentFile } = require('./compiler');
const { writeIdeConfig } = require('./ide-configs');
class Installer {
constructor() {
@ -25,7 +24,7 @@ class Installer {
* @param {Object} config - Configuration from UI prompts
*/
async install(config) {
const { projectDir, wdsFolder, ides, project_type, design_experience, root_folder } = config;
const { projectDir, wdsFolder, root_folder } = config;
const wdsDir = path.join(projectDir, wdsFolder);
// Check if already installed
@ -112,39 +111,16 @@ class Installer {
throw error;
}
// Update config.yaml with root folder
const configPath = path.join(wdsDir, 'config.yaml');
let configContent = await fs.readFile(configPath, 'utf8');
configContent = configContent.replace(/output_folder:\s*docs/, `output_folder: ${rootFolder}`);
await fs.writeFile(configPath, configContent, 'utf8');
// Step 5: Set up IDEs
const ideList = ides || (config.ide ? [config.ide] : []);
const ideSpinner = ora(`Setting up ${ideList.length} IDE(s)...`).start();
// Step 5: Copy learning & reference material (always included)
const learnSpinner = ora('Copying learning & reference material...').start();
try {
const labels = [];
for (const ide of ideList) {
const result = await writeIdeConfig(projectDir, ide, wdsFolder);
labels.push(result.label);
}
ideSpinner.succeed(`Configured: ${labels.join(', ')}`);
await this.copyLearningMaterial(projectDir);
learnSpinner.succeed('Learning material added to _wds-learn/ (safe to remove when no longer needed)');
} catch (error) {
ideSpinner.fail('Failed to set up IDEs');
learnSpinner.fail('Failed to copy learning material');
throw error;
}
// Step 6: Copy learning & reference material (optional)
if (config.include_learning) {
const learnSpinner = ora('Copying learning & reference material...').start();
try {
await this.copyLearningMaterial(projectDir);
learnSpinner.succeed('Learning material added to _wds-learn/ (safe to remove when no longer needed)');
} catch (error) {
learnSpinner.fail('Failed to copy learning material');
throw error;
}
}
return { success: true, wdsDir, projectDir };
}
@ -183,14 +159,25 @@ class Installer {
return;
}
// Get user name from git or system
const getUserName = () => {
try {
const { execSync } = require('child_process');
const gitName = execSync('git config user.name', { encoding: 'utf8' }).trim();
return gitName || 'Designer';
} catch {
return 'Designer';
}
};
const configData = {
user_name: config.user_name || 'Designer',
communication_language: config.communication_language || 'en',
document_output_language: config.document_output_language || 'en',
output_folder: 'docs',
user_name: getUserName(),
project_name: config.project_name || 'Untitled Project',
starting_point: config.starting_point || 'brief',
communication_language: 'en',
document_output_language: 'en',
output_folder: 'design-process',
wds_folder: config.wdsFolder,
project_type: config.project_type,
design_experience: config.design_experience,
};
const yamlStr = yaml.dump(configData, { lineWidth: -1 });
@ -242,21 +229,19 @@ class Installer {
/**
* Create the WDS work products folder structure
* @param {string} projectDir - Project root directory
* @param {string} rootFolder - Root folder name (design-process, docs, deliverables, etc.)
* @param {string} rootFolder - Root folder name (design-process)
* @param {Object} config - Configuration object
*/
async createDocsFolders(projectDir, rootFolder, config) {
const docsPath = path.join(projectDir, rootFolder);
// Simplified 5-phase structure
const folders = [
'A-Product-Brief',
'B-Trigger-Map',
'C-UX-Scenarios',
'D-Design-System',
'E-PRD',
'E-PRD/Design-Deliveries',
'F-Testing',
'G-Product-Development',
'D-UX-Design',
'E-Design-System',
];
for (const folder of folders) {
@ -275,6 +260,11 @@ class Installer {
}
}
// Create _progress folder for agent tracking
const progressPath = path.join(docsPath, '_progress');
await fs.ensureDir(progressPath);
await fs.ensureDir(path.join(progressPath, 'agent-dialogs'));
// Create 00 guide files in each folder (if they don't exist)
await this.createFolderGuides(docsPath, config);
}
@ -290,19 +280,18 @@ class Installer {
{ template: '00-product-brief.template.md', folder: 'A-Product-Brief', filename: '00-product-brief.md' },
{ template: '00-trigger-map.template.md', folder: 'B-Trigger-Map', filename: '00-trigger-map.md' },
{ template: '00-ux-scenarios.template.md', folder: 'C-UX-Scenarios', filename: '00-ux-scenarios.md' },
{ template: '00-design-system.template.md', folder: 'D-Design-System', filename: '00-design-system.md' },
{ template: '00-design-system.template.md', folder: 'E-Design-System', filename: '00-design-system.md' },
];
// Common placeholder replacements
const replacements = {
'{{project_name}}': config.project_name || 'Untitled Project',
'{{date}}': new Date().toISOString().split('T')[0],
'{{project_type}}': config.project_type || 'digital_product',
'{{design_experience}}': config.design_experience || 'intermediate',
'{{starting_point}}': config.starting_point || 'brief',
'{{user_name}}': config.user_name || 'Designer',
'{{communication_language}}': config.communication_language || 'en',
'{{document_output_language}}': config.document_output_language || 'en',
'{{output_folder}}': path.relative(config.projectDir, docsPath) || 'docs',
'{{communication_language}}': 'en',
'{{document_output_language}}': 'en',
'{{output_folder}}': 'design-process',
'{{wds_folder}}': config.wdsFolder || '_wds',
};
@ -358,12 +347,11 @@ class Installer {
const replacements = {
'{{project_name}}': config.project_name || 'Untitled Project',
'{{date}}': new Date().toISOString().split('T')[0],
'{{project_type}}': config.project_type || 'digital_product',
'{{design_experience}}': config.design_experience || 'intermediate',
'{{starting_point}}': config.starting_point || 'brief',
'{{user_name}}': config.user_name || 'Designer',
'{{communication_language}}': config.communication_language || 'en',
'{{document_output_language}}': config.document_output_language || 'en',
'{{output_folder}}': path.relative(config.projectDir, docsPath) || 'docs',
'{{communication_language}}': 'en',
'{{document_output_language}}': 'en',
'{{output_folder}}': 'design-process',
'{{wds_folder}}': config.wdsFolder || '_wds',
};

View File

@ -6,7 +6,6 @@ const chalk = require('chalk');
const figlet = require('figlet');
const inquirer = require('inquirer').default || require('inquirer');
const path = require('node:path');
const { getIdeChoices } = require('./ide-configs');
class UI {
/**
@ -30,77 +29,28 @@ class UI {
this.displayBanner();
const projectDir = process.cwd();
const defaultProjectName = path.basename(projectDir);
console.log(chalk.white(` Target: ${chalk.cyan(projectDir)}`));
console.log(chalk.dim(` Agents and workflows will be installed in ${chalk.white('_wds/')}\n`));
// Confirm directory
const { confirmDir } = await inquirer.prompt([
{
type: 'confirm',
name: 'confirmDir',
message: 'Install WDS in this directory?',
default: true,
},
]);
if (!confirmDir) {
return { cancelled: true };
}
// Collect configuration
// Minimal 2-question installer
const answers = await inquirer.prompt([
{
type: 'input',
name: 'user_name',
message: 'Your name (agents will greet you by name):',
default: 'Designer',
name: 'project_name',
message: 'Project name:',
default: defaultProjectName,
},
{
type: 'list',
name: 'project_type',
message: 'What type of project are you working on?',
name: 'starting_point',
message: 'Where are you starting?',
choices: [
{ name: 'Digital Product - Multiple scenarios with more complex structure', value: 'digital_product' },
{ name: 'Single Scenario - Simple web sites and flat navigation', value: 'single_scenario' },
{ name: 'Single Page - Landing pages or simple one page web sites', value: 'single_page' },
{ name: 'Custom - Specialized structure, define later', value: 'custom' },
{ name: 'Go straight to Product Brief (I have approval)', value: 'brief' },
{ name: 'Create pitch deck and project contract first', value: 'pitch' },
],
default: 'digital_product',
},
{
type: 'list',
name: 'design_experience',
message: 'What is your design experience level?',
choices: [
{ name: 'Beginner - New to UX design, provide detailed guidance', value: 'beginner' },
{ name: 'Intermediate - Familiar with design concepts, balanced approach', value: 'intermediate' },
{ name: 'Expert - Experienced designer, be direct and efficient', value: 'expert' },
],
default: 'intermediate',
},
{
type: 'list',
name: 'root_folder',
message: 'Where should design work products be stored?',
choices: [
{ name: 'design-process/ - Recommended for clarity', value: 'design-process' },
{ name: 'docs/ - Standard documentation folder', value: 'docs' },
{ name: 'deliverables/ - Alternative naming', value: 'deliverables' },
],
default: 'design-process',
},
{
type: 'confirm',
name: 'include_learning',
message: 'Include learning & reference material in _wds-learn/?',
default: true,
},
{
type: 'checkbox',
name: 'ides',
message: 'Which AI IDE/tools are you using? (Space to select, Enter to confirm)',
choices: getIdeChoices(),
validate: (answer) => (answer.length > 0 ? true : 'Select at least one IDE.'),
default: 'brief',
},
]);
@ -108,6 +58,7 @@ class UI {
projectDir,
...answers,
wdsFolder: '_wds',
root_folder: 'design-process',
cancelled: false,
};
}
@ -117,19 +68,21 @@ class UI {
*/
displaySuccess(wdsFolder) {
console.log('');
console.log(chalk.green.bold(' Installation complete!'));
console.log(chalk.green.bold(' Installation complete!'));
console.log('');
console.log(chalk.white(' Whiteport Design Studio - Design Methodology'));
console.log(chalk.dim(' Output: Product Brief, Trigger Map, UX Scenarios, Design System\n'));
console.log(chalk.white(' Getting started:'));
console.log(chalk.dim(` 1. Open your project in your AI IDE`));
console.log(chalk.dim(` 2. Tell the AI:`));
console.log(chalk.cyan(` "Read and activate the agent in ${wdsFolder}/agents/mimir-orchestrator.md"`));
console.log(chalk.dim(` 3. Mimir will greet you and guide you through project setup`));
console.log(chalk.cyan(` "Read and activate ${wdsFolder}/agents/saga-analyst.md"`));
console.log(chalk.dim(` 3. Saga will greet you and start the Product Brief`));
console.log('');
console.log(chalk.white(` Agents in ${chalk.cyan(wdsFolder + '/agents/')}:`));
console.log(chalk.dim(` - Mimir (Orchestrator) - Your guide. Start here.`));
console.log(chalk.dim(` - Saga (Analyst) - Product Brief & Trigger Mapping`));
console.log(chalk.dim(` - Idunn (PM) - Platform Requirements & Deliveries`));
console.log(chalk.dim(` - Freya (Designer) - UX Design & Testing`));
console.log(chalk.dim(` - Saga (Analyst) - Product Brief & Trigger Mapping (Start here)`));
console.log(chalk.dim(` - Freya (Designer) - UX Scenarios, Design & Design System`));
console.log('');
console.log(chalk.dim(' Need development? Install BMM: npx bmad-builder install'));
console.log('');
console.log(chalk.dim(' https://github.com/whiteport-collective/whiteport-design-studio'));
console.log('');