@hustle-together/api-dev-tools 3.12.3 → 4.5.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.
Files changed (159) hide show
  1. package/.claude/adr-requests/.gitkeep +10 -0
  2. package/.claude/agents/adr-researcher.md +109 -0
  3. package/.claude/agents/visual-analyzer.md +183 -0
  4. package/.claude/api-dev-state.json +7 -463
  5. package/.claude/documentation-audit.json +114 -0
  6. package/.claude/registry.json +289 -0
  7. package/.claude/settings.json +45 -1
  8. package/.claude/workflow-logs/None.json +49 -0
  9. package/.claude/workflow-logs/session-20251230-143727.json +106 -0
  10. package/.skills/adr-deep-research/SKILL.md +351 -0
  11. package/.skills/api-create/SKILL.md +116 -17
  12. package/.skills/api-research/SKILL.md +130 -0
  13. package/.skills/docs-sync/SKILL.md +260 -0
  14. package/.skills/docs-update/SKILL.md +205 -0
  15. package/.skills/hustle-brand/SKILL.md +368 -0
  16. package/.skills/hustle-build/SKILL.md +786 -0
  17. package/.skills/hustle-build-review/SKILL.md +518 -0
  18. package/.skills/parallel-spawn/SKILL.md +212 -0
  19. package/.skills/ralph-continue/SKILL.md +151 -0
  20. package/.skills/ralph-loop/SKILL.md +341 -0
  21. package/.skills/ralph-status/SKILL.md +87 -0
  22. package/.skills/refactor/SKILL.md +59 -0
  23. package/.skills/shadcn/SKILL.md +522 -0
  24. package/.skills/test-all/SKILL.md +210 -0
  25. package/.skills/test-builds/SKILL.md +208 -0
  26. package/.skills/test-debug/SKILL.md +212 -0
  27. package/.skills/test-e2e/SKILL.md +168 -0
  28. package/.skills/test-review/SKILL.md +707 -0
  29. package/.skills/test-unit/SKILL.md +143 -0
  30. package/.skills/test-visual/SKILL.md +301 -0
  31. package/.skills/token-report/SKILL.md +132 -0
  32. package/CHANGELOG.md +575 -0
  33. package/README.md +426 -56
  34. package/bin/cli.js +1538 -88
  35. package/commands/hustle-api-create.md +22 -0
  36. package/commands/hustle-build.md +259 -0
  37. package/commands/hustle-combine.md +81 -2
  38. package/commands/hustle-ui-create-page.md +84 -2
  39. package/commands/hustle-ui-create.md +82 -2
  40. package/hooks/__pycache__/api-workflow-check.cpython-314.pyc +0 -0
  41. package/hooks/__pycache__/auto-answer.cpython-314.pyc +0 -0
  42. package/hooks/__pycache__/cache-research.cpython-314.pyc +0 -0
  43. package/hooks/__pycache__/check-api-routes.cpython-314.pyc +0 -0
  44. package/hooks/__pycache__/check-playwright-setup.cpython-314.pyc +0 -0
  45. package/hooks/__pycache__/check-storybook-setup.cpython-314.pyc +0 -0
  46. package/hooks/__pycache__/check-update.cpython-314.pyc +0 -0
  47. package/hooks/__pycache__/completion-promise-detector.cpython-314.pyc +0 -0
  48. package/hooks/__pycache__/context-capacity-warning.cpython-314.pyc +0 -0
  49. package/hooks/__pycache__/detect-interruption.cpython-314.pyc +0 -0
  50. package/hooks/__pycache__/docs-update-check.cpython-314.pyc +0 -0
  51. package/hooks/__pycache__/enforce-a11y-audit.cpython-314.pyc +0 -0
  52. package/hooks/__pycache__/enforce-brand-guide.cpython-314.pyc +0 -0
  53. package/hooks/__pycache__/enforce-component-type-confirm.cpython-314.pyc +0 -0
  54. package/hooks/__pycache__/enforce-deep-research.cpython-314.pyc +0 -0
  55. package/hooks/__pycache__/enforce-disambiguation.cpython-314.pyc +0 -0
  56. package/hooks/__pycache__/enforce-documentation.cpython-314.pyc +0 -0
  57. package/hooks/__pycache__/enforce-dry-run.cpython-314.pyc +0 -0
  58. package/hooks/__pycache__/enforce-environment.cpython-314.pyc +0 -0
  59. package/hooks/__pycache__/enforce-external-research.cpython-314.pyc +0 -0
  60. package/hooks/__pycache__/enforce-freshness.cpython-314.pyc +0 -0
  61. package/hooks/__pycache__/enforce-interview.cpython-314.pyc +0 -0
  62. package/hooks/__pycache__/enforce-page-components.cpython-314.pyc +0 -0
  63. package/hooks/__pycache__/enforce-page-data-schema.cpython-314.pyc +0 -0
  64. package/hooks/__pycache__/enforce-questions-sourced.cpython-314.pyc +0 -0
  65. package/hooks/__pycache__/enforce-refactor.cpython-314.pyc +0 -0
  66. package/hooks/__pycache__/enforce-research.cpython-314.pyc +0 -0
  67. package/hooks/__pycache__/enforce-schema-from-interview.cpython-314.pyc +0 -0
  68. package/hooks/__pycache__/enforce-schema.cpython-314.pyc +0 -0
  69. package/hooks/__pycache__/enforce-scope.cpython-314.pyc +0 -0
  70. package/hooks/__pycache__/enforce-tdd-red.cpython-314.pyc +0 -0
  71. package/hooks/__pycache__/enforce-ui-disambiguation.cpython-314.pyc +0 -0
  72. package/hooks/__pycache__/enforce-ui-interview.cpython-314.pyc +0 -0
  73. package/hooks/__pycache__/enforce-verify.cpython-314.pyc +0 -0
  74. package/hooks/__pycache__/generate-adr-options.cpython-314.pyc +0 -0
  75. package/hooks/__pycache__/generate-manifest-entry.cpython-314.pyc +0 -0
  76. package/hooks/__pycache__/hook_utils.cpython-314.pyc +0 -0
  77. package/hooks/__pycache__/notify-input-needed.cpython-314.pyc +0 -0
  78. package/hooks/__pycache__/notify-phase-complete.cpython-314.pyc +0 -0
  79. package/hooks/__pycache__/ntfy-on-question.cpython-314.pyc +0 -0
  80. package/hooks/__pycache__/orchestrator-completion.cpython-314.pyc +0 -0
  81. package/hooks/__pycache__/orchestrator-handoff.cpython-314.pyc +0 -0
  82. package/hooks/__pycache__/orchestrator-session-startup.cpython-314.pyc +0 -0
  83. package/hooks/__pycache__/parallel-orchestrator.cpython-314.pyc +0 -0
  84. package/hooks/__pycache__/periodic-reground.cpython-314.pyc +0 -0
  85. package/hooks/__pycache__/project-document-prompt.cpython-314.pyc +0 -0
  86. package/hooks/__pycache__/remote-question-proxy.cpython-314.pyc +0 -0
  87. package/hooks/__pycache__/remote-question-server.cpython-314.pyc +0 -0
  88. package/hooks/__pycache__/run-code-review.cpython-314.pyc +0 -0
  89. package/hooks/__pycache__/run-visual-qa.cpython-314.pyc +0 -0
  90. package/hooks/__pycache__/session-logger.cpython-314.pyc +0 -0
  91. package/hooks/__pycache__/session-startup.cpython-314.pyc +0 -0
  92. package/hooks/__pycache__/track-scope-coverage.cpython-314.pyc +0 -0
  93. package/hooks/__pycache__/track-token-usage.cpython-314.pyc +0 -0
  94. package/hooks/__pycache__/track-tool-use.cpython-314.pyc +0 -0
  95. package/hooks/__pycache__/update-adr-decision.cpython-314.pyc +0 -0
  96. package/hooks/__pycache__/update-api-showcase.cpython-314.pyc +0 -0
  97. package/hooks/__pycache__/update-registry.cpython-314.pyc +0 -0
  98. package/hooks/__pycache__/update-ui-showcase.cpython-314.pyc +0 -0
  99. package/hooks/__pycache__/verify-after-green.cpython-314.pyc +0 -0
  100. package/hooks/__pycache__/verify-implementation.cpython-314.pyc +0 -0
  101. package/hooks/api-workflow-check.py +34 -0
  102. package/hooks/auto-answer.py +305 -0
  103. package/hooks/check-update.py +132 -0
  104. package/hooks/completion-promise-detector.py +293 -0
  105. package/hooks/context-capacity-warning.py +171 -0
  106. package/hooks/docs-update-check.py +120 -0
  107. package/hooks/enforce-dry-run.py +134 -0
  108. package/hooks/enforce-external-research.py +25 -0
  109. package/hooks/enforce-interview.py +20 -0
  110. package/hooks/generate-adr-options.py +282 -0
  111. package/hooks/hook_utils.py +609 -0
  112. package/hooks/lib/__pycache__/__init__.cpython-314.pyc +0 -0
  113. package/hooks/lib/__pycache__/greptile.cpython-314.pyc +0 -0
  114. package/hooks/lib/__pycache__/ntfy.cpython-314.pyc +0 -0
  115. package/hooks/ntfy-on-question.py +240 -0
  116. package/hooks/orchestrator-completion.py +313 -0
  117. package/hooks/orchestrator-handoff.py +267 -0
  118. package/hooks/orchestrator-session-startup.py +146 -0
  119. package/hooks/parallel-orchestrator.py +451 -0
  120. package/hooks/periodic-reground.py +270 -67
  121. package/hooks/project-document-prompt.py +302 -0
  122. package/hooks/remote-question-proxy.py +284 -0
  123. package/hooks/remote-question-server.py +1224 -0
  124. package/hooks/run-code-review.py +176 -29
  125. package/hooks/run-visual-qa.py +338 -0
  126. package/hooks/session-logger.py +27 -1
  127. package/hooks/session-startup.py +113 -0
  128. package/hooks/update-adr-decision.py +236 -0
  129. package/hooks/update-api-showcase.py +13 -1
  130. package/hooks/update-testing-checklist.py +195 -0
  131. package/hooks/update-ui-showcase.py +13 -1
  132. package/package.json +7 -3
  133. package/scripts/extract-schema-docs.cjs +322 -0
  134. package/templates/.skills/hustle-interview/SKILL.md +174 -0
  135. package/templates/CLAUDE-SECTION.md +89 -64
  136. package/templates/adr-viewer/_components/ADRViewer.tsx +326 -0
  137. package/templates/api-dev-state.json +33 -1
  138. package/templates/api-showcase/_components/APIModal.tsx +100 -8
  139. package/templates/api-showcase/_components/APIShowcase.tsx +36 -4
  140. package/templates/api-showcase/_components/APITester.tsx +367 -58
  141. package/templates/brand-page/page.tsx +645 -0
  142. package/templates/component/Component.visual.spec.ts +30 -24
  143. package/templates/docs/page.tsx +230 -0
  144. package/templates/eslint-plugin-zod-schema/index.js +446 -0
  145. package/templates/eslint-plugin-zod-schema/package.json +26 -0
  146. package/templates/github-workflows/security.yml +274 -0
  147. package/templates/hustle-build-defaults.json +136 -0
  148. package/templates/hustle-dev-dashboard/page.tsx +365 -0
  149. package/templates/page/page.e2e.test.ts +30 -26
  150. package/templates/performance-budgets.json +63 -5
  151. package/templates/playwright-report/page.tsx +258 -0
  152. package/templates/registry.json +279 -3
  153. package/templates/review-dashboard/page.tsx +510 -0
  154. package/templates/settings.json +155 -7
  155. package/templates/test-results/page.tsx +237 -0
  156. package/templates/typedoc.json +19 -0
  157. package/templates/ui-showcase/_components/UIShowcase.tsx +48 -1
  158. package/templates/ui-showcase/_components/VisualTestingDashboard.tsx +579 -0
  159. package/templates/ui-showcase/page.tsx +1 -1
