@hustle-together/api-dev-tools 3.12.3 → 3.12.16

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 (96) hide show
  1. package/.claude/commands/hustle-build.md +259 -0
  2. package/.claude/commands/hustle-combine.md +1089 -0
  3. package/.claude/commands/hustle-ui-create-page.md +1078 -0
  4. package/.claude/commands/hustle-ui-create.md +1058 -0
  5. package/.claude/hooks/auto-answer.py +305 -0
  6. package/.claude/hooks/cache-research.py +337 -0
  7. package/.claude/hooks/check-api-routes.py +168 -0
  8. package/.claude/hooks/check-playwright-setup.py +103 -0
  9. package/.claude/hooks/check-storybook-setup.py +81 -0
  10. package/.claude/hooks/check-update.py +132 -0
  11. package/.claude/hooks/completion-promise-detector.py +293 -0
  12. package/.claude/hooks/context-capacity-warning.py +171 -0
  13. package/.claude/hooks/detect-interruption.py +165 -0
  14. package/.claude/hooks/docs-update-check.py +120 -0
  15. package/.claude/hooks/enforce-a11y-audit.py +202 -0
  16. package/.claude/hooks/enforce-brand-guide.py +241 -0
  17. package/.claude/hooks/enforce-component-type-confirm.py +97 -0
  18. package/.claude/hooks/enforce-dry-run.py +134 -0
  19. package/.claude/hooks/enforce-freshness.py +184 -0
  20. package/.claude/hooks/enforce-page-components.py +186 -0
  21. package/.claude/hooks/enforce-page-data-schema.py +155 -0
  22. package/.claude/hooks/enforce-questions-sourced.py +146 -0
  23. package/.claude/hooks/enforce-schema-from-interview.py +248 -0
  24. package/.claude/hooks/enforce-ui-disambiguation.py +108 -0
  25. package/.claude/hooks/enforce-ui-interview.py +130 -0
  26. package/.claude/hooks/generate-adr-options.py +282 -0
  27. package/.claude/hooks/generate-manifest-entry.py +1161 -0
  28. package/.claude/hooks/hook_utils.py +609 -0
  29. package/.claude/hooks/lib/__init__.py +1 -0
  30. package/.claude/hooks/lib/__pycache__/__init__.cpython-314.pyc +0 -0
  31. package/.claude/hooks/lib/__pycache__/greptile.cpython-314.pyc +0 -0
  32. package/.claude/hooks/lib/__pycache__/ntfy.cpython-314.pyc +0 -0
  33. package/.claude/hooks/lib/greptile.py +355 -0
  34. package/.claude/hooks/lib/ntfy.py +209 -0
  35. package/.claude/hooks/notify-input-needed.py +73 -0
  36. package/.claude/hooks/notify-phase-complete.py +90 -0
  37. package/.claude/hooks/ntfy-on-question.py +240 -0
  38. package/.claude/hooks/orchestrator-completion.py +313 -0
  39. package/.claude/hooks/orchestrator-handoff.py +267 -0
  40. package/.claude/hooks/orchestrator-session-startup.py +146 -0
  41. package/.claude/hooks/parallel-orchestrator.py +451 -0
  42. package/.claude/hooks/project-document-prompt.py +302 -0
  43. package/.claude/hooks/remote-question-proxy.py +284 -0
  44. package/.claude/hooks/remote-question-server.py +1224 -0
  45. package/.claude/hooks/run-code-review.py +393 -0
  46. package/.claude/hooks/run-visual-qa.py +338 -0
  47. package/.claude/hooks/session-logger.py +323 -0
  48. package/.claude/hooks/test-orchestrator-reground.py +248 -0
  49. package/.claude/hooks/track-scope-coverage.py +220 -0
  50. package/.claude/hooks/track-token-usage.py +121 -0
  51. package/.claude/hooks/update-adr-decision.py +236 -0
  52. package/.claude/hooks/update-api-showcase.py +161 -0
  53. package/.claude/hooks/update-registry.py +352 -0
  54. package/.claude/hooks/update-testing-checklist.py +195 -0
  55. package/.claude/hooks/update-ui-showcase.py +224 -0
  56. package/.claude/settings.local.json +7 -1
  57. package/.claude/test-auto-answer-bot.py +183 -0
  58. package/.claude/test-completion-detector.py +263 -0
  59. package/.claude/test-orchestrator-state.json +20 -0
  60. package/.claude/test-orchestrator.sh +271 -0
  61. package/.skills/api-create/SKILL.md +88 -3
  62. package/.skills/docs-sync/SKILL.md +260 -0
  63. package/.skills/hustle-build/SKILL.md +459 -0
  64. package/.skills/hustle-build-review/SKILL.md +518 -0
  65. package/CHANGELOG.md +87 -0
  66. package/README.md +86 -9
  67. package/bin/cli.js +1302 -88
  68. package/commands/hustle-api-create.md +22 -0
  69. package/commands/hustle-combine.md +81 -2
  70. package/commands/hustle-ui-create-page.md +84 -2
  71. package/commands/hustle-ui-create.md +82 -2
  72. package/hooks/auto-answer.py +228 -0
  73. package/hooks/check-update.py +132 -0
  74. package/hooks/ntfy-on-question.py +227 -0
  75. package/hooks/orchestrator-completion.py +313 -0
  76. package/hooks/orchestrator-handoff.py +189 -0
  77. package/hooks/orchestrator-session-startup.py +146 -0
  78. package/hooks/periodic-reground.py +230 -67
  79. package/hooks/update-api-showcase.py +13 -1
  80. package/hooks/update-ui-showcase.py +13 -1
  81. package/package.json +7 -3
  82. package/scripts/extract-schema-docs.cjs +322 -0
  83. package/templates/CLAUDE-SECTION.md +89 -64
  84. package/templates/api-showcase/_components/APIModal.tsx +100 -8
  85. package/templates/api-showcase/_components/APIShowcase.tsx +36 -4
  86. package/templates/api-showcase/_components/APITester.tsx +367 -58
  87. package/templates/docs/page.tsx +230 -0
  88. package/templates/hustle-build-defaults.json +84 -0
  89. package/templates/hustle-dev-dashboard/page.tsx +365 -0
  90. package/templates/playwright-report/page.tsx +258 -0
  91. package/templates/settings.json +88 -7
  92. package/templates/test-results/page.tsx +237 -0
  93. package/templates/typedoc.json +19 -0
  94. package/templates/ui-showcase/_components/UIShowcase.tsx +1 -1
  95. package/templates/ui-showcase/page.tsx +1 -1
  96. package/.claude/api-dev-state.json +0 -466
