whiteport-design-studio 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package.json",
|
|
3
3
|
"name": "whiteport-design-studio",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.1",
|
|
5
5
|
"description": "Whiteport Design Studio - Strategic design methodology for AI-powered workflows",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"design",
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# Project Info: {{project_name}}
|
|
2
|
+
|
|
3
|
+
**Created:** {{date}}
|
|
4
|
+
**Project Type:** {{project_type}}
|
|
5
|
+
**Design Experience:** {{design_experience}}
|
|
6
|
+
**Status:** In progress
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Team
|
|
11
|
+
|
|
12
|
+
**Project Lead:** {{user_name}}
|
|
13
|
+
**Communication Language:** {{communication_language}}
|
|
14
|
+
**Document Output Language:** {{document_output_language}}
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Project Configuration
|
|
19
|
+
|
|
20
|
+
**Output Folder:** `{{output_folder}}/`
|
|
21
|
+
**WDS System Folder:** `{{wds_folder}}/`
|
|
22
|
+
|
|
23
|
+
Configuration stored in: `{{wds_folder}}/config.yaml`
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Quick Navigation
|
|
28
|
+
|
|
29
|
+
**Product Brief (Phase 1):**
|
|
30
|
+
- [01 — Product Brief](01-product-brief.md)
|
|
31
|
+
- [02 — Content Language](02-content-language.md)
|
|
32
|
+
- [03 — Visual Direction](03-visual-direction.md)
|
|
33
|
+
- [04 — Platform Requirements](04-platform-requirements.md)
|
|
34
|
+
|
|
35
|
+
**Trigger Map (Phase 2):**
|
|
36
|
+
- [00 — Trigger Map Overview](../B-Trigger-Map/00-trigger-map.md)
|
|
37
|
+
|
|
38
|
+
**UX Scenarios (Phase 4):**
|
|
39
|
+
- [UX Scenarios Guide](../C-UX-Scenarios/ux-scenarios-guide.md)
|
|
40
|
+
|
|
41
|
+
**Design System (Phase 7):**
|
|
42
|
+
- [00 — Design System Overview](../D-Design-System/00-design-system.md)
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## Project Timeline
|
|
47
|
+
|
|
48
|
+
| Phase | Status | Completed |
|
|
49
|
+
|-------|--------|-----------|
|
|
50
|
+
| 1 — Product Brief | Not started | — |
|
|
51
|
+
| 2 — Trigger Map | Not started | — |
|
|
52
|
+
| 3 — Platform Requirements | Not started | — |
|
|
53
|
+
| 4 — UX Design | Not started | — |
|
|
54
|
+
| 5 — Design System | Not started | — |
|
|
55
|
+
| 6 — Design Deliveries | Not started | — |
|
|
56
|
+
| 7 — Testing | Not started | — |
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## Technical Stack
|
|
61
|
+
|
|
62
|
+
**Frontend:** TBD
|
|
63
|
+
**Backend:** TBD
|
|
64
|
+
**Hosting:** TBD
|
|
65
|
+
**Languages:** {{document_output_language}}
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## WDS Agents
|
|
70
|
+
|
|
71
|
+
To activate agents, tell Claude:
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
Read and activate the agent in `{{wds_folder}}/agents/[agent-name].md`
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
**Available:**
|
|
78
|
+
- **Mimir** — Orchestrator & Guide
|
|
79
|
+
- **Saga** — Product Brief & Trigger Mapping
|
|
80
|
+
- **Idunn** — Platform Requirements & Design Deliveries
|
|
81
|
+
- **Freya** — UX Design, Design System & Testing
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
*Generated by Whiteport Design Studio installer*
|
|
@@ -103,14 +103,23 @@ class Installer {
|
|
|
103
103
|
|
|
104
104
|
// Step 4: Create docs folder structure
|
|
105
105
|
const docsSpinner = ora('Creating project folders...').start();
|
|
106
|
+
let detectedOutputFolder = 'docs';
|
|
106
107
|
try {
|
|
107
|
-
await this.createDocsFolders(projectDir);
|
|
108
|
-
docsSpinner.succeed(
|
|
108
|
+
detectedOutputFolder = await this.createDocsFolders(projectDir);
|
|
109
|
+
docsSpinner.succeed(`Project folders created in ${detectedOutputFolder}/`);
|
|
109
110
|
} catch (error) {
|
|
110
111
|
docsSpinner.fail('Failed to create project folders');
|
|
111
112
|
throw error;
|
|
112
113
|
}
|
|
113
114
|
|
|
115
|
+
// Update config.yaml with detected output folder (if different from default)
|
|
116
|
+
if (detectedOutputFolder !== 'docs') {
|
|
117
|
+
const configPath = path.join(wdsDir, 'config.yaml');
|
|
118
|
+
let configContent = await fs.readFile(configPath, 'utf8');
|
|
119
|
+
configContent = configContent.replace(/output_folder:\s*docs/, `output_folder: ${detectedOutputFolder}`);
|
|
120
|
+
await fs.writeFile(configPath, configContent, 'utf8');
|
|
121
|
+
}
|
|
122
|
+
|
|
114
123
|
// Step 5: Set up IDEs
|
|
115
124
|
const ideList = ides || (config.ide ? [config.ide] : []);
|
|
116
125
|
const ideSpinner = ora(`Setting up ${ideList.length} IDE(s)...`).start();
|
|
@@ -234,9 +243,30 @@ class Installer {
|
|
|
234
243
|
|
|
235
244
|
/**
|
|
236
245
|
* Create the WDS docs folder structure
|
|
246
|
+
* FIXED: Detects existing folders, doesn't overwrite files
|
|
237
247
|
*/
|
|
238
248
|
async createDocsFolders(projectDir) {
|
|
239
|
-
|
|
249
|
+
// Check if user already has a deliverables folder with WDS content
|
|
250
|
+
const possibleFolders = ['design-process', 'docs', 'deliverables', 'wds-deliverables'];
|
|
251
|
+
let existingFolder = null;
|
|
252
|
+
|
|
253
|
+
for (const folderName of possibleFolders) {
|
|
254
|
+
const folderPath = path.join(projectDir, folderName);
|
|
255
|
+
if (await fs.pathExists(folderPath)) {
|
|
256
|
+
// Check if it has WDS structure (A-Product-Brief, B-Trigger-Map, etc.)
|
|
257
|
+
const hasProductBrief = await fs.pathExists(path.join(folderPath, 'A-Product-Brief'));
|
|
258
|
+
const hasTriggerMap = await fs.pathExists(path.join(folderPath, 'B-Trigger-Map'));
|
|
259
|
+
if (hasProductBrief || hasTriggerMap) {
|
|
260
|
+
existingFolder = folderName;
|
|
261
|
+
break;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// Use existing folder if found, otherwise default to 'docs'
|
|
267
|
+
const outputFolder = existingFolder || 'docs';
|
|
268
|
+
const docsPath = path.join(projectDir, outputFolder);
|
|
269
|
+
|
|
240
270
|
const folders = [
|
|
241
271
|
'A-Product-Brief',
|
|
242
272
|
'B-Trigger-Map',
|
|
@@ -250,14 +280,121 @@ class Installer {
|
|
|
250
280
|
|
|
251
281
|
for (const folder of folders) {
|
|
252
282
|
const folderPath = path.join(docsPath, folder);
|
|
253
|
-
await fs.ensureDir(folderPath);
|
|
254
283
|
|
|
255
|
-
//
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
284
|
+
// Only create folder if it doesn't exist
|
|
285
|
+
if (!(await fs.pathExists(folderPath))) {
|
|
286
|
+
await fs.ensureDir(folderPath);
|
|
287
|
+
|
|
288
|
+
// Add .gitkeep to preserve empty directories (only if folder is empty)
|
|
289
|
+
const gitkeepPath = path.join(folderPath, '.gitkeep');
|
|
290
|
+
const existingFiles = await fs.readdir(folderPath);
|
|
291
|
+
if (existingFiles.length === 0) {
|
|
292
|
+
await fs.writeFile(gitkeepPath, '# This file ensures the directory is tracked by git\n');
|
|
293
|
+
}
|
|
259
294
|
}
|
|
260
295
|
}
|
|
296
|
+
|
|
297
|
+
// Create 00 guide files in each folder (if they don't exist)
|
|
298
|
+
await this.createFolderGuides(docsPath, config);
|
|
299
|
+
|
|
300
|
+
// Return the detected/used folder name so config.yaml can be updated
|
|
301
|
+
return outputFolder;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Create 00 guide files in each folder from templates
|
|
306
|
+
*/
|
|
307
|
+
async createFolderGuides(docsPath, config) {
|
|
308
|
+
const templateDir = path.join(this.srcDir, 'workflows', '0-project-setup', 'templates', 'folder-guides');
|
|
309
|
+
|
|
310
|
+
// Mapping: template filename → destination folder & filename
|
|
311
|
+
const guides = [
|
|
312
|
+
{ template: '00-product-brief.template.md', folder: 'A-Product-Brief', filename: '00-product-brief.md' },
|
|
313
|
+
{ template: '00-trigger-map.template.md', folder: 'B-Trigger-Map', filename: '00-trigger-map.md' },
|
|
314
|
+
{ template: '00-ux-scenarios.template.md', folder: 'C-UX-Scenarios', filename: '00-ux-scenarios.md' },
|
|
315
|
+
{ template: '00-design-system.template.md', folder: 'D-Design-System', filename: '00-design-system.md' },
|
|
316
|
+
];
|
|
317
|
+
|
|
318
|
+
// Common placeholder replacements
|
|
319
|
+
const replacements = {
|
|
320
|
+
'{{project_name}}': config.project_name || 'Untitled Project',
|
|
321
|
+
'{{date}}': new Date().toISOString().split('T')[0],
|
|
322
|
+
'{{project_type}}': config.project_type || 'digital_product',
|
|
323
|
+
'{{design_experience}}': config.design_experience || 'intermediate',
|
|
324
|
+
'{{user_name}}': config.user_name || 'Designer',
|
|
325
|
+
'{{communication_language}}': config.communication_language || 'en',
|
|
326
|
+
'{{document_output_language}}': config.document_output_language || 'en',
|
|
327
|
+
'{{output_folder}}': path.relative(config.projectDir, docsPath) || 'docs',
|
|
328
|
+
'{{wds_folder}}': config.wdsFolder || '_wds',
|
|
329
|
+
};
|
|
330
|
+
|
|
331
|
+
// Create each folder guide
|
|
332
|
+
for (const guide of guides) {
|
|
333
|
+
const templatePath = path.join(templateDir, guide.template);
|
|
334
|
+
const destPath = path.join(docsPath, guide.folder, guide.filename);
|
|
335
|
+
|
|
336
|
+
// Skip if file exists (never overwrite) or template doesn't exist
|
|
337
|
+
if (await fs.pathExists(destPath)) continue;
|
|
338
|
+
if (!(await fs.pathExists(templatePath))) continue;
|
|
339
|
+
|
|
340
|
+
// Read template
|
|
341
|
+
let content = await fs.readFile(templatePath, 'utf8');
|
|
342
|
+
|
|
343
|
+
// Replace all placeholders
|
|
344
|
+
for (const [placeholder, value] of Object.entries(replacements)) {
|
|
345
|
+
content = content.split(placeholder).join(value);
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
// Write file
|
|
349
|
+
await fs.writeFile(destPath, content, 'utf8');
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// Also create 00-project-info.md in A-Product-Brief (project settings home)
|
|
353
|
+
await this.createProjectInfoFile(docsPath, config);
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* Create 00-project-info.md in A-Product-Brief from template
|
|
358
|
+
*/
|
|
359
|
+
async createProjectInfoFile(docsPath, config) {
|
|
360
|
+
const productBriefPath = path.join(docsPath, 'A-Product-Brief');
|
|
361
|
+
const projectInfoPath = path.join(productBriefPath, '00-project-info.md');
|
|
362
|
+
|
|
363
|
+
// Only create if it doesn't exist (never overwrite)
|
|
364
|
+
if (await fs.pathExists(projectInfoPath)) {
|
|
365
|
+
return;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
const templatePath = path.join(this.srcDir, 'workflows', '1-project-brief', 'templates', '00-project-info.template.md');
|
|
369
|
+
|
|
370
|
+
// Check if template exists
|
|
371
|
+
if (!(await fs.pathExists(templatePath))) {
|
|
372
|
+
// Skip if template not found (backward compatibility)
|
|
373
|
+
return;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
// Read template
|
|
377
|
+
let template = await fs.readFile(templatePath, 'utf8');
|
|
378
|
+
|
|
379
|
+
// Replace placeholders
|
|
380
|
+
const replacements = {
|
|
381
|
+
'{{project_name}}': config.project_name || 'Untitled Project',
|
|
382
|
+
'{{date}}': new Date().toISOString().split('T')[0],
|
|
383
|
+
'{{project_type}}': config.project_type || 'digital_product',
|
|
384
|
+
'{{design_experience}}': config.design_experience || 'intermediate',
|
|
385
|
+
'{{user_name}}': config.user_name || 'Designer',
|
|
386
|
+
'{{communication_language}}': config.communication_language || 'en',
|
|
387
|
+
'{{document_output_language}}': config.document_output_language || 'en',
|
|
388
|
+
'{{output_folder}}': path.relative(config.projectDir, docsPath) || 'docs',
|
|
389
|
+
'{{wds_folder}}': config.wdsFolder || '_wds',
|
|
390
|
+
};
|
|
391
|
+
|
|
392
|
+
for (const [placeholder, value] of Object.entries(replacements)) {
|
|
393
|
+
template = template.split(placeholder).join(value);
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
// Write the file
|
|
397
|
+
await fs.writeFile(projectInfoPath, template, 'utf8');
|
|
261
398
|
}
|
|
262
399
|
}
|
|
263
400
|
|