@@ -1,18 +1,87 @@
1
1
  {
2
2
  "permissions": {
3
3
  "allow": [
4
+ "Read(*)",
5
+ "Write(*)",
6
+ "Edit(*)",
7
+ "Glob(*)",
8
+ "Grep(*)",
9
+ "LSP(*)",
10
+ "NotebookEdit(*)",
4
11
  "WebSearch",
5
12
  "WebFetch",
6
- "mcp__context7",
7
- "mcp__context7__resolve-library-id",
8
- "mcp__context7__get-library-docs",
9
- "mcp__github",
13
+ "Task",
14
+ "TodoWrite",
15
+ "AskUserQuestion",
16
+ "Skill",
17
+ "mcp__context7__*",
18
+ "mcp__github__*",
19
+ "mcp__linear__*",
20
+ "mcp__supabase__*",
21
+ "mcp__playwright__*",
10
22
  "Bash(claude mcp:*)",
11
- "Bash(pnpm test:*)",
12
- "Bash(npm test:*)",
23
+ "Bash(pnpm *)",
24
+ "Bash(npm *)",
25
+ "Bash(npx *)",
13
26
  "Bash(git status:*)",
14
27
  "Bash(git diff:*)",
15
- "Bash(git log:*)"
28
+ "Bash(git log:*)",
29
+ "Bash(git add:*)",
30
+ "Bash(git commit:*)",
31
+ "Bash(git branch:*)",
32
+ "Bash(git checkout:*)",
33
+ "Bash(curl:*)",
34
+ "Bash(tree:*)",
35
+ "Bash(ls:*)",
36
+ "Bash(cat:*)",
37
+ "Bash(echo:*)",
38
+ "Bash(mkdir:*)",
39
+ "Bash(touch:*)",
40
+ "Bash(cp:*)",
41
+ "Bash(mv:*)",
42
+ "Bash(chmod:*)"
43
+ ],
44
+ "deny": [
45
+ "Read(.env*)",
46
+ "Read(**/.env*)",
47
+ "Read(**/secrets/**)",
48
+ "Read(**/credentials*)",
49
+ "Read(**/*.pem)",
50
+ "Read(**/*.key)",
51
+ "Read(**/.ssh/**)",
52
+ "Read(**/.aws/**)",
53
+ "Read(**/.gcloud/**)",
54
+ "Write(.env*)",
55
+ "Write(**/.env*)",
56
+ "Write(**/secrets/**)",
57
+ "Edit(.env*)",
58
+ "Edit(**/.env*)",
59
+ "Edit(**/secrets/**)",
60
+ "Bash(rm -rf:*)",
61
+ "Bash(sudo:*)",
62
+ "Bash(chmod 777:*)",
63
+ "Bash(chown -R:*)",
64
+ "Bash(git push --force:*)",
65
+ "Bash(git push -f:*)",
66
+ "Bash(git reset --hard:*)",
67
+ "Bash(git clean -fd:*)",
68
+ "Bash(git stash drop:*)",
69
+ "Bash(git branch -D main)",
70
+ "Bash(git branch -D master)",
71
+ "Bash(eval:*)",
72
+ "Write(/etc/**)",
73
+ "Write(/var/**)",
74
+ "Write(/usr/**)",
75
+ "Write(/bin/**)",
76
+ "Write(/sbin/**)",
77
+ "Read(/etc/passwd)",
78
+ "Read(/etc/shadow)",
79
+ "Bash(nmap:*)",
80
+ "Bash(nikto:*)",
81
+ "Bash(sqlmap:*)",
82
+ "Bash(hydra:*)",
83
+ "Bash(metasploit:*)",
84
+ "Bash(msfconsole:*)"
16
85
  ]
17
86
  },
18
87
  "hooks": {
@@ -26,6 +95,18 @@
26
95
  {
27
96
  "type": "command",
28
97
  "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/detect-interruption.py"
98
+ },
99
+ {
100
+ "type": "command",
101
+ "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/check-update.py"
102
+ },
103
+ {
104
+ "type": "command",
105
+ "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/orchestrator-session-startup.py"
106
+ },
107
+ {
108
+ "type": "command",
109
+ "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/parallel-orchestrator.py"
29
110
  }
30
111
  ]
31
112
  }