@@ -0,0 +1,258 @@
1
+ "use client";
2
+
3
+ import Link from "next/link";
4
+
5
+ /**
6
+ * Playwright Report Page
7
+ *
8
+ * Shows Playwright E2E test results or instructions to run tests.
9
+ * Links to the HTML report when available.
10
+ *
11
+ * Created with Hustle API Dev Tools (v3.12.12)
12
+ */
13
+ export default function PlaywrightReportPage() {
14
+ // In a real implementation, check if playwright-report/ exists
15
+ const hasReport = false;
16
+
17
+ return (
18
+ <div className="min-h-screen bg-white dark:bg-gray-950">
19
+ {/* Header */}
20
+ <header className="border-b-4 border-black bg-[#BA0C2F] px-6 py-8 dark:border-gray-600">
21
+ <div className="mx-auto max-w-4xl">
22
+ <div className="flex items-center gap-2">
23
+ <Link
24
+ href="/hustle-dev-dashboard"
25
+ className="text-white/80 hover:text-white"
26
+ >
27
+ Dashboard
28
+ </Link>
29
+ <span className="text-white/60">/</span>
30
+ <span className="text-white">Playwright</span>
31
+ </div>
32
+ <h1 className="mt-2 text-3xl font-black text-white">
33
+ PLAYWRIGHT REPORTS
34
+ </h1>
35
+ <p className="mt-2 text-white/80">End-to-end test results</p>
36
+ </div>
37
+ </header>
38
+
39
+ {/* Main Content */}
40
+ <main className="mx-auto max-w-4xl px-6 py-8">
41
+ {hasReport ? <ReportContent /> : <EmptyState />}
42
+ </main>
43
+
44
+ {/* Footer */}
45
+ <footer className="border-t-2 border-black px-6 py-4 dark:border-gray-600">
46
+ <div className="mx-auto max-w-4xl text-center text-sm text-gray-600 dark:text-gray-400">
47
+ Built with{" "}
48
+ <a
49
+ href="https://github.com/hustle-together/api-dev-tools"
50
+ className="font-bold text-[#BA0C2F] hover:underline"
51
+ >
52
+ Hustle API Dev Tools
53
+ </a>
54
+ </div>
55
+ </footer>
56
+ </div>
57
+ );
58
+ }
59
+
60
+ function ReportContent() {
61
+ return (
62
+ <div className="space-y-6">
63
+ <div className="border-2 border-black p-6 dark:border-gray-600">
64
+ <h2 className="mb-4 text-xl font-bold text-black dark:text-white">
65
+ View Report
66
+ </h2>
67
+ <p className="mb-4 text-gray-600 dark:text-gray-400">
68
+ Playwright has generated an HTML report. Click below to view it:
69
+ </p>
70
+ <a
71
+ href="/playwright-report/index.html"
72
+ target="_blank"
73
+ rel="noopener noreferrer"
74
+ className="inline-block rounded bg-[#BA0C2F] px-6 py-3 font-bold text-white transition-colors hover:bg-[#8a0923]"
75
+ >
76
+ Open HTML Report
77
+ </a>
78
+ </div>
79
+ </div>
80
+ );
81
+ }
82
+
83
+ function EmptyState() {
84
+ return (
85
+ <div className="space-y-6">
86
+ {/* Status Card */}
87
+ <div className="border-2 border-black p-6 dark:border-gray-600">
88
+ <div className="flex items-center gap-3">
89
+ <div className="flex h-12 w-12 items-center justify-center rounded-full bg-gray-100 text-2xl dark:bg-gray-800">
90
+ 0
91
+ </div>
92
+ <div>
93
+ <h2 className="text-xl font-bold text-black dark:text-white">
94
+ No Playwright Reports
95
+ </h2>
96
+ <p className="text-gray-600 dark:text-gray-400">
97
+ Run E2E tests to generate a report
98
+ </p>
99
+ </div>
100
+ </div>
101
+ </div>
102
+
103
+ {/* Instructions */}
104
+ <div className="border-2 border-black bg-gray-50 p-6 dark:border-gray-600 dark:bg-gray-900">
105
+ <h3 className="mb-4 font-bold text-black dark:text-white">
106
+ Run E2E Tests
107
+ </h3>
108
+ <div className="space-y-4">
109
+ <Step
110
+ number={1}
111
+ title="Run All E2E Tests"
112
+ command="pnpm test:e2e"
113
+ description="Runs all Playwright tests and generates a report"
114
+ />
115
+ <Step
116
+ number={2}
117
+ title="Run with UI"
118
+ command="pnpm playwright test --ui"
119
+ description="Opens Playwright's interactive test runner"
120
+ />
121
+ <Step
122
+ number={3}
123
+ title="View Report"
124
+ command="pnpm playwright show-report"
125
+ description="Opens the HTML report in your browser"
126
+ />
127
+ </div>
128
+ </div>
129
+
130
+ {/* Available Commands */}
131
+ <div className="border-2 border-black p-6 dark:border-gray-600">
132
+ <h3 className="mb-4 font-bold text-black dark:text-white">
133
+ Playwright Commands
134
+ </h3>
135
+ <div className="space-y-3">
136
+ <CommandItem
137
+ command="pnpm test:e2e"
138
+ description="Run all E2E tests"
139
+ />
140
+ <CommandItem
141
+ command="pnpm playwright test --ui"
142
+ description="Interactive test runner"
143
+ />
144
+ <CommandItem
145
+ command="pnpm playwright test --headed"
146
+ description="Run with visible browser"
147
+ />
148
+ <CommandItem
149
+ command="pnpm playwright show-report"
150
+ description="Open HTML report"
151
+ />
152
+ <CommandItem
153
+ command="pnpm playwright codegen"
154
+ description="Generate tests by recording"
155
+ />
156
+ </div>
157
+ </div>
158
+
159
+ {/* Test Types */}
160
+ <div className="border-2 border-black bg-gray-50 p-6 dark:border-gray-600 dark:bg-gray-900">
161
+ <h3 className="mb-4 font-bold text-black dark:text-white">
162
+ E2E Test Types
163
+ </h3>
164
+ <div className="grid gap-4 sm:grid-cols-2">
165
+ <TestTypeCard
166
+ icon="🖥️"
167
+ title="Page Tests"
168
+ description="Full page navigation and interaction tests"
169
+ pattern="*.e2e.test.ts"
170
+ />
171
+ <TestTypeCard
172
+ icon="📸"
173
+ title="Visual Tests"
174
+ description="Screenshot comparison for UI changes"
175
+ pattern="*.visual.spec.ts"
176
+ />
177
+ <TestTypeCard
178
+ icon="♿"
179
+ title="Accessibility"
180
+ description="WCAG compliance and a11y checks"
181
+ pattern="*.a11y.spec.ts"
182
+ />
183
+ <TestTypeCard
184
+ icon="📱"
185
+ title="Responsive"
186
+ description="Mobile, tablet, and desktop viewports"
187
+ pattern="--project=mobile"
188
+ />
189
+ </div>
190
+ </div>
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
+ }
238
+
239
+ function TestTypeCard({
240
+ icon,
241
+ title,
242
+ description,
243
+ pattern,
244
+ }: {
245
+ icon: string;
246
+ title: string;
247
+ description: string;
248
+ pattern: string;
249
+ }) {
250
+ return (
251
+ <div className="rounded border border-gray-200 bg-white p-4 dark:border-gray-700 dark:bg-gray-800">
252
+ <div className="mb-2 text-2xl">{icon}</div>
253
+ <h4 className="font-medium text-black dark:text-white">{title}</h4>
254
+ <p className="text-sm text-gray-600 dark:text-gray-400">{description}</p>
255
+ <code className="mt-2 block text-xs text-[#BA0C2F]">{pattern}</code>
256
+ </div>
257
+ );
258
+ }
@@ -1,18 +1,60 @@
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
+ "Write(.env*)",
50
+ "Edit(.env*)",
51
+ "Bash(rm -rf *)",
52
+ "Bash(sudo *)",
53
+ "Bash(git push --force *)",
54
+ "Bash(git reset --hard *)",
55
+ "Bash(> /dev/*)",
56
+ "Bash(curl * | bash)",
57
+ "Bash(wget * | bash)"
16
58
  ]
