get-shit-done-cc 1.9.11 → 1.10.0-experimental.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -9
- package/agents/design-specialist.md +222 -0
- package/agents/gsd-executor.md +37 -375
- package/agents/gsd-planner.md +15 -108
- package/bin/install.js +92 -5
- package/commands/gsd/autopilot.md +518 -0
- package/commands/gsd/checkpoints.md +229 -0
- package/commands/gsd/design-system.md +70 -0
- package/commands/gsd/discuss-design.md +77 -0
- package/commands/gsd/extend.md +80 -0
- package/commands/gsd/help.md +46 -17
- package/commands/gsd/new-project.md +94 -8
- package/commands/gsd/plan-phase.md +35 -5
- package/get-shit-done/references/ccr-integration.md +468 -0
- package/get-shit-done/references/checkpoint-execution.md +369 -0
- package/get-shit-done/references/checkpoint-types.md +728 -0
- package/get-shit-done/references/deviation-rules.md +215 -0
- package/get-shit-done/references/framework-patterns.md +543 -0
- package/get-shit-done/references/ui-principles.md +258 -0
- package/get-shit-done/references/verification-patterns.md +1 -1
- package/get-shit-done/skills/gsd-extend/SKILL.md +154 -0
- package/get-shit-done/skills/gsd-extend/references/agent-structure.md +305 -0
- package/get-shit-done/skills/gsd-extend/references/extension-anatomy.md +123 -0
- package/get-shit-done/skills/gsd-extend/references/reference-structure.md +408 -0
- package/get-shit-done/skills/gsd-extend/references/template-structure.md +370 -0
- package/get-shit-done/skills/gsd-extend/references/validation-rules.md +140 -0
- package/get-shit-done/skills/gsd-extend/references/workflow-structure.md +253 -0
- package/get-shit-done/skills/gsd-extend/templates/agent-template.md +234 -0
- package/get-shit-done/skills/gsd-extend/templates/reference-template.md +239 -0
- package/get-shit-done/skills/gsd-extend/templates/workflow-template.md +169 -0
- package/get-shit-done/skills/gsd-extend/workflows/create-approach.md +332 -0
- package/get-shit-done/skills/gsd-extend/workflows/list-extensions.md +133 -0
- package/get-shit-done/skills/gsd-extend/workflows/remove-extension.md +93 -0
- package/get-shit-done/skills/gsd-extend/workflows/validate-extension.md +184 -0
- package/get-shit-done/templates/autopilot-script-simple.sh +181 -0
- package/get-shit-done/templates/autopilot-script.sh +1142 -0
- package/get-shit-done/templates/autopilot-script.sh.backup +1142 -0
- package/get-shit-done/templates/design-system.md +238 -0
- package/get-shit-done/templates/phase-design.md +205 -0
- package/get-shit-done/templates/phase-models-template.json +71 -0
- package/get-shit-done/templates/phase-prompt.md +4 -4
- package/get-shit-done/templates/state.md +37 -0
- package/get-shit-done/tui/App.tsx +169 -0
- package/get-shit-done/tui/README.md +107 -0
- package/get-shit-done/tui/build.js +37 -0
- package/get-shit-done/tui/components/ActivityFeed.tsx +126 -0
- package/get-shit-done/tui/components/PhaseCard.tsx +86 -0
- package/get-shit-done/tui/components/StatsBar.tsx +147 -0
- package/get-shit-done/tui/dist/index.js +387 -0
- package/get-shit-done/tui/index.tsx +12 -0
- package/get-shit-done/tui/package-lock.json +1074 -0
- package/get-shit-done/tui/package.json +22 -0
- package/get-shit-done/tui/utils/pipeReader.ts +129 -0
- package/get-shit-done/workflows/design-system.md +245 -0
- package/get-shit-done/workflows/discuss-design.md +330 -0
- package/get-shit-done/workflows/execute-phase.md +44 -1
- package/get-shit-done/workflows/execute-plan-auth.md +122 -0
- package/get-shit-done/workflows/execute-plan-checkpoints.md +541 -0
- package/get-shit-done/workflows/execute-plan.md +34 -856
- package/package.json +8 -3
- package/commands/gsd/whats-new.md +0 -124
|
@@ -0,0 +1,543 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: framework-patterns
|
|
3
|
+
description: Framework-specific UI patterns for React, SwiftUI, HTML/CSS, and Python frontends
|
|
4
|
+
load_when:
|
|
5
|
+
- design
|
|
6
|
+
- mockup
|
|
7
|
+
- component
|
|
8
|
+
- ui
|
|
9
|
+
auto_load_for: []
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
<framework_patterns>
|
|
13
|
+
|
|
14
|
+
## Overview
|
|
15
|
+
|
|
16
|
+
When creating mockups, match the project's framework. This reference covers patterns for major UI frameworks.
|
|
17
|
+
|
|
18
|
+
## Framework Detection
|
|
19
|
+
|
|
20
|
+
Detect project framework by checking:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
# React/Next.js
|
|
24
|
+
ls package.json && grep -q '"react"' package.json && echo "react"
|
|
25
|
+
|
|
26
|
+
# SwiftUI
|
|
27
|
+
ls *.xcodeproj 2>/dev/null || ls Package.swift 2>/dev/null && echo "swift"
|
|
28
|
+
|
|
29
|
+
# Python web (Flask/Django/FastAPI with templates)
|
|
30
|
+
ls requirements.txt 2>/dev/null && grep -qE 'flask|django|fastapi' requirements.txt && echo "python"
|
|
31
|
+
|
|
32
|
+
# Pure HTML/CSS
|
|
33
|
+
ls index.html 2>/dev/null && echo "html"
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## React/Next.js Patterns
|
|
37
|
+
|
|
38
|
+
### Component Structure
|
|
39
|
+
|
|
40
|
+
```tsx
|
|
41
|
+
interface ComponentNameProps {
|
|
42
|
+
required: string;
|
|
43
|
+
optional?: boolean;
|
|
44
|
+
children?: React.ReactNode;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function ComponentName({
|
|
48
|
+
required,
|
|
49
|
+
optional = false,
|
|
50
|
+
children
|
|
51
|
+
}: ComponentNameProps) {
|
|
52
|
+
return (
|
|
53
|
+
<div className="component-name">
|
|
54
|
+
{children}
|
|
55
|
+
</div>
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Styling Approach
|
|
61
|
+
|
|
62
|
+
**Tailwind CSS (preferred for mockups):**
|
|
63
|
+
```tsx
|
|
64
|
+
<button className="px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors">
|
|
65
|
+
Click me
|
|
66
|
+
</button>
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
**CSS Modules:**
|
|
70
|
+
```tsx
|
|
71
|
+
import styles from './Button.module.css';
|
|
72
|
+
|
|
73
|
+
<button className={styles.primary}>Click me</button>
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Component Categories
|
|
77
|
+
|
|
78
|
+
**Layout components:**
|
|
79
|
+
```tsx
|
|
80
|
+
// Container with max-width
|
|
81
|
+
export function Container({ children }: { children: React.ReactNode }) {
|
|
82
|
+
return (
|
|
83
|
+
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
|
|
84
|
+
{children}
|
|
85
|
+
</div>
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Stack (vertical)
|
|
90
|
+
export function Stack({ gap = 4, children }: { gap?: number; children: React.ReactNode }) {
|
|
91
|
+
return <div className={`flex flex-col gap-${gap}`}>{children}</div>;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Row (horizontal)
|
|
95
|
+
export function Row({ gap = 4, children }: { gap?: number; children: React.ReactNode }) {
|
|
96
|
+
return <div className={`flex flex-row gap-${gap}`}>{children}</div>;
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
**Interactive components:**
|
|
101
|
+
```tsx
|
|
102
|
+
// Button with variants
|
|
103
|
+
interface ButtonProps {
|
|
104
|
+
variant?: 'primary' | 'secondary' | 'ghost';
|
|
105
|
+
size?: 'sm' | 'md' | 'lg';
|
|
106
|
+
children: React.ReactNode;
|
|
107
|
+
onClick?: () => void;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export function Button({ variant = 'primary', size = 'md', children, onClick }: ButtonProps) {
|
|
111
|
+
const variants = {
|
|
112
|
+
primary: 'bg-blue-600 text-white hover:bg-blue-700',
|
|
113
|
+
secondary: 'bg-gray-100 text-gray-900 hover:bg-gray-200',
|
|
114
|
+
ghost: 'bg-transparent hover:bg-gray-100',
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
const sizes = {
|
|
118
|
+
sm: 'px-3 py-1.5 text-sm',
|
|
119
|
+
md: 'px-4 py-2 text-base',
|
|
120
|
+
lg: 'px-6 py-3 text-lg',
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
return (
|
|
124
|
+
<button
|
|
125
|
+
className={`rounded-lg font-medium transition-colors ${variants[variant]} ${sizes[size]}`}
|
|
126
|
+
onClick={onClick}
|
|
127
|
+
>
|
|
128
|
+
{children}
|
|
129
|
+
</button>
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### Mockup File Structure
|
|
135
|
+
|
|
136
|
+
```
|
|
137
|
+
.planning/phases/XX-name/mockups/
|
|
138
|
+
├── index.tsx # Main preview entry
|
|
139
|
+
├── components/
|
|
140
|
+
│ ├── Button.tsx
|
|
141
|
+
│ ├── Card.tsx
|
|
142
|
+
│ └── ...
|
|
143
|
+
└── preview.tsx # Standalone preview component
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Preview Entry Point
|
|
147
|
+
|
|
148
|
+
```tsx
|
|
149
|
+
// .planning/phases/XX-name/mockups/preview.tsx
|
|
150
|
+
'use client';
|
|
151
|
+
|
|
152
|
+
import { Button } from './components/Button';
|
|
153
|
+
import { Card } from './components/Card';
|
|
154
|
+
|
|
155
|
+
export function DesignPreview() {
|
|
156
|
+
return (
|
|
157
|
+
<div className="min-h-screen bg-gray-50 p-8">
|
|
158
|
+
<h1 className="text-2xl font-bold mb-8">Phase XX Design Preview</h1>
|
|
159
|
+
|
|
160
|
+
<section className="mb-12">
|
|
161
|
+
<h2 className="text-lg font-semibold mb-4">Buttons</h2>
|
|
162
|
+
<div className="flex gap-4">
|
|
163
|
+
<Button variant="primary">Primary</Button>
|
|
164
|
+
<Button variant="secondary">Secondary</Button>
|
|
165
|
+
<Button variant="ghost">Ghost</Button>
|
|
166
|
+
</div>
|
|
167
|
+
</section>
|
|
168
|
+
|
|
169
|
+
<section className="mb-12">
|
|
170
|
+
<h2 className="text-lg font-semibold mb-4">Cards</h2>
|
|
171
|
+
<Card title="Example Card">
|
|
172
|
+
Card content here
|
|
173
|
+
</Card>
|
|
174
|
+
</section>
|
|
175
|
+
</div>
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
## SwiftUI Patterns
|
|
181
|
+
|
|
182
|
+
### View Structure
|
|
183
|
+
|
|
184
|
+
```swift
|
|
185
|
+
struct ComponentName: View {
|
|
186
|
+
let title: String
|
|
187
|
+
var subtitle: String? = nil
|
|
188
|
+
|
|
189
|
+
var body: some View {
|
|
190
|
+
VStack(alignment: .leading, spacing: 8) {
|
|
191
|
+
Text(title)
|
|
192
|
+
.font(.headline)
|
|
193
|
+
|
|
194
|
+
if let subtitle {
|
|
195
|
+
Text(subtitle)
|
|
196
|
+
.font(.subheadline)
|
|
197
|
+
.foregroundColor(.secondary)
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
.padding()
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
### Common Components
|
|
206
|
+
|
|
207
|
+
**Button styles:**
|
|
208
|
+
```swift
|
|
209
|
+
struct PrimaryButton: View {
|
|
210
|
+
let title: String
|
|
211
|
+
let action: () -> Void
|
|
212
|
+
|
|
213
|
+
var body: some View {
|
|
214
|
+
Button(action: action) {
|
|
215
|
+
Text(title)
|
|
216
|
+
.font(.headline)
|
|
217
|
+
.foregroundColor(.white)
|
|
218
|
+
.frame(maxWidth: .infinity)
|
|
219
|
+
.padding()
|
|
220
|
+
.background(Color.accentColor)
|
|
221
|
+
.cornerRadius(12)
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
struct SecondaryButton: View {
|
|
227
|
+
let title: String
|
|
228
|
+
let action: () -> Void
|
|
229
|
+
|
|
230
|
+
var body: some View {
|
|
231
|
+
Button(action: action) {
|
|
232
|
+
Text(title)
|
|
233
|
+
.font(.headline)
|
|
234
|
+
.foregroundColor(.accentColor)
|
|
235
|
+
.frame(maxWidth: .infinity)
|
|
236
|
+
.padding()
|
|
237
|
+
.background(Color.accentColor.opacity(0.1))
|
|
238
|
+
.cornerRadius(12)
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
**Card:**
|
|
245
|
+
```swift
|
|
246
|
+
struct Card<Content: View>: View {
|
|
247
|
+
let content: Content
|
|
248
|
+
|
|
249
|
+
init(@ViewBuilder content: () -> Content) {
|
|
250
|
+
self.content = content()
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
var body: some View {
|
|
254
|
+
content
|
|
255
|
+
.padding()
|
|
256
|
+
.background(Color(.systemBackground))
|
|
257
|
+
.cornerRadius(16)
|
|
258
|
+
.shadow(color: .black.opacity(0.05), radius: 8, y: 4)
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### Mockup File Structure
|
|
264
|
+
|
|
265
|
+
```
|
|
266
|
+
.planning/phases/XX-name/mockups/
|
|
267
|
+
├── DesignPreview.swift # Main preview
|
|
268
|
+
├── Components/
|
|
269
|
+
│ ├── Buttons.swift
|
|
270
|
+
│ ├── Cards.swift
|
|
271
|
+
│ └── ...
|
|
272
|
+
└── PreviewProvider.swift # Xcode preview setup
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
### Preview Setup
|
|
276
|
+
|
|
277
|
+
```swift
|
|
278
|
+
// DesignPreview.swift
|
|
279
|
+
import SwiftUI
|
|
280
|
+
|
|
281
|
+
struct DesignPreview: View {
|
|
282
|
+
var body: some View {
|
|
283
|
+
NavigationStack {
|
|
284
|
+
ScrollView {
|
|
285
|
+
VStack(alignment: .leading, spacing: 32) {
|
|
286
|
+
buttonsSection
|
|
287
|
+
cardsSection
|
|
288
|
+
formsSection
|
|
289
|
+
}
|
|
290
|
+
.padding()
|
|
291
|
+
}
|
|
292
|
+
.navigationTitle("Phase XX Design")
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
private var buttonsSection: some View {
|
|
297
|
+
VStack(alignment: .leading, spacing: 16) {
|
|
298
|
+
Text("Buttons")
|
|
299
|
+
.font(.title2.bold())
|
|
300
|
+
|
|
301
|
+
PrimaryButton(title: "Primary Action") {}
|
|
302
|
+
SecondaryButton(title: "Secondary") {}
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// ... more sections
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
#Preview {
|
|
310
|
+
DesignPreview()
|
|
311
|
+
}
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
## HTML/CSS Patterns
|
|
315
|
+
|
|
316
|
+
### File Structure
|
|
317
|
+
|
|
318
|
+
```
|
|
319
|
+
.planning/phases/XX-name/mockups/
|
|
320
|
+
├── index.html # Main preview
|
|
321
|
+
├── styles.css # All styles
|
|
322
|
+
└── components/ # Optional component HTML snippets
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
### Base HTML Template
|
|
326
|
+
|
|
327
|
+
```html
|
|
328
|
+
<!DOCTYPE html>
|
|
329
|
+
<html lang="en">
|
|
330
|
+
<head>
|
|
331
|
+
<meta charset="UTF-8">
|
|
332
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
333
|
+
<title>Phase XX Design Preview</title>
|
|
334
|
+
<link rel="stylesheet" href="styles.css">
|
|
335
|
+
</head>
|
|
336
|
+
<body>
|
|
337
|
+
<main class="preview-container">
|
|
338
|
+
<h1>Phase XX Design Preview</h1>
|
|
339
|
+
|
|
340
|
+
<section class="component-section">
|
|
341
|
+
<h2>Buttons</h2>
|
|
342
|
+
<div class="component-grid">
|
|
343
|
+
<button class="btn btn-primary">Primary</button>
|
|
344
|
+
<button class="btn btn-secondary">Secondary</button>
|
|
345
|
+
<button class="btn btn-ghost">Ghost</button>
|
|
346
|
+
</div>
|
|
347
|
+
</section>
|
|
348
|
+
|
|
349
|
+
<!-- More sections -->
|
|
350
|
+
</main>
|
|
351
|
+
</body>
|
|
352
|
+
</html>
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
### CSS Reset + Variables
|
|
356
|
+
|
|
357
|
+
```css
|
|
358
|
+
/* styles.css */
|
|
359
|
+
*, *::before, *::after {
|
|
360
|
+
box-sizing: border-box;
|
|
361
|
+
margin: 0;
|
|
362
|
+
padding: 0;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
:root {
|
|
366
|
+
/* Colors */
|
|
367
|
+
--color-primary: #2563eb;
|
|
368
|
+
--color-primary-hover: #1d4ed8;
|
|
369
|
+
--color-secondary: #f3f4f6;
|
|
370
|
+
--color-text: #111827;
|
|
371
|
+
--color-text-secondary: #6b7280;
|
|
372
|
+
--color-border: #e5e7eb;
|
|
373
|
+
--color-background: #ffffff;
|
|
374
|
+
--color-surface: #f9fafb;
|
|
375
|
+
|
|
376
|
+
/* Spacing */
|
|
377
|
+
--space-1: 0.25rem;
|
|
378
|
+
--space-2: 0.5rem;
|
|
379
|
+
--space-3: 0.75rem;
|
|
380
|
+
--space-4: 1rem;
|
|
381
|
+
--space-6: 1.5rem;
|
|
382
|
+
--space-8: 2rem;
|
|
383
|
+
|
|
384
|
+
/* Typography */
|
|
385
|
+
--font-sans: system-ui, -apple-system, sans-serif;
|
|
386
|
+
--font-size-sm: 0.875rem;
|
|
387
|
+
--font-size-base: 1rem;
|
|
388
|
+
--font-size-lg: 1.125rem;
|
|
389
|
+
--font-size-xl: 1.25rem;
|
|
390
|
+
--font-size-2xl: 1.5rem;
|
|
391
|
+
|
|
392
|
+
/* Border radius */
|
|
393
|
+
--radius-sm: 0.375rem;
|
|
394
|
+
--radius-md: 0.5rem;
|
|
395
|
+
--radius-lg: 0.75rem;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
body {
|
|
399
|
+
font-family: var(--font-sans);
|
|
400
|
+
color: var(--color-text);
|
|
401
|
+
background: var(--color-surface);
|
|
402
|
+
line-height: 1.5;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
/* Button component */
|
|
406
|
+
.btn {
|
|
407
|
+
display: inline-flex;
|
|
408
|
+
align-items: center;
|
|
409
|
+
justify-content: center;
|
|
410
|
+
padding: var(--space-2) var(--space-4);
|
|
411
|
+
font-size: var(--font-size-base);
|
|
412
|
+
font-weight: 500;
|
|
413
|
+
border-radius: var(--radius-md);
|
|
414
|
+
border: none;
|
|
415
|
+
cursor: pointer;
|
|
416
|
+
transition: all 0.15s ease;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
.btn-primary {
|
|
420
|
+
background: var(--color-primary);
|
|
421
|
+
color: white;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
.btn-primary:hover {
|
|
425
|
+
background: var(--color-primary-hover);
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
.btn-secondary {
|
|
429
|
+
background: var(--color-secondary);
|
|
430
|
+
color: var(--color-text);
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
.btn-ghost {
|
|
434
|
+
background: transparent;
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
.btn-ghost:hover {
|
|
438
|
+
background: var(--color-secondary);
|
|
439
|
+
}
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
## Python Frontend Patterns
|
|
443
|
+
|
|
444
|
+
### Jinja2 Templates (Flask/Django)
|
|
445
|
+
|
|
446
|
+
```html
|
|
447
|
+
<!-- templates/components/button.html -->
|
|
448
|
+
{% macro button(text, variant='primary', size='md', type='button') %}
|
|
449
|
+
<button
|
|
450
|
+
type="{{ type }}"
|
|
451
|
+
class="btn btn-{{ variant }} btn-{{ size }}"
|
|
452
|
+
>
|
|
453
|
+
{{ text }}
|
|
454
|
+
</button>
|
|
455
|
+
{% endmacro %}
|
|
456
|
+
```
|
|
457
|
+
|
|
458
|
+
```html
|
|
459
|
+
<!-- templates/preview.html -->
|
|
460
|
+
{% from "components/button.html" import button %}
|
|
461
|
+
|
|
462
|
+
<!DOCTYPE html>
|
|
463
|
+
<html>
|
|
464
|
+
<head>
|
|
465
|
+
<link rel="stylesheet" href="{{ url_for('static', filename='styles.css') }}">
|
|
466
|
+
</head>
|
|
467
|
+
<body>
|
|
468
|
+
<h1>Design Preview</h1>
|
|
469
|
+
|
|
470
|
+
<section>
|
|
471
|
+
<h2>Buttons</h2>
|
|
472
|
+
{{ button('Primary', 'primary') }}
|
|
473
|
+
{{ button('Secondary', 'secondary') }}
|
|
474
|
+
</section>
|
|
475
|
+
</body>
|
|
476
|
+
</html>
|
|
477
|
+
```
|
|
478
|
+
|
|
479
|
+
### Streamlit (for data apps)
|
|
480
|
+
|
|
481
|
+
```python
|
|
482
|
+
# mockup_preview.py
|
|
483
|
+
import streamlit as st
|
|
484
|
+
|
|
485
|
+
st.set_page_config(page_title="Phase XX Design", layout="wide")
|
|
486
|
+
|
|
487
|
+
st.title("Phase XX Design Preview")
|
|
488
|
+
|
|
489
|
+
with st.container():
|
|
490
|
+
st.subheader("Buttons")
|
|
491
|
+
col1, col2, col3 = st.columns(3)
|
|
492
|
+
|
|
493
|
+
with col1:
|
|
494
|
+
st.button("Primary", type="primary")
|
|
495
|
+
with col2:
|
|
496
|
+
st.button("Secondary")
|
|
497
|
+
with col3:
|
|
498
|
+
st.button("Ghost", type="secondary")
|
|
499
|
+
|
|
500
|
+
with st.container():
|
|
501
|
+
st.subheader("Cards")
|
|
502
|
+
with st.expander("Example Card", expanded=True):
|
|
503
|
+
st.write("Card content goes here")
|
|
504
|
+
```
|
|
505
|
+
|
|
506
|
+
## Mockup Serving
|
|
507
|
+
|
|
508
|
+
### React/Next.js
|
|
509
|
+
|
|
510
|
+
Add to package.json scripts or run:
|
|
511
|
+
```bash
|
|
512
|
+
# If using Next.js app router
|
|
513
|
+
# Create app/mockups/page.tsx that imports preview
|
|
514
|
+
|
|
515
|
+
# Or use Storybook-lite approach
|
|
516
|
+
npx vite .planning/phases/XX-name/mockups
|
|
517
|
+
```
|
|
518
|
+
|
|
519
|
+
### SwiftUI
|
|
520
|
+
|
|
521
|
+
Open in Xcode, use Canvas preview (Cmd+Option+Enter)
|
|
522
|
+
|
|
523
|
+
### HTML/CSS
|
|
524
|
+
|
|
525
|
+
```bash
|
|
526
|
+
# Simple Python server
|
|
527
|
+
python -m http.server 8080 --directory .planning/phases/XX-name/mockups
|
|
528
|
+
|
|
529
|
+
# Or use live-server
|
|
530
|
+
npx live-server .planning/phases/XX-name/mockups
|
|
531
|
+
```
|
|
532
|
+
|
|
533
|
+
### Python
|
|
534
|
+
|
|
535
|
+
```bash
|
|
536
|
+
# Flask
|
|
537
|
+
FLASK_APP=mockup_preview.py flask run
|
|
538
|
+
|
|
539
|
+
# Streamlit
|
|
540
|
+
streamlit run mockup_preview.py
|
|
541
|
+
```
|
|
542
|
+
|
|
543
|
+
</framework_patterns>
|