@hustle-together/api-dev-tools 3.6.5 → 3.9.2
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 +5307 -258
- package/bin/cli.js +348 -20
- package/commands/README.md +459 -71
- package/commands/hustle-api-continue.md +158 -0
- package/commands/{api-create.md → hustle-api-create.md} +22 -2
- 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.md +825 -0
- package/hooks/api-workflow-check.py +385 -19
- package/hooks/cache-research.py +337 -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-brand-guide.py +131 -0
- package/hooks/enforce-documentation.py +60 -8
- package/hooks/enforce-freshness.py +184 -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 +981 -0
- package/hooks/session-logger.py +297 -0
- package/hooks/session-startup.py +65 -10
- 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 +148 -0
- package/package.json +8 -2
- 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 +179 -161
- package/templates/api-showcase/APICard.tsx +153 -0
- package/templates/api-showcase/APIModal.tsx +375 -0
- package/templates/api-showcase/APIShowcase.tsx +231 -0
- package/templates/api-showcase/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 +74 -0
- package/templates/shared/HeroHeader.tsx +261 -0
- package/templates/shared/index.ts +1 -0
- package/templates/ui-showcase/PreviewCard.tsx +315 -0
- package/templates/ui-showcase/PreviewModal.tsx +676 -0
- package/templates/ui-showcase/UIShowcase.tsx +262 -0
- package/templates/ui-showcase/page.tsx +26 -0
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,95 @@ 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.
|
|
761
|
+
log('🎉 API Development Tools v3.9.2 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.
|
|
485
|
-
log(' •
|
|
486
|
-
log(' •
|
|
487
|
-
log(' •
|
|
488
|
-
log(' •
|
|
489
|
-
log(' •
|
|
490
|
-
log(' •
|
|
777
|
+
log('\n🆕 New in v3.9.2:', 'bright');
|
|
778
|
+
log(' • Animated 3D grid hero header on showcase pages', 'cyan');
|
|
779
|
+
log(' • Dev Tools landing page at /dev-tools', 'cyan');
|
|
780
|
+
log(' • Multi-endpoint API selector (e.g., /tts, /voices, /models)', 'cyan');
|
|
781
|
+
log(' • Audio playback for TTS/voice API responses', 'cyan');
|
|
782
|
+
log(' • Enhanced Hustle branding (#BA0C2F)', 'cyan');
|
|
783
|
+
log(' • Dark mode support throughout', 'cyan');
|
|
784
|
+
|
|
785
|
+
log('\n📦 v3.9.0 Features (included):', 'bright');
|
|
786
|
+
log(' • /hustle-ui-create command for components and pages', 'cyan');
|
|
787
|
+
log(' • UI Showcase page (grid + modal preview at /ui-showcase)', 'cyan');
|
|
788
|
+
log(' • API Showcase page (interactive testing at /api-showcase)', 'cyan');
|
|
789
|
+
log(' • Brand guide integration (.claude/BRAND_GUIDE.md)', 'cyan');
|
|
790
|
+
log(' • Performance budgets as TDD gates (memory, re-renders, timing)', 'cyan');
|
|
791
|
+
log(' • ShadCN component detection in src/components/ui/', 'cyan');
|
|
792
|
+
log(' • 4-step verification (responsive + brand + tests + memory)', 'cyan');
|
|
793
|
+
log(' • Storybook + Playwright testing templates with thresholds', 'cyan');
|
|
794
|
+
|
|
795
|
+
log('\n📦 v3.8.0 Features (included):', 'bright');
|
|
796
|
+
log(' • /hustle-combine command for API orchestration', 'cyan');
|
|
797
|
+
log(' • Central registry (registry.json) tracks all created elements', 'cyan');
|
|
491
798
|
|
|
492
799
|
log('\n🔒 User Checkpoint Enforcement:', 'bright');
|
|
493
800
|
log(' • Phase 1: "Which interpretation?" (disambiguation)', 'cyan');
|
|
@@ -502,15 +809,25 @@ function main() {
|
|
|
502
809
|
log(' • Phase 12: "Documentation complete?" (final checklist)', 'cyan');
|
|
503
810
|
|
|
504
811
|
log('\n📚 Available Commands:', 'bright');
|
|
505
|
-
log('
|
|
506
|
-
log(' /api-
|
|
507
|
-
log(' /
|
|
508
|
-
log(' /api-
|
|
509
|
-
log(' /api-
|
|
510
|
-
log(' /api-
|
|
812
|
+
log(' API Development:', 'bright');
|
|
813
|
+
log(' /hustle-api-create [endpoint] - Complete 13-phase API workflow', 'blue');
|
|
814
|
+
log(' /hustle-combine [api|ui] - Combine existing APIs into orchestration', 'blue');
|
|
815
|
+
log(' /hustle-api-interview [endpoint] - Questions FROM research', 'blue');
|
|
816
|
+
log(' /hustle-api-research [library] - Adaptive propose-approve research', 'blue');
|
|
817
|
+
log(' /hustle-api-verify [endpoint] - Manual Phase 10 verification', 'blue');
|
|
818
|
+
log(' /hustle-api-env [endpoint] - Check API keys and environment', 'blue');
|
|
819
|
+
log(' /hustle-api-status [endpoint] - Track 13-phase progress', 'blue');
|
|
820
|
+
log('', 'blue');
|
|
821
|
+
log(' UI Development:', 'bright');
|
|
822
|
+
log(' /hustle-ui-create [name] - Create component or page (13-phase)', 'blue');
|
|
823
|
+
log(' • Brand guide integration', 'blue');
|
|
824
|
+
log(' • ShadCN component detection', 'blue');
|
|
825
|
+
log(' • 4-step verification', 'blue');
|
|
826
|
+
log(' • UI Showcase auto-update', 'blue');
|
|
511
827
|
|
|
512
828
|
log('\n🚀 Quick Start:', 'bright');
|
|
513
|
-
log(' /api-create my-endpoint', 'blue');
|
|
829
|
+
log(' API: /hustle-api-create my-endpoint', 'blue');
|
|
830
|
+
log(' UI: /hustle-ui-create Button', 'blue');
|
|
514
831
|
|
|
515
832
|
log('\n💡 Check progress anytime:', 'yellow');
|
|
516
833
|
log(' cat .claude/api-dev-state.json | jq \'.phases\'', 'yellow');
|
|
@@ -518,6 +835,17 @@ function main() {
|
|
|
518
835
|
log('\n📖 Documentation:', 'bright');
|
|
519
836
|
log(` ${path.join(commandsDir, 'README.md')}\n`, 'blue');
|
|
520
837
|
|
|
838
|
+
log('\n🎨 Showcase Pages:', 'bright');
|
|
839
|
+
log(' /dev-tools - Landing page with all dev tools', 'blue');
|
|
840
|
+
log(' /api-showcase - Interactive API testing', 'blue');
|
|
841
|
+
log(' /ui-showcase - Live component previews', 'blue');
|
|
842
|
+
|
|
843
|
+
log('\n📦 Optional Tools (use --with-* flags to auto-install):', 'yellow');
|
|
844
|
+
log(' --with-sandpack Live component editing in UI Showcase', 'yellow');
|
|
845
|
+
log(' --with-storybook Component development environment', 'yellow');
|
|
846
|
+
log(' --with-playwright E2E testing framework', 'yellow');
|
|
847
|
+
log('\n Example: npx @hustle-together/api-dev-tools --with-sandpack --with-storybook\n', 'yellow');
|
|
848
|
+
|
|
521
849
|
// ========================================
|
|
522
850
|
// 5. Verify Installation
|
|
523
851
|
// ========================================
|