@@ -36,6 +117,14 @@
36
117
  {
37
118
  "type": "command",
38
119
  "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/enforce-external-research.py"
120
+ },
121
+ {
122
+ "type": "command",
123
+ "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/parallel-orchestrator.py"
124
+ },
125
+ {
126
+ "type": "command",
127
+ "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/completion-promise-detector.py"
39
128
  }
40
129
  ]
41
130
  }
@@ -44,6 +133,10 @@
44
133
  {
45
134
  "matcher": "Write|Edit",
46
135
  "hooks": [
136
+ {
137
+ "type": "command",
138
+ "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/enforce-dry-run.py"
139
+ },
47
140
  {
48
141
  "type": "command",
49
142
  "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/enforce-disambiguation.py"
@@ -140,6 +233,19 @@
140
233
  {
141
234
  "type": "command",
142
235
  "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/enforce-questions-sourced.py"
236
+ },
237
+ {
238
+ "type": "command",
239
+ "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/auto-answer.py"
240
+ }
241
+ ]
242
+ },
243
+ {
244
+ "matcher": "Skill",
245
+ "hooks": [
246
+ {
247
+ "type": "command",
248
+ "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/orchestrator-handoff.py"
143
249
  }
144
250
  ]
145
251
  }
@@ -159,6 +265,27 @@
159
265
  {
160
266
  "type": "command",
161
267
  "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/track-scope-coverage.py"
268
+ },
269
+ {
270
+ "type": "command",
271
+ "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/context-capacity-warning.py"
272
+ },
273
+ {
274
+ "type": "command",
275
+ "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/generate-adr-options.py"
276
+ }
277
+ ]
278
+ },
279
+ {
280
+ "matcher": "AskUserQuestion",
281
+ "hooks": [
282
+ {
283
+ "type": "command",
284
+ "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/ntfy-on-question.py"
285
+ },
286
+ {
287
+ "type": "command",
288
+ "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/update-adr-decision.py"
162
289
  }
163
290
  ]
164
291
  },
