@hustle-together/api-dev-tools 3.6.5 → 3.10.0
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/README.md +5599 -258
- package/bin/cli.js +395 -20
- package/commands/README.md +459 -71
- package/commands/hustle-api-continue.md +158 -0
- package/commands/{api-create.md → hustle-api-create.md} +35 -15
- package/commands/{api-env.md → hustle-api-env.md} +4 -4
- package/commands/{api-interview.md → hustle-api-interview.md} +1 -1
- package/commands/{api-research.md → hustle-api-research.md} +3 -3
- package/commands/hustle-api-sessions.md +149 -0
- package/commands/{api-status.md → hustle-api-status.md} +16 -16
- package/commands/{api-verify.md → hustle-api-verify.md} +2 -2
- package/commands/hustle-combine.md +763 -0
- package/commands/hustle-ui-create-page.md +933 -0
- package/commands/hustle-ui-create.md +825 -0
- package/hooks/api-workflow-check.py +545 -21
- package/hooks/cache-research.py +337 -0
- package/hooks/check-api-routes.py +168 -0
- package/hooks/check-playwright-setup.py +103 -0
- package/hooks/check-storybook-setup.py +81 -0
- package/hooks/detect-interruption.py +165 -0
- package/hooks/enforce-a11y-audit.py +202 -0
- package/hooks/enforce-brand-guide.py +241 -0
- package/hooks/enforce-documentation.py +60 -8
- package/hooks/enforce-freshness.py +184 -0
- package/hooks/enforce-page-components.py +186 -0
- package/hooks/enforce-page-data-schema.py +155 -0
- package/hooks/enforce-questions-sourced.py +146 -0
- package/hooks/enforce-schema-from-interview.py +248 -0
- package/hooks/enforce-ui-disambiguation.py +108 -0
- package/hooks/enforce-ui-interview.py +130 -0
- package/hooks/generate-manifest-entry.py +1161 -0
- package/hooks/session-logger.py +297 -0
- package/hooks/session-startup.py +160 -15
- package/hooks/track-scope-coverage.py +220 -0
- package/hooks/track-tool-use.py +81 -1
- package/hooks/update-api-showcase.py +149 -0
- package/hooks/update-registry.py +352 -0
- package/hooks/update-ui-showcase.py +212 -0
- package/package.json +8 -3
- package/templates/BRAND_GUIDE.md +299 -0
- package/templates/CLAUDE-SECTION.md +56 -24
- package/templates/SPEC.json +640 -0
- package/templates/api-dev-state.json +217 -161
- package/templates/api-showcase/_components/APICard.tsx +153 -0
- package/templates/api-showcase/_components/APIModal.tsx +375 -0
- package/templates/api-showcase/_components/APIShowcase.tsx +231 -0
- package/templates/api-showcase/_components/APITester.tsx +522 -0
- package/templates/api-showcase/page.tsx +41 -0
- package/templates/component/Component.stories.tsx +172 -0
- package/templates/component/Component.test.tsx +237 -0
- package/templates/component/Component.tsx +86 -0
- package/templates/component/Component.types.ts +55 -0
- package/templates/component/index.ts +15 -0
- package/templates/dev-tools/_components/DevToolsLanding.tsx +320 -0
- package/templates/dev-tools/page.tsx +10 -0
- package/templates/page/page.e2e.test.ts +218 -0
- package/templates/page/page.tsx +42 -0
- package/templates/performance-budgets.json +58 -0
- package/templates/registry.json +13 -0
- package/templates/settings.json +90 -0
- package/templates/shared/HeroHeader.tsx +261 -0
- package/templates/shared/index.ts +1 -0
- package/templates/ui-showcase/_components/PreviewCard.tsx +315 -0
- package/templates/ui-showcase/_components/PreviewModal.tsx +676 -0
- package/templates/ui-showcase/_components/UIShowcase.tsx +262 -0
- package/templates/ui-showcase/page.tsx +26 -0
- package/demo/hustle-together/blog/gemini-vs-claude-widgets.html +0 -959
- package/demo/hustle-together/blog/interview-driven-api-development.html +0 -1146
- package/demo/hustle-together/blog/tdd-for-ai.html +0 -982
- package/demo/hustle-together/index.html +0 -1312
- package/demo/workflow-demo-v3.5-backup.html +0 -5008
- package/demo/workflow-demo.html +0 -6202
package/bin/cli.js
CHANGED
|
@@ -15,12 +15,20 @@ const { execSync } = require('child_process');
|
|
|
15
15
|
* - Settings configuration for hook registration
|
|
16
16
|
* - State file template for progress tracking
|
|
17
17
|
*
|
|
18
|
-
* Usage: npx @
|
|
18
|
+
* Usage: npx @hustle-together/api-dev-tools --scope=project
|
|
19
|
+
*
|
|
20
|
+
* Optional flags:
|
|
21
|
+
* --with-storybook Auto-initialize Storybook for component development
|
|
22
|
+
* --with-playwright Auto-initialize Playwright for E2E testing
|
|
23
|
+
* --with-sandpack Auto-install Sandpack for live UI previews
|
|
19
24
|
*/
|
|
20
25
|
|
|
21
26
|
// Parse command-line arguments
|
|
22
27
|
const args = process.argv.slice(2);
|
|
23
28
|
const scope = args.find(arg => arg.startsWith('--scope='))?.split('=')[1] || 'project';
|
|
29
|
+
const withStorybook = args.includes('--with-storybook');
|
|
30
|
+
const withPlaywright = args.includes('--with-playwright');
|
|
31
|
+
const withSandpack = args.includes('--with-sandpack');
|
|
24
32
|
|
|
25
33
|
// Colors for terminal output
|
|
26
34
|
const colors = {
|
|
@@ -65,6 +73,8 @@ function verifyInstallation(claudeDir, hooksDir) {
|
|
|
65
73
|
{ path: path.join(claudeDir, 'commands'), name: 'Commands directory' },
|
|
66
74
|
{ path: path.join(claudeDir, 'settings.json'), name: 'Settings file' },
|
|
67
75
|
{ path: path.join(claudeDir, 'api-dev-state.json'), name: 'State file' },
|
|
76
|
+
{ path: path.join(claudeDir, 'registry.json'), name: 'Registry file' },
|
|
77
|
+
{ path: path.join(claudeDir, 'performance-budgets.json'), name: 'Performance budgets' },
|
|
68
78
|
{ path: path.join(claudeDir, 'research'), name: 'Research cache directory' },
|
|
69
79
|
{ path: path.join(claudeDir, 'research', 'index.json'), name: 'Research index' },
|
|
70
80
|
];
|
|
@@ -91,7 +101,8 @@ function verifyInstallation(claudeDir, hooksDir) {
|
|
|
91
101
|
{ path: path.join(hooksDir, 'verify-after-green.py'), name: 'verify-after-green.py' },
|
|
92
102
|
{ path: path.join(hooksDir, 'enforce-verify.py'), name: 'enforce-verify.py' },
|
|
93
103
|
{ path: path.join(hooksDir, 'enforce-refactor.py'), name: 'enforce-refactor.py' },
|
|
94
|
-
{ path: path.join(hooksDir, 'enforce-documentation.py'), name: 'enforce-documentation.py' }
|
|
104
|
+
{ path: path.join(hooksDir, 'enforce-documentation.py'), name: 'enforce-documentation.py' },
|
|
105
|
+
{ path: path.join(hooksDir, 'update-registry.py'), name: 'update-registry.py' }
|
|
95
106
|
);
|
|
96
107
|
}
|
|
97
108
|
|
|
@@ -253,7 +264,70 @@ function main() {
|
|
|
253
264
|
}
|
|
254
265
|
|
|
255
266
|
// ========================================
|
|
256
|
-
// 4b. Install
|
|
267
|
+
// 4b. Install Registry (v3.8.0)
|
|
268
|
+
// ========================================
|
|
269
|
+
const registrySource = path.join(sourceTemplatesDir, 'registry.json');
|
|
270
|
+
const registryDest = path.join(claudeDir, 'registry.json');
|
|
271
|
+
|
|
272
|
+
if (fs.existsSync(registrySource)) {
|
|
273
|
+
log('\n📋 Setting up central registry:', 'cyan');
|
|
274
|
+
|
|
275
|
+
if (!fs.existsSync(registryDest)) {
|
|
276
|
+
try {
|
|
277
|
+
fs.copyFileSync(registrySource, registryDest);
|
|
278
|
+
log(' ✅ Created registry.json (tracks APIs, components, pages)', 'green');
|
|
279
|
+
} catch (error) {
|
|
280
|
+
log(` ❌ Failed to create registry: ${error.message}`, 'red');
|
|
281
|
+
}
|
|
282
|
+
} else {
|
|
283
|
+
log(' ℹ️ Registry already exists (preserved)', 'blue');
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// ========================================
|
|
288
|
+
// 4c. Install Brand Guide Template (v3.9.0)
|
|
289
|
+
// ========================================
|
|
290
|
+
const brandGuideSource = path.join(sourceTemplatesDir, 'BRAND_GUIDE.md');
|
|
291
|
+
const brandGuideDest = path.join(claudeDir, 'BRAND_GUIDE.md');
|
|
292
|
+
|
|
293
|
+
if (fs.existsSync(brandGuideSource)) {
|
|
294
|
+
log('\n🎨 Setting up brand guide:', 'cyan');
|
|
295
|
+
|
|
296
|
+
if (!fs.existsSync(brandGuideDest)) {
|
|
297
|
+
try {
|
|
298
|
+
fs.copyFileSync(brandGuideSource, brandGuideDest);
|
|
299
|
+
log(' ✅ Created BRAND_GUIDE.md (customize for your project branding)', 'green');
|
|
300
|
+
} catch (error) {
|
|
301
|
+
log(` ❌ Failed to create brand guide: ${error.message}`, 'red');
|
|
302
|
+
}
|
|
303
|
+
} else {
|
|
304
|
+
log(' ℹ️ Brand guide already exists (preserved)', 'blue');
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// ========================================
|
|
309
|
+
// 4d. Install Performance Budgets (v3.9.0)
|
|
310
|
+
// ========================================
|
|
311
|
+
const perfBudgetsSource = path.join(sourceTemplatesDir, 'performance-budgets.json');
|
|
312
|
+
const perfBudgetsDest = path.join(claudeDir, 'performance-budgets.json');
|
|
313
|
+
|
|
314
|
+
if (fs.existsSync(perfBudgetsSource)) {
|
|
315
|
+
log('\n📊 Setting up performance budgets:', 'cyan');
|
|
316
|
+
|
|
317
|
+
if (!fs.existsSync(perfBudgetsDest)) {
|
|
318
|
+
try {
|
|
319
|
+
fs.copyFileSync(perfBudgetsSource, perfBudgetsDest);
|
|
320
|
+
log(' ✅ Created performance-budgets.json (thresholds for TDD gates)', 'green');
|
|
321
|
+
} catch (error) {
|
|
322
|
+
log(` ❌ Failed to create performance budgets: ${error.message}`, 'red');
|
|
323
|
+
}
|
|
324
|
+
} else {
|
|
325
|
+
log(' ℹ️ Performance budgets already exist (preserved)', 'blue');
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
// ========================================
|
|
330
|
+
// 4e. Install Research Cache Structure (v3.0)
|
|
257
331
|
// ========================================
|
|
258
332
|
const researchDir = path.join(claudeDir, 'research');
|
|
259
333
|
const researchIndexSource = path.join(sourceTemplatesDir, 'research-index.json');
|
|
@@ -353,7 +427,175 @@ function main() {
|
|
|
353
427
|
}
|
|
354
428
|
|
|
355
429
|
// ========================================
|
|
356
|
-
//
|
|
430
|
+
// 4f. Install Showcase Pages (v3.9.2)
|
|
431
|
+
// ========================================
|
|
432
|
+
log('\n🎨 Setting up showcase pages:', 'cyan');
|
|
433
|
+
|
|
434
|
+
if (hasNextJs && appDir) {
|
|
435
|
+
const showcaseTemplates = [
|
|
436
|
+
// Shared components first (required by other pages)
|
|
437
|
+
{
|
|
438
|
+
source: 'shared',
|
|
439
|
+
dest: path.join(appDir, 'shared'),
|
|
440
|
+
files: ['HeroHeader.tsx', 'index.ts'],
|
|
441
|
+
name: 'Shared components (HeroHeader)'
|
|
442
|
+
},
|
|
443
|
+
// API Showcase
|
|
444
|
+
{
|
|
445
|
+
source: 'api-showcase',
|
|
446
|
+
dest: path.join(appDir, 'api-showcase'),
|
|
447
|
+
files: ['page.tsx'],
|
|
448
|
+
componentsDir: '_components',
|
|
449
|
+
componentFiles: ['APIShowcase.tsx', 'APICard.tsx', 'APIModal.tsx', 'APITester.tsx'],
|
|
450
|
+
name: 'API Showcase'
|
|
451
|
+
},
|
|
452
|
+
// UI Showcase
|
|
453
|
+
{
|
|
454
|
+
source: 'ui-showcase',
|
|
455
|
+
dest: path.join(appDir, 'ui-showcase'),
|
|
456
|
+
files: ['page.tsx'],
|
|
457
|
+
componentsDir: '_components',
|
|
458
|
+
componentFiles: ['UIShowcase.tsx', 'PreviewCard.tsx', 'PreviewModal.tsx'],
|
|
459
|
+
name: 'UI Showcase'
|
|
460
|
+
},
|
|
461
|
+
// Dev Tools Landing
|
|
462
|
+
{
|
|
463
|
+
source: 'dev-tools',
|
|
464
|
+
dest: path.join(appDir, 'dev-tools'),
|
|
465
|
+
files: ['page.tsx'],
|
|
466
|
+
componentsDir: '_components',
|
|
467
|
+
componentFiles: ['DevToolsLanding.tsx'],
|
|
468
|
+
name: 'Dev Tools Landing'
|
|
469
|
+
}
|
|
470
|
+
];
|
|
471
|
+
|
|
472
|
+
for (const template of showcaseTemplates) {
|
|
473
|
+
const sourceDir = path.join(sourceTemplatesDir, template.source);
|
|
474
|
+
|
|
475
|
+
if (!fs.existsSync(sourceDir)) {
|
|
476
|
+
log(` ⚠️ ${template.name} template not found`, 'yellow');
|
|
477
|
+
continue;
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
// Create destination directory
|
|
481
|
+
if (!fs.existsSync(template.dest)) {
|
|
482
|
+
fs.mkdirSync(template.dest, { recursive: true });
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
let installedFiles = [];
|
|
486
|
+
|
|
487
|
+
// Copy main files (page.tsx, etc.)
|
|
488
|
+
for (const file of template.files) {
|
|
489
|
+
const srcFile = path.join(sourceDir, file);
|
|
490
|
+
const destFile = path.join(template.dest, file);
|
|
491
|
+
|
|
492
|
+
if (fs.existsSync(srcFile) && !fs.existsSync(destFile)) {
|
|
493
|
+
try {
|
|
494
|
+
fs.copyFileSync(srcFile, destFile);
|
|
495
|
+
installedFiles.push(file);
|
|
496
|
+
} catch (error) {
|
|
497
|
+
log(` ❌ Failed to copy ${file}: ${error.message}`, 'red');
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
// Copy _components directory if exists
|
|
503
|
+
if (template.componentsDir && template.componentFiles) {
|
|
504
|
+
const srcComponentsDir = path.join(sourceDir, template.componentsDir);
|
|
505
|
+
const destComponentsDir = path.join(template.dest, template.componentsDir);
|
|
506
|
+
|
|
507
|
+
if (fs.existsSync(srcComponentsDir)) {
|
|
508
|
+
if (!fs.existsSync(destComponentsDir)) {
|
|
509
|
+
fs.mkdirSync(destComponentsDir, { recursive: true });
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
for (const file of template.componentFiles) {
|
|
513
|
+
const srcFile = path.join(srcComponentsDir, file);
|
|
514
|
+
const destFile = path.join(destComponentsDir, file);
|
|
515
|
+
|
|
516
|
+
if (fs.existsSync(srcFile) && !fs.existsSync(destFile)) {
|
|
517
|
+
try {
|
|
518
|
+
fs.copyFileSync(srcFile, destFile);
|
|
519
|
+
installedFiles.push(`_components/${file}`);
|
|
520
|
+
} catch (error) {
|
|
521
|
+
log(` ❌ Failed to copy ${file}: ${error.message}`, 'red');
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
if (installedFiles.length > 0) {
|
|
529
|
+
log(` ✅ ${template.name} (${installedFiles.length} files)`, 'green');
|
|
530
|
+
} else {
|
|
531
|
+
log(` ℹ️ ${template.name} already exists (preserved)`, 'blue');
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
log('\n 💡 Showcase pages available at:', 'yellow');
|
|
536
|
+
log(' /dev-tools - Landing page with all dev tools', 'yellow');
|
|
537
|
+
log(' /api-showcase - Interactive API testing', 'yellow');
|
|
538
|
+
log(' /ui-showcase - Live component previews', 'yellow');
|
|
539
|
+
} else {
|
|
540
|
+
log(' ⚠️ Next.js App Router not detected - skipping showcase pages', 'yellow');
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
// ========================================
|
|
544
|
+
// 4g. Install Component/Page Templates (v3.9.0)
|
|
545
|
+
// ========================================
|
|
546
|
+
log('\n📦 Setting up component/page templates:', 'cyan');
|
|
547
|
+
|
|
548
|
+
const componentPageTemplates = [
|
|
549
|
+
{
|
|
550
|
+
source: 'component',
|
|
551
|
+
dest: path.join(claudeDir, 'templates', 'component'),
|
|
552
|
+
name: 'Component templates'
|
|
553
|
+
},
|
|
554
|
+
{
|
|
555
|
+
source: 'page',
|
|
556
|
+
dest: path.join(claudeDir, 'templates', 'page'),
|
|
557
|
+
name: 'Page templates'
|
|
558
|
+
}
|
|
559
|
+
];
|
|
560
|
+
|
|
561
|
+
for (const template of componentPageTemplates) {
|
|
562
|
+
const sourceDir = path.join(sourceTemplatesDir, template.source);
|
|
563
|
+
|
|
564
|
+
if (!fs.existsSync(sourceDir)) {
|
|
565
|
+
log(` ⚠️ ${template.name} not found`, 'yellow');
|
|
566
|
+
continue;
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
if (!fs.existsSync(template.dest)) {
|
|
570
|
+
fs.mkdirSync(template.dest, { recursive: true });
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
const files = fs.readdirSync(sourceDir);
|
|
574
|
+
let copiedCount = 0;
|
|
575
|
+
|
|
576
|
+
for (const file of files) {
|
|
577
|
+
const srcFile = path.join(sourceDir, file);
|
|
578
|
+
const destFile = path.join(template.dest, file);
|
|
579
|
+
|
|
580
|
+
if (fs.statSync(srcFile).isFile() && !fs.existsSync(destFile)) {
|
|
581
|
+
try {
|
|
582
|
+
fs.copyFileSync(srcFile, destFile);
|
|
583
|
+
copiedCount++;
|
|
584
|
+
} catch (error) {
|
|
585
|
+
log(` ❌ Failed to copy ${file}: ${error.message}`, 'red');
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
if (copiedCount > 0) {
|
|
591
|
+
log(` ✅ ${template.name} (${copiedCount} files)`, 'green');
|
|
592
|
+
} else {
|
|
593
|
+
log(` ℹ️ ${template.name} already exists (preserved)`, 'blue');
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
// ========================================
|
|
598
|
+
// 4h. Install Manifest Generation Scripts
|
|
357
599
|
// ========================================
|
|
358
600
|
log('\n📊 Setting up manifest generation scripts:', 'cyan');
|
|
359
601
|
|
|
@@ -464,30 +706,98 @@ function main() {
|
|
|
464
706
|
}
|
|
465
707
|
}
|
|
466
708
|
|
|
709
|
+
// ========================================
|
|
710
|
+
// 7. Install Optional Development Tools
|
|
711
|
+
// ========================================
|
|
712
|
+
if (withStorybook || withPlaywright || withSandpack) {
|
|
713
|
+
log('\n🔧 Installing optional development tools:', 'cyan');
|
|
714
|
+
|
|
715
|
+
if (withSandpack) {
|
|
716
|
+
try {
|
|
717
|
+
log(' 📦 Installing Sandpack for live component previews...', 'blue');
|
|
718
|
+
execSync('pnpm add @codesandbox/sandpack-react 2>&1', { cwd: targetDir, encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'] });
|
|
719
|
+
log(' ✅ Sandpack installed successfully', 'green');
|
|
720
|
+
} catch (error) {
|
|
721
|
+
// Try npm if pnpm fails
|
|
722
|
+
try {
|
|
723
|
+
execSync('npm install @codesandbox/sandpack-react 2>&1', { cwd: targetDir, encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'] });
|
|
724
|
+
log(' ✅ Sandpack installed successfully (via npm)', 'green');
|
|
725
|
+
} catch (npmError) {
|
|
726
|
+
log(' ⚠️ Could not install Sandpack automatically. Run manually:', 'yellow');
|
|
727
|
+
log(' pnpm add @codesandbox/sandpack-react', 'yellow');
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
if (withStorybook) {
|
|
733
|
+
try {
|
|
734
|
+
log(' 📖 Initializing Storybook (this may take a moment)...', 'blue');
|
|
735
|
+
execSync('npx storybook@latest init --yes 2>&1', { cwd: targetDir, encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'], timeout: 300000 });
|
|
736
|
+
log(' ✅ Storybook initialized successfully', 'green');
|
|
737
|
+
log(' 💡 Run with: pnpm storybook', 'yellow');
|
|
738
|
+
} catch (error) {
|
|
739
|
+
log(' ⚠️ Storybook init failed. Run manually:', 'yellow');
|
|
740
|
+
log(' npx storybook@latest init', 'yellow');
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
if (withPlaywright) {
|
|
745
|
+
try {
|
|
746
|
+
log(' 🎭 Initializing Playwright (this may take a moment)...', 'blue');
|
|
747
|
+
execSync('npm init playwright@latest -- --yes 2>&1', { cwd: targetDir, encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'], timeout: 300000 });
|
|
748
|
+
log(' ✅ Playwright initialized successfully', 'green');
|
|
749
|
+
log(' 💡 Run tests with: npx playwright test', 'yellow');
|
|
750
|
+
} catch (error) {
|
|
751
|
+
log(' ⚠️ Playwright init failed. Run manually:', 'yellow');
|
|
752
|
+
log(' npm init playwright@latest', 'yellow');
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
|
|
467
757
|
// ========================================
|
|
468
758
|
// Success Summary
|
|
469
759
|
// ========================================
|
|
470
760
|
log('\n' + '═'.repeat(60), 'green');
|
|
471
|
-
log('🎉 API Development Tools v3.0 installed successfully!', 'green');
|
|
761
|
+
log('🎉 API Development Tools v3.10.0 installed successfully!', 'green');
|
|
472
762
|
log('═'.repeat(60) + '\n', 'green');
|
|
473
763
|
|
|
474
764
|
log('📋 What was installed:', 'bright');
|
|
475
765
|
log(' Commands: .claude/commands/*.md', 'blue');
|
|
476
|
-
log(' Hooks: .claude/hooks/*.py (
|
|
766
|
+
log(' Hooks: .claude/hooks/*.py (enforcement + user checkpoints)', 'blue');
|
|
477
767
|
log(' Settings: .claude/settings.json', 'blue');
|
|
478
768
|
log(' State: .claude/api-dev-state.json', 'blue');
|
|
769
|
+
log(' Registry: .claude/registry.json (tracks APIs, components, pages)', 'blue');
|
|
770
|
+
log(' Brand: .claude/BRAND_GUIDE.md (customize for your branding)', 'blue');
|
|
771
|
+
log(' Budgets: .claude/performance-budgets.json (TDD gate thresholds)', 'blue');
|
|
479
772
|
log(' Research: .claude/research/ (with freshness tracking)', 'blue');
|
|
480
773
|
log(' Scripts: scripts/api-dev-tools/*.ts (manifest generation)', 'blue');
|
|
481
774
|
log(' MCP: context7, github (via claude mcp add)', 'blue');
|
|
482
775
|
log(' Test UI: /api-test page + /api/test-structure API (if Next.js)', 'blue');
|
|
483
776
|
|
|
484
|
-
log('\n🆕 New in v3.0:', 'bright');
|
|
485
|
-
log(' •
|
|
486
|
-
log(' •
|
|
487
|
-
log(' •
|
|
488
|
-
log(' •
|
|
489
|
-
log(' •
|
|
490
|
-
log(' •
|
|
777
|
+
log('\n🆕 New in v3.10.0:', 'bright');
|
|
778
|
+
log(' • Enhanced installer with detailed optional tools info', 'cyan');
|
|
779
|
+
log(' • UI workflow auto-prompts for Storybook/Playwright installation', 'cyan');
|
|
780
|
+
log(' • Demo JSONs updated for 13-phase workflow accuracy', 'cyan');
|
|
781
|
+
log(' • Animated 3D grid hero header on showcase pages', 'cyan');
|
|
782
|
+
log(' • Dev Tools landing page at /dev-tools', 'cyan');
|
|
783
|
+
log(' • Multi-endpoint API selector (e.g., /tts, /voices, /models)', 'cyan');
|
|
784
|
+
log(' • Audio playback for TTS/voice API responses', 'cyan');
|
|
785
|
+
log(' • Enhanced Hustle branding (#BA0C2F)', 'cyan');
|
|
786
|
+
log(' • Dark mode support throughout', 'cyan');
|
|
787
|
+
|
|
788
|
+
log('\n📦 v3.9.0 Features (included):', 'bright');
|
|
789
|
+
log(' • /hustle-ui-create command for components and pages', 'cyan');
|
|
790
|
+
log(' • UI Showcase page (grid + modal preview at /ui-showcase)', 'cyan');
|
|
791
|
+
log(' • API Showcase page (interactive testing at /api-showcase)', 'cyan');
|
|
792
|
+
log(' • Brand guide integration (.claude/BRAND_GUIDE.md)', 'cyan');
|
|
793
|
+
log(' • Performance budgets as TDD gates (memory, re-renders, timing)', 'cyan');
|
|
794
|
+
log(' • ShadCN component detection in src/components/ui/', 'cyan');
|
|
795
|
+
log(' • 4-step verification (responsive + brand + tests + memory)', 'cyan');
|
|
796
|
+
log(' • Storybook + Playwright testing templates with thresholds', 'cyan');
|
|
797
|
+
|
|
798
|
+
log('\n📦 v3.8.0 Features (included):', 'bright');
|
|
799
|
+
log(' • /hustle-combine command for API orchestration', 'cyan');
|
|
800
|
+
log(' • Central registry (registry.json) tracks all created elements', 'cyan');
|
|
491
801
|
|
|
492
802
|
log('\n🔒 User Checkpoint Enforcement:', 'bright');
|
|
493
803
|
log(' • Phase 1: "Which interpretation?" (disambiguation)', 'cyan');
|
|
@@ -502,15 +812,25 @@ function main() {
|
|
|
502
812
|
log(' • Phase 12: "Documentation complete?" (final checklist)', 'cyan');
|
|
503
813
|
|
|
504
814
|
log('\n📚 Available Commands:', 'bright');
|
|
505
|
-
log('
|
|
506
|
-
log(' /api-
|
|
507
|
-
log(' /
|
|
508
|
-
log(' /api-
|
|
509
|
-
log(' /api-
|
|
510
|
-
log(' /api-
|
|
815
|
+
log(' API Development:', 'bright');
|
|
816
|
+
log(' /hustle-api-create [endpoint] - Complete 13-phase API workflow', 'blue');
|
|
817
|
+
log(' /hustle-combine [api|ui] - Combine existing APIs into orchestration', 'blue');
|
|
818
|
+
log(' /hustle-api-interview [endpoint] - Questions FROM research', 'blue');
|
|
819
|
+
log(' /hustle-api-research [library] - Adaptive propose-approve research', 'blue');
|
|
820
|
+
log(' /hustle-api-verify [endpoint] - Manual Phase 10 verification', 'blue');
|
|
821
|
+
log(' /hustle-api-env [endpoint] - Check API keys and environment', 'blue');
|
|
822
|
+
log(' /hustle-api-status [endpoint] - Track 13-phase progress', 'blue');
|
|
823
|
+
log('', 'blue');
|
|
824
|
+
log(' UI Development:', 'bright');
|
|
825
|
+
log(' /hustle-ui-create [name] - Create component or page (13-phase)', 'blue');
|
|
826
|
+
log(' • Brand guide integration', 'blue');
|
|
827
|
+
log(' • ShadCN component detection', 'blue');
|
|
828
|
+
log(' • 4-step verification', 'blue');
|
|
829
|
+
log(' • UI Showcase auto-update', 'blue');
|
|
511
830
|
|
|
512
831
|
log('\n🚀 Quick Start:', 'bright');
|
|
513
|
-
log(' /api-create my-endpoint', 'blue');
|
|
832
|
+
log(' API: /hustle-api-create my-endpoint', 'blue');
|
|
833
|
+
log(' UI: /hustle-ui-create Button', 'blue');
|
|
514
834
|
|
|
515
835
|
log('\n💡 Check progress anytime:', 'yellow');
|
|
516
836
|
log(' cat .claude/api-dev-state.json | jq \'.phases\'', 'yellow');
|
|
@@ -518,6 +838,61 @@ function main() {
|
|
|
518
838
|
log('\n📖 Documentation:', 'bright');
|
|
519
839
|
log(` ${path.join(commandsDir, 'README.md')}\n`, 'blue');
|
|
520
840
|
|
|
841
|
+
log('\n🎨 Showcase Pages:', 'bright');
|
|
842
|
+
log(' /dev-tools - Landing page with all dev tools', 'blue');
|
|
843
|
+
log(' /api-showcase - Interactive API testing', 'blue');
|
|
844
|
+
log(' /ui-showcase - Live component previews', 'blue');
|
|
845
|
+
|
|
846
|
+
// Enhanced Optional Development Tools Section
|
|
847
|
+
log('\n' + '─'.repeat(60), 'yellow');
|
|
848
|
+
log('📦 OPTIONAL DEVELOPMENT TOOLS', 'yellow');
|
|
849
|
+
log('─'.repeat(60), 'yellow');
|
|
850
|
+
log(' The following tools are OPTIONAL but enhance UI development.', 'bright');
|
|
851
|
+
log(' Install now with flags, or later when prompted during /hustle-ui-create.\n', 'bright');
|
|
852
|
+
|
|
853
|
+
log(' ┌──────────────────────────────────────────────────────────┐', 'cyan');
|
|
854
|
+
log(' │ STORYBOOK (Component Development) │', 'cyan');
|
|
855
|
+
log(' ├──────────────────────────────────────────────────────────┤', 'cyan');
|
|
856
|
+
log(' │ Size: ~50MB │', 'cyan');
|
|
857
|
+
log(' │ Purpose: Visual component testing, interactive docs │', 'cyan');
|
|
858
|
+
log(' │ Required: /hustle-ui-create (component mode) │', 'cyan');
|
|
859
|
+
log(' │ Without: Cannot write .stories.tsx files │', 'cyan');
|
|
860
|
+
log(' │ Install: --with-storybook flag OR during UI workflow │', 'cyan');
|
|
861
|
+
log(' │ Command: npx storybook@latest init │', 'cyan');
|
|
862
|
+
log(' └──────────────────────────────────────────────────────────┘', 'cyan');
|
|
863
|
+
|
|
864
|
+
log(' ┌──────────────────────────────────────────────────────────┐', 'magenta');
|
|
865
|
+
log(' │ PLAYWRIGHT (E2E Testing) │', 'magenta');
|
|
866
|
+
log(' ├──────────────────────────────────────────────────────────┤', 'magenta');
|
|
867
|
+
log(' │ Size: ~200MB (includes browser binaries) │', 'magenta');
|
|
868
|
+
log(' │ Purpose: End-to-end page testing, cross-browser │', 'magenta');
|
|
869
|
+
log(' │ Required: /hustle-ui-create-page (page mode) │', 'magenta');
|
|
870
|
+
log(' │ Without: Cannot write .e2e.test.ts files │', 'magenta');
|
|
871
|
+
log(' │ Install: --with-playwright flag OR during UI workflow │', 'magenta');
|
|
872
|
+
log(' │ Command: npm init playwright@latest │', 'magenta');
|
|
873
|
+
log(' └──────────────────────────────────────────────────────────┘', 'magenta');
|
|
874
|
+
|
|
875
|
+
log(' ┌──────────────────────────────────────────────────────────┐', 'blue');
|
|
876
|
+
log(' │ SANDPACK (Live Editing) │', 'blue');
|
|
877
|
+
log(' ├──────────────────────────────────────────────────────────┤', 'blue');
|
|
878
|
+
log(' │ Size: ~5MB │', 'blue');
|
|
879
|
+
log(' │ Purpose: Live code editing in UI Showcase │', 'blue');
|
|
880
|
+
log(' │ Required: Interactive component playground │', 'blue');
|
|
881
|
+
log(' │ Without: Static previews only (still functional) │', 'blue');
|
|
882
|
+
log(' │ Install: --with-sandpack flag │', 'blue');
|
|
883
|
+
log(' │ Command: npm install @codesandbox/sandpack-react │', 'blue');
|
|
884
|
+
log(' └──────────────────────────────────────────────────────────┘', 'blue');
|
|
885
|
+
|
|
886
|
+
log('\n 💡 UI Workflow Behavior:', 'bright');
|
|
887
|
+
log(' When you run /hustle-ui-create without Storybook or Playwright:', 'bright');
|
|
888
|
+
log(' 1. The hook will BLOCK writing test/story files', 'bright');
|
|
889
|
+
log(' 2. You\'ll see the install command and be prompted to install', 'bright');
|
|
890
|
+
log(' 3. After installing, the workflow continues automatically', 'bright');
|
|
891
|
+
log(' 4. You can skip and install later, but Phase 8-10 will be blocked', 'bright');
|
|
892
|
+
|
|
893
|
+
log('\n Example with all optional tools:', 'yellow');
|
|
894
|
+
log(' npx @hustle-together/api-dev-tools --with-storybook --with-playwright --with-sandpack\n', 'yellow');
|
|
895
|
+
|
|
521
896
|
// ========================================
|
|
522
897
|
// 5. Verify Installation
|
|
523
898
|
// ========================================
|