@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
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Hook: PostToolUse for Write/Edit
|
|
4
|
+
Purpose: Auto-create UI Showcase page when first component/page is created
|
|
5
|
+
|
|
6
|
+
This hook monitors for new component or page registrations. When the first
|
|
7
|
+
UI element is added to registry.json, it creates the UI Showcase page
|
|
8
|
+
at src/app/ui-showcase/ if it doesn't exist.
|
|
9
|
+
|
|
10
|
+
Version: 3.9.0
|
|
11
|
+
|
|
12
|
+
Returns:
|
|
13
|
+
- {"continue": true} - Always continues
|
|
14
|
+
- May include "notify" about showcase creation
|
|
15
|
+
"""
|
|
16
|
+
import json
|
|
17
|
+
import sys
|
|
18
|
+
from pathlib import Path
|
|
19
|
+
import shutil
|
|
20
|
+
|
|
21
|
+
# State and registry files in .claude/ directory
|
|
22
|
+
STATE_FILE = Path(__file__).parent.parent / "api-dev-state.json"
|
|
23
|
+
REGISTRY_FILE = Path(__file__).parent.parent / "registry.json"
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def copy_showcase_templates(cwd):
|
|
27
|
+
"""Copy UI showcase templates to src/app/ui-showcase/."""
|
|
28
|
+
# Source templates (installed by CLI)
|
|
29
|
+
templates_dir = Path(__file__).parent.parent / "templates" / "ui-showcase"
|
|
30
|
+
|
|
31
|
+
# Destination
|
|
32
|
+
showcase_dir = cwd / "src" / "app" / "ui-showcase"
|
|
33
|
+
|
|
34
|
+
# Create directory if needed
|
|
35
|
+
showcase_dir.mkdir(parents=True, exist_ok=True)
|
|
36
|
+
|
|
37
|
+
# Copy template files
|
|
38
|
+
templates_to_copy = [
|
|
39
|
+
("page.tsx", "page.tsx"),
|
|
40
|
+
("UIShowcase.tsx", "_components/UIShowcase.tsx"),
|
|
41
|
+
("PreviewCard.tsx", "_components/PreviewCard.tsx"),
|
|
42
|
+
("PreviewModal.tsx", "_components/PreviewModal.tsx"),
|
|
43
|
+
]
|
|
44
|
+
|
|
45
|
+
created_files = []
|
|
46
|
+
for src_name, dest_name in templates_to_copy:
|
|
47
|
+
src_path = templates_dir / src_name
|
|
48
|
+
dest_path = showcase_dir / dest_name
|
|
49
|
+
|
|
50
|
+
# Create subdirectories if needed
|
|
51
|
+
dest_path.parent.mkdir(parents=True, exist_ok=True)
|
|
52
|
+
|
|
53
|
+
if src_path.exists() and not dest_path.exists():
|
|
54
|
+
shutil.copy2(src_path, dest_path)
|
|
55
|
+
created_files.append(str(dest_path.relative_to(cwd)))
|
|
56
|
+
|
|
57
|
+
return created_files
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def main():
|
|
61
|
+
# Read hook input from stdin
|
|
62
|
+
try:
|
|
63
|
+
input_data = json.load(sys.stdin)
|
|
64
|
+
except json.JSONDecodeError:
|
|
65
|
+
print(json.dumps({"continue": True}))
|
|
66
|
+
sys.exit(0)
|
|
67
|
+
|
|
68
|
+
tool_name = input_data.get("tool_name", "")
|
|
69
|
+
|
|
70
|
+
# Only process Write/Edit operations
|
|
71
|
+
if tool_name not in ["Write", "Edit"]:
|
|
72
|
+
print(json.dumps({"continue": True}))
|
|
73
|
+
sys.exit(0)
|
|
74
|
+
|
|
75
|
+
# Check if state file exists
|
|
76
|
+
if not STATE_FILE.exists():
|
|
77
|
+
print(json.dumps({"continue": True}))
|
|
78
|
+
sys.exit(0)
|
|
79
|
+
|
|
80
|
+
# Load state
|
|
81
|
+
try:
|
|
82
|
+
state = json.loads(STATE_FILE.read_text())
|
|
83
|
+
except json.JSONDecodeError:
|
|
84
|
+
print(json.dumps({"continue": True}))
|
|
85
|
+
sys.exit(0)
|
|
86
|
+
|
|
87
|
+
workflow = state.get("workflow", "")
|
|
88
|
+
|
|
89
|
+
# Only apply for UI workflows
|
|
90
|
+
if workflow not in ["ui-create-component", "ui-create-page"]:
|
|
91
|
+
print(json.dumps({"continue": True}))
|
|
92
|
+
sys.exit(0)
|
|
93
|
+
|
|
94
|
+
# Check if completion phase is complete
|
|
95
|
+
active_element = state.get("active_element", "")
|
|
96
|
+
elements = state.get("elements", {})
|
|
97
|
+
|
|
98
|
+
if active_element and active_element in elements:
|
|
99
|
+
phases = elements[active_element].get("phases", {})
|
|
100
|
+
else:
|
|
101
|
+
phases = state.get("phases", {})
|
|
102
|
+
|
|
103
|
+
completion = phases.get("completion", {})
|
|
104
|
+
if completion.get("status") != "complete":
|
|
105
|
+
print(json.dumps({"continue": True}))
|
|
106
|
+
sys.exit(0)
|
|
107
|
+
|
|
108
|
+
# Check if showcase already exists
|
|
109
|
+
cwd = Path.cwd()
|
|
110
|
+
showcase_page = cwd / "src" / "app" / "ui-showcase" / "page.tsx"
|
|
111
|
+
|
|
112
|
+
if showcase_page.exists():
|
|
113
|
+
print(json.dumps({"continue": True}))
|
|
114
|
+
sys.exit(0)
|
|
115
|
+
|
|
116
|
+
# Check if we have components or pages in registry
|
|
117
|
+
if not REGISTRY_FILE.exists():
|
|
118
|
+
print(json.dumps({"continue": True}))
|
|
119
|
+
sys.exit(0)
|
|
120
|
+
|
|
121
|
+
try:
|
|
122
|
+
registry = json.loads(REGISTRY_FILE.read_text())
|
|
123
|
+
except json.JSONDecodeError:
|
|
124
|
+
print(json.dumps({"continue": True}))
|
|
125
|
+
sys.exit(0)
|
|
126
|
+
|
|
127
|
+
components = registry.get("components", {})
|
|
128
|
+
pages = registry.get("pages", {})
|
|
129
|
+
|
|
130
|
+
# Create showcase if we have at least one component or page
|
|
131
|
+
if components or pages:
|
|
132
|
+
created_files = copy_showcase_templates(cwd)
|
|
133
|
+
|
|
134
|
+
if created_files:
|
|
135
|
+
print(json.dumps({
|
|
136
|
+
"continue": True,
|
|
137
|
+
"notify": f"Created UI Showcase at /ui-showcase ({len(created_files)} files)"
|
|
138
|
+
}))
|
|
139
|
+
else:
|
|
140
|
+
print(json.dumps({"continue": True}))
|
|
141
|
+
else:
|
|
142
|
+
print(json.dumps({"continue": True}))
|
|
143
|
+
|
|
144
|
+
sys.exit(0)
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
if __name__ == "__main__":
|
|
148
|
+
main()
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hustle-together/api-dev-tools",
|
|
3
|
-
"version": "3.
|
|
4
|
-
"description": "Interview-driven, research-first API development workflow with continuous verification loops for Claude Code",
|
|
3
|
+
"version": "3.9.2",
|
|
4
|
+
"description": "Interview-driven, research-first API and UI development workflow with continuous verification loops for Claude Code",
|
|
5
5
|
"main": "bin/cli.js",
|
|
6
6
|
"bin": {
|
|
7
7
|
"api-dev-tools": "./bin/cli.js"
|
|
@@ -23,10 +23,16 @@
|
|
|
23
23
|
"claude",
|
|
24
24
|
"claude-code",
|
|
25
25
|
"api-development",
|
|
26
|
+
"ui-development",
|
|
27
|
+
"components",
|
|
28
|
+
"storybook",
|
|
29
|
+
"playwright",
|
|
26
30
|
"tdd",
|
|
27
31
|
"test-driven-development",
|
|
28
32
|
"interview-driven",
|
|
29
33
|
"api-testing",
|
|
34
|
+
"api-orchestration",
|
|
35
|
+
"combine",
|
|
30
36
|
"documentation",
|
|
31
37
|
"workflow",
|
|
32
38
|
"automation"
|
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
# Hustle Together Brand Guide
|
|
2
|
+
|
|
3
|
+
> This file is used by `/hustle-ui-create` during Phase 3 (Design Research).
|
|
4
|
+
> Update this guide to match your project's branding before creating components.
|
|
5
|
+
|
|
6
|
+
## Core Colors
|
|
7
|
+
|
|
8
|
+
### Hustle Brand Colors
|
|
9
|
+
| Name | Hex | RGB | Usage |
|
|
10
|
+
|------|-----|-----|-------|
|
|
11
|
+
| **Hustle Red** | #BA0C2F | rgb(186, 12, 47) | Primary accent, buttons, links, focus rings |
|
|
12
|
+
| **Hustle Red Hover** | #8A0923 | rgb(138, 9, 35) | Hover states |
|
|
13
|
+
| **Hustle Red Light** | rgba(186, 12, 47, 0.1) | - | Backgrounds, badges |
|
|
14
|
+
|
|
15
|
+
### Light Mode
|
|
16
|
+
| Name | Hex | Usage |
|
|
17
|
+
|------|-----|-------|
|
|
18
|
+
| **Background** | #FFFFFF | Main background |
|
|
19
|
+
| **Background Secondary** | #F8F8F8 | Cards, sections |
|
|
20
|
+
| **Background Tertiary** | #F0F0F0 | Nested elements |
|
|
21
|
+
| **Text** | #1A1A1A | Primary text |
|
|
22
|
+
| **Text Muted** | #666666 | Secondary text |
|
|
23
|
+
| **Border** | #E5E5E5 | Light borders |
|
|
24
|
+
| **Border Strong** | #000000 | Boxy card borders |
|
|
25
|
+
|
|
26
|
+
### Dark Mode
|
|
27
|
+
| Name | Hex | Usage |
|
|
28
|
+
|------|-----|-------|
|
|
29
|
+
| **Background** | #050505 | Main background |
|
|
30
|
+
| **Background Secondary** | #111111 | Cards, sections |
|
|
31
|
+
| **Background Tertiary** | #1A1A1A | Nested elements |
|
|
32
|
+
| **Text** | #F0F0F0 | Primary text |
|
|
33
|
+
| **Text Muted** | #888888 | Secondary text |
|
|
34
|
+
| **Border** | #333333 | Dark borders |
|
|
35
|
+
|
|
36
|
+
### Status Colors
|
|
37
|
+
| Name | Hex | Usage |
|
|
38
|
+
|------|-----|-------|
|
|
39
|
+
| **Success** | #22C55E | Completed, passed, positive |
|
|
40
|
+
| **Warning** | #EAB308 | Caution, pending |
|
|
41
|
+
| **Error** | #EF4444 | Failed, errors, destructive |
|
|
42
|
+
| **Info** | #3B82F6 | Informational |
|
|
43
|
+
|
|
44
|
+
## Typography
|
|
45
|
+
|
|
46
|
+
### Font Stack
|
|
47
|
+
```css
|
|
48
|
+
/* Main font */
|
|
49
|
+
--font-main: -apple-system, BlinkMacSystemFont, 'SF Pro Text', 'Segoe UI', Roboto, sans-serif;
|
|
50
|
+
|
|
51
|
+
/* Monospace */
|
|
52
|
+
--font-mono: 'SF Mono', Monaco, Inconsolata, 'Fira Code', monospace;
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Font Sizes
|
|
56
|
+
- **xs:** 0.75rem (12px)
|
|
57
|
+
- **sm:** 0.875rem (14px)
|
|
58
|
+
- **base:** 1rem (16px)
|
|
59
|
+
- **lg:** 1.125rem (18px)
|
|
60
|
+
- **xl:** 1.25rem (20px)
|
|
61
|
+
- **2xl:** 1.5rem (24px)
|
|
62
|
+
- **3xl:** 1.875rem (30px)
|
|
63
|
+
- **4xl:** 2.25rem (36px)
|
|
64
|
+
- **5xl:** 3rem (48px)
|
|
65
|
+
- **6xl:** 4rem (64px)
|
|
66
|
+
|
|
67
|
+
### Font Weights
|
|
68
|
+
- **Normal:** 400
|
|
69
|
+
- **Medium:** 500
|
|
70
|
+
- **Semibold:** 600
|
|
71
|
+
- **Bold:** 700
|
|
72
|
+
- **Extrabold:** 800
|
|
73
|
+
|
|
74
|
+
### Line Heights
|
|
75
|
+
- **Tight:** 1.1 (headings)
|
|
76
|
+
- **Normal:** 1.5 (body)
|
|
77
|
+
- **Relaxed:** 1.6 (paragraphs)
|
|
78
|
+
|
|
79
|
+
## Spacing
|
|
80
|
+
|
|
81
|
+
### Base Unit
|
|
82
|
+
- **Base:** 4px (0.25rem)
|
|
83
|
+
|
|
84
|
+
### Scale
|
|
85
|
+
| Token | Value | Pixels |
|
|
86
|
+
|-------|-------|--------|
|
|
87
|
+
| 0 | 0 | 0 |
|
|
88
|
+
| 1 | 0.25rem | 4px |
|
|
89
|
+
| 2 | 0.5rem | 8px |
|
|
90
|
+
| 3 | 0.75rem | 12px |
|
|
91
|
+
| 4 | 1rem | 16px |
|
|
92
|
+
| 5 | 1.25rem | 20px |
|
|
93
|
+
| 6 | 1.5rem | 24px |
|
|
94
|
+
| 8 | 2rem | 32px |
|
|
95
|
+
| 10 | 2.5rem | 40px |
|
|
96
|
+
| 12 | 3rem | 48px |
|
|
97
|
+
| 16 | 4rem | 64px |
|
|
98
|
+
|
|
99
|
+
### Common Usage
|
|
100
|
+
- **Component Padding:** 16px (1rem)
|
|
101
|
+
- **Card Padding:** 24px (1.5rem)
|
|
102
|
+
- **Section Margin:** 32px (2rem)
|
|
103
|
+
- **Page Padding:** 60px (desktop), 30px (mobile)
|
|
104
|
+
|
|
105
|
+
## Component Styling
|
|
106
|
+
|
|
107
|
+
### Design Philosophy
|
|
108
|
+
**90s Boxy Style** - Clean, minimal, sharp edges with solid borders.
|
|
109
|
+
|
|
110
|
+
### Border Radius
|
|
111
|
+
- **Default:** 0 (boxy, no rounding)
|
|
112
|
+
- **Soft:** 4px (subtle rounding for inputs only)
|
|
113
|
+
- **Full:** 9999px (pills, avatars)
|
|
114
|
+
|
|
115
|
+
### Border Width
|
|
116
|
+
- **Cards:** 2px solid
|
|
117
|
+
- **Inputs:** 2px solid (focus: Hustle Red)
|
|
118
|
+
- **Subtle:** 1px solid
|
|
119
|
+
|
|
120
|
+
### Shadows
|
|
121
|
+
```css
|
|
122
|
+
/* Float effect for cards */
|
|
123
|
+
--shadow-float: 0 10px 30px -10px rgba(0, 0, 0, 0.1);
|
|
124
|
+
|
|
125
|
+
/* Hover shadow */
|
|
126
|
+
--shadow-hover: 4px 4px 0px 0px rgba(186, 12, 47, 0.2);
|
|
127
|
+
|
|
128
|
+
/* No shadow for flat design */
|
|
129
|
+
--shadow-none: none;
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Focus Ring
|
|
133
|
+
```css
|
|
134
|
+
/* Hustle Red focus ring */
|
|
135
|
+
outline: 2px solid #BA0C2F;
|
|
136
|
+
outline-offset: 2px;
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### Transitions
|
|
140
|
+
```css
|
|
141
|
+
/* Standard transition */
|
|
142
|
+
transition: all 0.2s ease;
|
|
143
|
+
transition-property: color, background-color, border-color, opacity, transform, box-shadow;
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## Buttons
|
|
147
|
+
|
|
148
|
+
### Primary Button (Hustle Red)
|
|
149
|
+
```css
|
|
150
|
+
background: #BA0C2F;
|
|
151
|
+
color: #ffffff;
|
|
152
|
+
padding: 12px 24px;
|
|
153
|
+
border: 2px solid #BA0C2F;
|
|
154
|
+
border-radius: 0;
|
|
155
|
+
font-weight: 700;
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### Secondary Button
|
|
159
|
+
```css
|
|
160
|
+
background: #ffffff;
|
|
161
|
+
color: #000000;
|
|
162
|
+
padding: 12px 24px;
|
|
163
|
+
border: 2px solid #000000;
|
|
164
|
+
border-radius: 0;
|
|
165
|
+
font-weight: 700;
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### Ghost Button
|
|
169
|
+
```css
|
|
170
|
+
background: transparent;
|
|
171
|
+
color: #000000;
|
|
172
|
+
padding: 12px 24px;
|
|
173
|
+
border: 2px solid #000000;
|
|
174
|
+
border-radius: 0;
|
|
175
|
+
font-weight: 700;
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### Button Hover States
|
|
179
|
+
- **Primary:** background: #8A0923
|
|
180
|
+
- **Secondary:** border-color: #BA0C2F
|
|
181
|
+
- **Ghost:** border-color: #BA0C2F
|
|
182
|
+
|
|
183
|
+
### Button Sizes
|
|
184
|
+
| Size | Padding | Font Size |
|
|
185
|
+
|------|---------|-----------|
|
|
186
|
+
| Small | 8px 16px | 12px |
|
|
187
|
+
| Medium | 12px 24px | 14px |
|
|
188
|
+
| Large | 16px 32px | 16px |
|
|
189
|
+
|
|
190
|
+
## Form Elements
|
|
191
|
+
|
|
192
|
+
### Input Fields
|
|
193
|
+
```css
|
|
194
|
+
background: #ffffff;
|
|
195
|
+
border: 2px solid #000000;
|
|
196
|
+
border-radius: 0;
|
|
197
|
+
padding: 12px 16px;
|
|
198
|
+
font-size: 14px;
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### Input States
|
|
202
|
+
- **Focus:** `border-color: #BA0C2F;`
|
|
203
|
+
- **Error:** `border-color: #EF4444;`
|
|
204
|
+
- **Disabled:** `background: #F5F5F5; opacity: 0.5;`
|
|
205
|
+
|
|
206
|
+
### Labels
|
|
207
|
+
```css
|
|
208
|
+
display: block;
|
|
209
|
+
margin-bottom: 8px;
|
|
210
|
+
font-weight: 700;
|
|
211
|
+
font-size: 14px;
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
## Cards
|
|
215
|
+
|
|
216
|
+
### Default Card
|
|
217
|
+
```css
|
|
218
|
+
background: #ffffff;
|
|
219
|
+
border: 2px solid #000000;
|
|
220
|
+
border-radius: 0;
|
|
221
|
+
padding: 24px;
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### Card Hover
|
|
225
|
+
```css
|
|
226
|
+
border-color: #BA0C2F;
|
|
227
|
+
box-shadow: 4px 4px 0px 0px rgba(186, 12, 47, 0.2);
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
### Card (Dark Mode)
|
|
231
|
+
```css
|
|
232
|
+
background: #111111;
|
|
233
|
+
border: 2px solid #333333;
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
## Hero Headers
|
|
237
|
+
|
|
238
|
+
### Animated Grid Hero
|
|
239
|
+
- Height: 450px
|
|
240
|
+
- Canvas-based 3D perspective grid animation
|
|
241
|
+
- Hustle Red accent cells (#BA0C2F)
|
|
242
|
+
- Fog/fade gradient overlay
|
|
243
|
+
- Left-aligned content
|
|
244
|
+
- Padding: 60px (desktop), 30px (mobile)
|
|
245
|
+
|
|
246
|
+
## Dark Mode Implementation
|
|
247
|
+
|
|
248
|
+
### CSS Custom Properties
|
|
249
|
+
```css
|
|
250
|
+
[data-theme="dark"] {
|
|
251
|
+
--bg: #050505;
|
|
252
|
+
--text: #f0f0f0;
|
|
253
|
+
--text-muted: #888888;
|
|
254
|
+
--border: #333333;
|
|
255
|
+
--surface-glass: rgba(20, 20, 20, 0.8);
|
|
256
|
+
}
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
### Tailwind Classes
|
|
260
|
+
Use `dark:` prefix for all dark mode styles:
|
|
261
|
+
```html
|
|
262
|
+
<div class="bg-white dark:bg-gray-900 text-black dark:text-white">
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
## Voice & Tone
|
|
266
|
+
|
|
267
|
+
### Writing Style
|
|
268
|
+
- **Professional** but approachable
|
|
269
|
+
- **Clear** and concise
|
|
270
|
+
- **Technical precision** - no fluff
|
|
271
|
+
- **No emojis** in code or documentation (unless requested)
|
|
272
|
+
|
|
273
|
+
### UI Copy Guidelines
|
|
274
|
+
- Use active voice
|
|
275
|
+
- Keep button labels to 2-3 words
|
|
276
|
+
- Error messages should explain how to fix the issue
|
|
277
|
+
- Success messages should confirm the action taken
|
|
278
|
+
|
|
279
|
+
## Accessibility Requirements
|
|
280
|
+
|
|
281
|
+
### Color Contrast
|
|
282
|
+
- **Normal Text:** Minimum 4.5:1 ratio (WCAG AA)
|
|
283
|
+
- **Large Text:** Minimum 3:1 ratio
|
|
284
|
+
- **Interactive Elements:** Minimum 3:1 ratio
|
|
285
|
+
|
|
286
|
+
### Focus Indicators
|
|
287
|
+
- All interactive elements must have visible focus states
|
|
288
|
+
- Hustle Red (#BA0C2F) focus ring
|
|
289
|
+
- Focus should not be removed or hidden
|
|
290
|
+
|
|
291
|
+
### Touch Targets
|
|
292
|
+
- Minimum size: 44px x 44px
|
|
293
|
+
- Minimum spacing: 8px between targets
|
|
294
|
+
|
|
295
|
+
---
|
|
296
|
+
|
|
297
|
+
**Last Updated:** 2025-12-12
|
|
298
|
+
**Brand Version:** 3.9.1
|
|
299
|
+
**Design System:** Hustle Together
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
## API Development Workflow (v3.0)
|
|
1
|
+
## Hustle API Development Workflow (v3.7.0)
|
|
2
2
|
|
|
3
3
|
This project uses **@hustle-together/api-dev-tools** for interview-driven, research-first API development.
|
|
4
4
|
|
|
@@ -6,12 +6,14 @@ This project uses **@hustle-together/api-dev-tools** for interview-driven, resea
|
|
|
6
6
|
|
|
7
7
|
| Command | Purpose |
|
|
8
8
|
|---------|---------|
|
|
9
|
-
| `/api-create [endpoint]` | Complete 13-phase workflow |
|
|
10
|
-
| `/api-interview [endpoint]` | Questions FROM research findings |
|
|
11
|
-
| `/api-research [library]` | Adaptive propose-approve research |
|
|
12
|
-
| `/api-verify [endpoint]` | Re-research and verify implementation |
|
|
13
|
-
| `/api-env [endpoint]` | Check API keys |
|
|
14
|
-
| `/api-status [endpoint]` | Track progress |
|
|
9
|
+
| `/hustle-api-create [endpoint]` | Complete 13-phase workflow |
|
|
10
|
+
| `/hustle-api-interview [endpoint]` | Questions FROM research findings |
|
|
11
|
+
| `/hustle-api-research [library]` | Adaptive propose-approve research |
|
|
12
|
+
| `/hustle-api-verify [endpoint]` | Re-research and verify implementation |
|
|
13
|
+
| `/hustle-api-env [endpoint]` | Check API keys |
|
|
14
|
+
| `/hustle-api-status [endpoint]` | Track progress |
|
|
15
|
+
| `/hustle-api-continue [endpoint]` | Resume interrupted workflow |
|
|
16
|
+
| `/hustle-api-sessions` | Browse saved session logs |
|
|
15
17
|
|
|
16
18
|
### 13-Phase Flow
|
|
17
19
|
|
|
@@ -42,43 +44,73 @@ Phase 13: COMPLETION - Final verification, commit
|
|
|
42
44
|
### State Tracking
|
|
43
45
|
|
|
44
46
|
All progress is tracked in `.claude/api-dev-state.json`:
|
|
45
|
-
- Current phase and status for each
|
|
47
|
+
- Current phase and status for each endpoint
|
|
46
48
|
- Interview decisions (injected during implementation)
|
|
47
49
|
- Research sources with freshness tracking
|
|
48
50
|
- Turn count for re-grounding
|
|
51
|
+
- Multi-API support with active endpoint pointer
|
|
49
52
|
|
|
50
53
|
### Research Cache
|
|
51
54
|
|
|
52
55
|
Research is cached in `.claude/research/` with 7-day freshness:
|
|
53
56
|
- `index.json` - Freshness tracking
|
|
54
57
|
- `[api-name]/CURRENT.md` - Latest research
|
|
58
|
+
- `[api-name]/sources.json` - Research sources
|
|
59
|
+
- `[api-name]/interview.json` - Interview decisions
|
|
60
|
+
- `[api-name]/schema.json` - Schema snapshot
|
|
55
61
|
- Stale research (>7 days) triggers re-research prompt
|
|
56
62
|
|
|
57
|
-
### Hooks (Automatic Enforcement)
|
|
58
|
-
|
|
59
|
-
| Hook |
|
|
60
|
-
|
|
61
|
-
| `session-startup.py` |
|
|
62
|
-
| `
|
|
63
|
-
| `enforce-research.py` |
|
|
64
|
-
| `enforce-
|
|
65
|
-
| `
|
|
66
|
-
| `
|
|
67
|
-
| `
|
|
63
|
+
### Hooks (25 Total - Automatic Enforcement)
|
|
64
|
+
|
|
65
|
+
| Hook | Event | Action |
|
|
66
|
+
|------|-------|--------|
|
|
67
|
+
| `session-startup.py` | SessionStart | Inject state context |
|
|
68
|
+
| `detect-interruption.py` | SessionStart | Detect interrupted workflows |
|
|
69
|
+
| `enforce-external-research.py` | UserPromptSubmit | Require research first |
|
|
70
|
+
| `enforce-disambiguation.py` | PreToolUse | Phase 1 enforcement |
|
|
71
|
+
| `enforce-scope.py` | PreToolUse | Phase 2 enforcement |
|
|
72
|
+
| `enforce-research.py` | PreToolUse | Phase 3 enforcement |
|
|
73
|
+
| `enforce-interview.py` | PreToolUse | Phase 4 - inject decisions |
|
|
74
|
+
| `enforce-deep-research.py` | PreToolUse | Phase 5 enforcement |
|
|
75
|
+
| `enforce-schema.py` | PreToolUse | Phase 6 enforcement |
|
|
76
|
+
| `enforce-environment.py` | PreToolUse | Phase 7 enforcement |
|
|
77
|
+
| `enforce-tdd-red.py` | PreToolUse | Phase 8 enforcement |
|
|
78
|
+
| `verify-implementation.py` | PreToolUse | Phase 9 helper |
|
|
79
|
+
| `enforce-verify.py` | PreToolUse | Phase 10 enforcement |
|
|
80
|
+
| `enforce-refactor.py` | PreToolUse | Phase 11 enforcement |
|
|
81
|
+
| `enforce-documentation.py` | PreToolUse | Phase 12 enforcement |
|
|
82
|
+
| `enforce-questions-sourced.py` | PreToolUse | Validate questions from research |
|
|
83
|
+
| `enforce-schema-from-interview.py` | PreToolUse | Validate schema from interview |
|
|
84
|
+
| `track-tool-use.py` | PostToolUse | Log research, count turns |
|
|
85
|
+
| `periodic-reground.py` | PostToolUse | Re-inject context every 7 turns |
|
|
86
|
+
| `track-scope-coverage.py` | PostToolUse | Track implemented vs deferred |
|
|
87
|
+
| `verify-after-green.py` | PostToolUse | Trigger Phase 10 after tests pass |
|
|
88
|
+
| `cache-research.py` | PostToolUse | Create research cache files |
|
|
89
|
+
| `generate-manifest-entry.py` | PostToolUse | Auto-generate API documentation |
|
|
90
|
+
| `api-workflow-check.py` | Stop | Block if incomplete, generate output |
|
|
91
|
+
| `session-logger.py` | Stop | Save session to api-sessions |
|
|
92
|
+
|
|
93
|
+
### Auto-Generated Documentation
|
|
94
|
+
|
|
95
|
+
When Phase 12 completes, `generate-manifest-entry.py` automatically creates:
|
|
96
|
+
- **Comprehensive curl examples** (minimal, full, auth, enum variations, boundary values)
|
|
97
|
+
- **Complete test cases** (success, validation, required fields, types, boundaries, arrays)
|
|
98
|
+
- **Parameter documentation** with all possible values
|
|
99
|
+
- **Ready-to-use entries** for `api-tests-manifest.json`
|
|
68
100
|
|
|
69
101
|
### Usage
|
|
70
102
|
|
|
71
103
|
```bash
|
|
72
104
|
# Full automated workflow
|
|
73
|
-
/api-create my-endpoint
|
|
105
|
+
/hustle-api-create my-endpoint
|
|
74
106
|
|
|
75
107
|
# Manual step-by-step
|
|
76
|
-
/api-research [library]
|
|
77
|
-
/api-interview [endpoint]
|
|
78
|
-
/api-env [endpoint]
|
|
108
|
+
/hustle-api-research [library]
|
|
109
|
+
/hustle-api-interview [endpoint]
|
|
110
|
+
/hustle-api-env [endpoint]
|
|
79
111
|
/red
|
|
80
112
|
/green
|
|
81
|
-
/api-verify [endpoint]
|
|
113
|
+
/hustle-api-verify [endpoint]
|
|
82
114
|
/refactor
|
|
83
115
|
/commit
|
|
84
116
|
```
|