@@ -168,6 +295,14 @@
168
295
  {
169
296
  "type": "command",
170
297
  "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/verify-after-green.py"
298
+ },
299
+ {
300
+ "type": "command",
301
+ "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/completion-promise-detector.py"
302
+ },
303
+ {
304
+ "type": "command",
305
+ "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/update-testing-checklist.py"
171
306
  }
172
307
  ]
173
308
  },
@@ -197,6 +332,19 @@
197
332
  {
198
333
  "type": "command",
199
334
  "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/enforce-a11y-audit.py"
335
+ },
336
+ {
337
+ "type": "command",
338
+ "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/completion-promise-detector.py"
339
+ }
340
+ ]
341
+ },
342
+ {
343
+ "matcher": "Skill",
344
+ "hooks": [
345
+ {
346
+ "type": "command",
347
+ "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/orchestrator-completion.py"
200
348
  }
201
349
  ]
202
350
  }
@@ -0,0 +1,237 @@
1
+ "use client";
2
+
3
+ import Link from "next/link";
4
+
5
+ /**
6
+ * Test Results Page
7
+ *
8
+ * Shows Vitest unit test results or instructions to run tests.
9
+ * Designed to work with vitest --reporter=json output.
10
+ *
11
+ * Created with Hustle API Dev Tools (v3.12.12)
12
+ */
13
+ export default function TestResultsPage() {
14
+ // In a real implementation, this would fetch test results from a JSON file
15
+ // For now, we show the empty state with instructions
16
+ const hasResults = false;
17
+
18
+ return (
19
+ <div className="min-h-screen bg-white dark:bg-gray-950">
20
+ {/* Header */}
21
+ <header className="border-b-4 border-black bg-[#BA0C2F] px-6 py-8 dark:border-gray-600">
22
+ <div className="mx-auto max-w-4xl">
23
+ <div className="flex items-center gap-2">
24
+ <Link
25
+ href="/hustle-dev-dashboard"
26
+ className="text-white/80 hover:text-white"
27
+ >
28
+ Dashboard
29
+ </Link>
30
+ <span className="text-white/60">/</span>
31
+ <span className="text-white">Test Results</span>
32
+ </div>
33
+ <h1 className="mt-2 text-3xl font-black text-white">TEST RESULTS</h1>
34
+ <p className="mt-2 text-white/80">Vitest unit test results</p>
35
+ </div>
36
+ </header>
37
+
38
+ {/* Main Content */}
39
+ <main className="mx-auto max-w-4xl px-6 py-8">
40
+ {hasResults ? <TestResults /> : <EmptyState />}
41
+ </main>
42
+
43
+ {/* Footer */}
44
+ <footer className="border-t-2 border-black px-6 py-4 dark:border-gray-600">
45
+ <div className="mx-auto max-w-4xl text-center text-sm text-gray-600 dark:text-gray-400">
46
+ Built with{" "}
47
+ <a
48
+ href="https://github.com/hustle-together/api-dev-tools"
49
+ className="font-bold text-[#BA0C2F] hover:underline"
50
+ >
51
+ Hustle API Dev Tools
52
+ </a>
53
+ </div>
54
+ </footer>
55
+ </div>
56
+ );
57
+ }
58
+
59
+ function TestResults() {
60
+ // Placeholder for actual test results display
61
+ return (
62
+ <div className="space-y-6">
63
+ <div className="grid gap-4 sm:grid-cols-3">
64
+ <StatCard label="Passed" value={0} color="green" />
65
+ <StatCard label="Failed" value={0} color="red" />
66
+ <StatCard label="Skipped" value={0} color="yellow" />
67
+ </div>
68
+ </div>
69
+ );
70
+ }
71
+
72
+ function EmptyState() {
73
+ return (
74
+ <div className="space-y-6">
75
+ {/* Status Card */}
76
+ <div className="border-2 border-black p-6 dark:border-gray-600">
77
+ <div className="flex items-center gap-3">
78
+ <div className="flex h-12 w-12 items-center justify-center rounded-full bg-gray-100 text-2xl dark:bg-gray-800">
79
+ 0
80
+ </div>
81
+ <div>
82
+ <h2 className="text-xl font-bold text-black dark:text-white">
83
+ No Test Results
84
+ </h2>
85
+ <p className="text-gray-600 dark:text-gray-400">
86
+ Run your tests to see results here
87
+ </p>
88
+ </div>
89
+ </div>
90
+ </div>
91
+
92
+ {/* Instructions */}
93
+ <div className="border-2 border-black bg-gray-50 p-6 dark:border-gray-600 dark:bg-gray-900">
94
+ <h3 className="mb-4 font-bold text-black dark:text-white">Run Tests</h3>
95
+ <div className="space-y-4">
96
+ <Step
97
+ number={1}
98
+ title="Run Unit Tests"
99
+ command="pnpm test"
100
+ description="Runs Vitest in watch mode for development"
101
+ />
102
+ <Step
103
+ number={2}
104
+ title="Run Tests Once"
105
+ command="pnpm test:run"
106
+ description="Runs all tests once and exits"
107
+ />
108
+ <Step
109
+ number={3}
110
+ title="Run with Coverage"
111
+ command="pnpm test:coverage"
112
+ description="Generates code coverage report"
113
+ />
114
+ </div>
115
+ </div>
116
+
117
+ {/* Test Commands Reference */}
118
+ <div className="border-2 border-black p-6 dark:border-gray-600">
119
+ <h3 className="mb-4 font-bold text-black dark:text-white">
120
+ Available Commands
121
+ </h3>
122
+ <div className="space-y-3">
123
+ <CommandItem
124
+ command="pnpm test"
125
+ description="Watch mode - reruns on file changes"
126
+ />
127
+ <CommandItem
128
+ command="pnpm test:run"
129
+ description="Single run - CI/CD friendly"
130
+ />
131
+ <CommandItem
132
+ command="pnpm test:coverage"
133
+ description="With coverage report"
134
+ />
135
+ <CommandItem
136
+ command="pnpm test [file]"
137
+ description="Run specific test file"
138
+ />
139
+ </div>
140
+ </div>
141
+
142
+ {/* Test File Conventions */}
143
+ <div className="border-2 border-black bg-gray-50 p-6 dark:border-gray-600 dark:bg-gray-900">
144
+ <h3 className="mb-4 font-bold text-black dark:text-white">
145
+ Test File Conventions
146
+ </h3>
147
+ <ul className="space-y-2 text-sm text-gray-600 dark:text-gray-400">
148
+ <li className="flex items-center gap-2">
149
+ <code className="rounded bg-white px-2 py-0.5 text-[#BA0C2F] dark:bg-gray-800">
150
+ *.test.ts
151
+ </code>
152
+ Unit tests
153
+ </li>
154
+ <li className="flex items-center gap-2">
155
+ <code className="rounded bg-white px-2 py-0.5 text-[#BA0C2F] dark:bg-gray-800">
156
+ *.api.test.ts
157
+ </code>
158
+ API route tests
159
+ </li>
160
+ <li className="flex items-center gap-2">
161
+ <code className="rounded bg-white px-2 py-0.5 text-[#BA0C2F] dark:bg-gray-800">
162
+ __tests__/
163
+ </code>
164
+ Test directory convention
165
+ </li>
166
+ </ul>
167
+ </div>
168
+ </div>
169
+ );
170
+ }
171
+
172
+ function StatCard({
173
+ label,
174
+ value,
175
+ color,
176
+ }: {
177
+ label: string;
178
+ value: number;
179
+ color: "green" | "red" | "yellow";
180
+ }) {
181
+ const colorClasses = {
182
+ green: "text-green-600",
183
+ red: "text-red-600",
184
+ yellow: "text-yellow-600",
185
+ };
186
+
187
+ return (
188
+ <div className="border-2 border-black bg-white p-4 dark:border-gray-600 dark:bg-gray-900">
189
+ <p className={`text-3xl font-black ${colorClasses[color]}`}>{value}</p>
190
+ <p className="text-sm text-gray-600 dark:text-gray-400">{label}</p>
191
+ </div>
192
+ );
193
+ }
194
+
195
+ function Step({
196
+ number,
197
+ title,
198
+ command,
199
+ description,
200
+ }: {
201
+ number: number;
202
+ title: string;
203
+ command: string;
204
+ description: string;
205
+ }) {
206
+ return (
207
+ <div className="flex gap-4">
208
+ <div className="flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-full bg-[#BA0C2F] text-sm font-bold text-white">
209
+ {number}
210
+ </div>
211
+ <div>
212
+ <p className="font-medium text-black dark:text-white">{title}</p>
213
+ <code className="mt-1 block rounded bg-white px-3 py-1 font-mono text-sm text-[#BA0C2F] dark:bg-gray-800">
214
+ {command}
215
+ </code>
216
+ <p className="mt-1 text-sm text-gray-600 dark:text-gray-400">
217
+ {description}
218
+ </p>
219
+ </div>
220
+ </div>
221
+ );
222
+ }
223
+
224
+ function CommandItem({
225
+ command,
226
+ description,
227
+ }: {
228
+ command: string;
229
+ description: string;
230
+ }) {
231
+ return (
232
+ <div className="flex items-center justify-between rounded bg-white px-4 py-2 dark:bg-gray-800">
233
+ <code className="font-mono text-[#BA0C2F]">{command}</code>
234
+ <span className="text-sm text-gray-500">{description}</span>
235
+ </div>
236
+ );
237
+ }
@@ -0,0 +1,19 @@
1
+ {
2
+ "$schema": "https://typedoc.org/schema.json",
3
+ "entryPoints": ["src/lib/schemas/*.ts", "src/app/api/**/*.ts"],
4
+ "out": "docs/api",
5
+ "plugin": ["typedoc-plugin-markdown"],
6
+ "exclude": ["**/*.test.ts", "**/__tests__/**", "**/node_modules/**"],
7
+ "excludePrivate": true,
8
+ "excludeInternal": true,
9
+ "readme": "none",
10
+ "name": "API Documentation",
11
+ "includeVersion": true,
12
+ "categorizeByGroup": true,
13
+ "sort": ["alphabetical"],
14
+ "validation": {
15
+ "notExported": false,
16
+ "invalidLink": false,
17
+ "notDocumented": false
18
+ }
19
+ }
@@ -1,14 +1,16 @@
1
1
  "use client";