17
59
  },
18
60
  "hooks": {
@@ -26,6 +68,14 @@
26
68
  {
27
69
  "type": "command",
28
70
  "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/detect-interruption.py"
71
+ },
72
+ {
73
+ "type": "command",
74
+ "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/check-update.py"
75
+ },
76
+ {
77
+ "type": "command",
78
+ "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/orchestrator-session-startup.py"
29
79
  }
30
80
  ]
31
81
  }
@@ -140,6 +190,19 @@
140
190
  {
141
191
  "type": "command",
142
192
  "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/enforce-questions-sourced.py"
193
+ },
194
+ {
195
+ "type": "command",
196
+ "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/auto-answer.py"
197
+ }
198
+ ]
199
+ },
200
+ {
201
+ "matcher": "Skill",
202
+ "hooks": [
203
+ {
204
+ "type": "command",
205
+ "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/orchestrator-handoff.py"
143
206
  }
144
207
  ]
145
208
  }
@@ -162,6 +225,15 @@
162
225
  }
163
226
  ]
164
227
  },
228
+ {
229
+ "matcher": "AskUserQuestion",
230
+ "hooks": [
231
+ {
232
+ "type": "command",
233
+ "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/ntfy-on-question.py"
234
+ }
235
+ ]
236
+ },
165
237
  {
166
238
  "matcher": "Bash",
167
239
  "hooks": [
@@ -199,6 +271,15 @@
199
271
  "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/enforce-a11y-audit.py"
200
272
  }
201
273
  ]
274
+ },
275
+ {
276
+ "matcher": "Skill",
277
+ "hooks": [
278
+ {
279
+ "type": "command",
280
+ "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/orchestrator-completion.py"
281
+ }
282
+ ]
202
283
  }
203
284
  ],
204
285
  "Stop": [
@@ -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,7 +1,7 @@
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
7
 
@@ -1,5 +1,5 @@
1
1
  import type { Metadata } from "next";
2
- import { UIShowcase } from "./UIShowcase";
2
+ import { UIShowcase } from "./_components/UIShowcase";
3
3
 
4
4
  export const metadata: Metadata = {
5
5
  title: "UI Showcase",