2
2
 
3
3
  import { useState, useMemo } from "react";
4
- import { HeroHeader } from "../shared/HeroHeader";
4
+ import { HeroHeader } from "../../shared/HeroHeader";
5
5
  import { PreviewCard } from "./PreviewCard";
6
6
  import { PreviewModal } from "./PreviewModal";
7
+ import { VisualTestingDashboard } from "./VisualTestingDashboard";
7
8
 
8
9
  // Import registry - this will be updated by the CLI when components are created
9
10
  // Note: In production, this could be fetched from an API route
10
11
  import registry from "@/../.claude/registry.json";
11
12
 
13
+ type ViewType = "gallery" | "visual-testing";
12
14
  type FilterType = "all" | "components" | "pages";
13
15
 
14
16
  interface RegistryItem {
@@ -48,6 +50,7 @@ interface Registry {
48
50
  * Created with Hustle API Dev Tools (v3.9.2)
49
51
  */
50
52
  export function UIShowcase() {
53
+ const [view, setView] = useState<ViewType>("gallery");
51
54
  const [filter, setFilter] = useState<FilterType>("all");
52
55
  const [searchQuery, setSearchQuery] = useState("");
53
56
  const [selectedItem, setSelectedItem] = useState<{
@@ -106,8 +109,52 @@ export function UIShowcase() {
106
109
  const componentCount = Object.keys(typedRegistry.components || {}).length;
107
110
  const pageCount = Object.keys(typedRegistry.pages || {}).length;
108
111
 
112
+ // If viewing visual testing dashboard, render that instead
113
+ if (view === "visual-testing") {
114
+ return (
115
+ <div className="min-h-screen bg-white dark:bg-[#050505]">
116
+ {/* View Switcher */}
117
+ <div className="border-b-2 border-black bg-gray-100 dark:border-gray-600 dark:bg-gray-900">
118
+ <div className="container mx-auto flex gap-0 px-4">
119
+ <button
120
+ onClick={() => setView("gallery")}
121
+ className="border-b-4 border-transparent px-6 py-3 font-bold text-gray-600 hover:text-black dark:text-gray-400 dark:hover:text-white"
122
+ >
123
+ Gallery View
124
+ </button>
125
+ <button
126
+ onClick={() => setView("visual-testing")}
127
+ className="border-b-4 border-[#BA0C2F] px-6 py-3 font-bold text-[#BA0C2F]"
128
+ >
129
+ Visual Testing
130
+ </button>
131
+ </div>
132
+ </div>
133
+ <VisualTestingDashboard />
134
+ </div>
135
+ );
136
+ }
137
+
109
138
  return (
110
139
  <div className="min-h-screen bg-white dark:bg-[#050505]">
140
+ {/* View Switcher */}
141
+ <div className="border-b-2 border-black bg-gray-100 dark:border-gray-600 dark:bg-gray-900">
142
+ <div className="container mx-auto flex gap-0 px-4">
143
+ <button
144
+ onClick={() => setView("gallery")}
145
+ className="border-b-4 border-[#BA0C2F] px-6 py-3 font-bold text-[#BA0C2F]"
146
+ >
147
+ Gallery View
148
+ </button>
149
+ <button
150
+ onClick={() => setView("visual-testing")}
151
+ className="border-b-4 border-transparent px-6 py-3 font-bold text-gray-600 hover:text-black dark:text-gray-400 dark:hover:text-white"
152
+ >
153
+ Visual Testing
154
+ </button>
155
+ </div>
156
+ </div>
157
+
111
158
  {/* Hero Header */}
112
159
  <HeroHeader
113
160
  title="UI Showcase"