@minhduydev/mdpi 0.4.0 → 0.5.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/dist/index.js +1 -1
- package/dist/template/.pi/VERSION +1 -1
- package/dist/template/.pi/extensions/templates-injector.ts +34 -6
- package/dist/template/.pi/prompts/INDEX.md +3 -9
- package/dist/template/.pi/skills/INDEX.md +81 -19
- package/dist/template/.pi/skills/accessibility-audit/SKILL.md +8 -2
- package/dist/template/.pi/skills/baseline-ui/SKILL.md +211 -0
- package/dist/template/.pi/skills/dcp-hygiene/SKILL.md +1 -1
- package/dist/template/.pi/skills/design-taste-frontend/SKILL.md +53 -42
- package/dist/template/.pi/skills/fixing-accessibility/SKILL.md +509 -0
- package/dist/template/.pi/skills/frontend-design/SKILL.md +60 -47
- package/dist/template/.pi/skills/frontend-design/references/animation/motion-advanced.md +88 -15
- package/dist/template/.pi/skills/frontend-design/references/animation/motion-core.md +148 -13
- package/dist/template/.pi/skills/frontend-design/references/shadcn/setup.md +127 -20
- package/dist/template/.pi/skills/frontend-ui-engineering/SKILL.md +21 -27
- package/dist/template/.pi/skills/nextjs-app-router/SKILL.md +334 -0
- package/dist/template/.pi/skills/nextjs-cache/SKILL.md +262 -0
- package/dist/template/.pi/skills/oklch-color-workflow/SKILL.md +426 -0
- package/dist/template/.pi/skills/production-hardening/SKILL.md +652 -0
- package/dist/template/.pi/skills/react-best-practices/SKILL.md +79 -1
- package/dist/template/.pi/skills/react-compiler/SKILL.md +237 -0
- package/dist/template/.pi/skills/react-hook-form/SKILL.md +374 -0
- package/dist/template/.pi/skills/react-server-actions/SKILL.md +299 -0
- package/dist/template/.pi/skills/shadcn-ui/SKILL.md +404 -0
- package/dist/template/.pi/skills/tanstack-query/SKILL.md +330 -0
- package/dist/template/.pi/skills/ui-craft-principles/SKILL.md +564 -0
- package/dist/template/.pi/skills/ui-quality-audit/SKILL.md +329 -0
- package/dist/template/.pi/skills/v0/SKILL.md +264 -0
- package/dist/template/.pi/skills/zustand/SKILL.md +333 -0
- package/dist/template/.pi/templates/DESIGN.md +76 -0
- package/dist/template/.pi/workflows/INDEX.md +2 -1
- package/dist/template/.pi/workflows/frontend-feature-workflow.md +343 -0
- package/dist/template/.pi/workflows/quality-loop.md +1 -1
- package/package.json +1 -1
- package/dist/template/.pi/prompts/loop-check.md +0 -87
- package/dist/template/.pi/prompts/loop-init.md +0 -157
- package/dist/template/.pi/prompts/loop-review.md +0 -90
- package/dist/template/.pi/skills/loop-audit/SKILL.md +0 -141
- package/dist/template/.pi/skills/loop-cost/SKILL.md +0 -130
- package/dist/template/.pi/skills/loop-engineering/SKILL.md +0 -175
- package/dist/template/.pi/templates/loop-github-action.yml +0 -162
- package/dist/template/.pi/templates/loop-orchestrator.sh +0 -514
- package/dist/template/.pi/templates/loop-orchestrator.test.ts +0 -332
- package/dist/template/.pi/templates/loop-orchestrator.ts +0 -936
- package/dist/template/.pi/templates/loop-state.json +0 -24
- package/dist/template/.pi/templates/loop-state.md +0 -98
- package/dist/template/.pi/templates/loop-vision.md +0 -110
- /package/dist/template/.pi/templates/{design.md → feature-design.md} +0 -0
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: zustand
|
|
3
|
+
description: Use when implementing global or shared state management in React with Zustand v5. Covers store creation, slices pattern, middleware, selective subscriptions, React 19 + SSR integration. MUST load before any state management implementation.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Zustand v5
|
|
7
|
+
|
|
8
|
+
## When to Use
|
|
9
|
+
|
|
10
|
+
- Managing global or shared client-side state in React
|
|
11
|
+
- Replacing Redux, Jotai, or Context for state management
|
|
12
|
+
- Creating stores that are used across multiple components
|
|
13
|
+
- Implementing slices for domain-separated state
|
|
14
|
+
- Persisting state to localStorage or sessionStorage
|
|
15
|
+
- Using middleware (immer, devtools, persist)
|
|
16
|
+
|
|
17
|
+
## When NOT to Use
|
|
18
|
+
|
|
19
|
+
- Server state (use TanStack Query or Server Components)
|
|
20
|
+
- Form state (use React Hook Form or Server Actions)
|
|
21
|
+
- Single-component local state (use `useState` or `useReducer`)
|
|
22
|
+
- Server Components (Zustand is client-only)
|
|
23
|
+
|
|
24
|
+
## Setup
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npm install zustand
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Basic Store
|
|
31
|
+
|
|
32
|
+
```tsx
|
|
33
|
+
// stores/counter.ts
|
|
34
|
+
import { create } from 'zustand'
|
|
35
|
+
|
|
36
|
+
interface CounterState {
|
|
37
|
+
count: number
|
|
38
|
+
increment: () => void
|
|
39
|
+
decrement: () => void
|
|
40
|
+
reset: () => void
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export const useCounterStore = create<CounterState>((set) => ({
|
|
44
|
+
count: 0,
|
|
45
|
+
increment: () => set((state) => ({ count: state.count + 1 })),
|
|
46
|
+
decrement: () => set((state) => ({ count: state.count - 1 })),
|
|
47
|
+
reset: () => set({ count: 0 }),
|
|
48
|
+
}))
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
```tsx
|
|
52
|
+
// components/Counter.tsx
|
|
53
|
+
'use client'
|
|
54
|
+
|
|
55
|
+
import { useCounterStore } from '@/stores/counter'
|
|
56
|
+
|
|
57
|
+
export function Counter() {
|
|
58
|
+
const { count, increment, decrement } = useCounterStore()
|
|
59
|
+
|
|
60
|
+
return (
|
|
61
|
+
<div>
|
|
62
|
+
<p>Count: {count}</p>
|
|
63
|
+
<button onClick={increment}>+</button>
|
|
64
|
+
<button onClick={decrement}>-</button>
|
|
65
|
+
</div>
|
|
66
|
+
)
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Slices Pattern
|
|
71
|
+
|
|
72
|
+
Split store into domain slices:
|
|
73
|
+
|
|
74
|
+
```tsx
|
|
75
|
+
// stores/index.ts
|
|
76
|
+
import { create } from 'zustand'
|
|
77
|
+
import { createAuthSlice, type AuthSlice } from './slices/auth'
|
|
78
|
+
import { createCartSlice, type CartSlice } from './slices/cart'
|
|
79
|
+
|
|
80
|
+
type Store = AuthSlice & CartSlice
|
|
81
|
+
|
|
82
|
+
export const useStore = create<Store>()((...args) => ({
|
|
83
|
+
...createAuthSlice(...args),
|
|
84
|
+
...createCartSlice(...args),
|
|
85
|
+
}))
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
```tsx
|
|
89
|
+
// stores/slices/auth.ts
|
|
90
|
+
import type { StateCreator } from 'zustand'
|
|
91
|
+
|
|
92
|
+
export interface AuthSlice {
|
|
93
|
+
user: User | null
|
|
94
|
+
login: (credentials: Credentials) => Promise<void>
|
|
95
|
+
logout: () => void
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export const createAuthSlice: StateCreator<AuthSlice, [], [], AuthSlice> = (set) => ({
|
|
99
|
+
user: null,
|
|
100
|
+
login: async (credentials) => {
|
|
101
|
+
const user = await api.login(credentials)
|
|
102
|
+
set({ user })
|
|
103
|
+
},
|
|
104
|
+
logout: () => set({ user: null }),
|
|
105
|
+
})
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Selective Subscriptions
|
|
109
|
+
|
|
110
|
+
Zustand re-renders only when **used** state changes:
|
|
111
|
+
|
|
112
|
+
```tsx
|
|
113
|
+
// ❌ Whole store — re-renders on any change
|
|
114
|
+
const { count, name } = useStore()
|
|
115
|
+
|
|
116
|
+
// ✅ Selective — re-renders only when count changes
|
|
117
|
+
const count = useStore((state) => state.count)
|
|
118
|
+
const increment = useStore((state) => state.increment) // Stable reference
|
|
119
|
+
|
|
120
|
+
// ✅ Multiple values — useShallow for objects
|
|
121
|
+
import { useShallow } from 'zustand/react/shallow'
|
|
122
|
+
|
|
123
|
+
const { name, email } = useStore(
|
|
124
|
+
useShallow((state) => ({ name: state.user.name, email: state.user.email }))
|
|
125
|
+
)
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
`useShallow` does shallow equality — avoids re-render when both values are the same.
|
|
129
|
+
|
|
130
|
+
## Middleware
|
|
131
|
+
|
|
132
|
+
### Persist (localStorage)
|
|
133
|
+
|
|
134
|
+
```tsx
|
|
135
|
+
import { create } from 'zustand'
|
|
136
|
+
import { persist } from 'zustand/middleware'
|
|
137
|
+
|
|
138
|
+
export const useSettingsStore = create(
|
|
139
|
+
persist(
|
|
140
|
+
(set) => ({
|
|
141
|
+
theme: 'light',
|
|
142
|
+
setTheme: (theme: 'light' | 'dark') => set({ theme }),
|
|
143
|
+
}),
|
|
144
|
+
{
|
|
145
|
+
name: 'app-settings', // localStorage key
|
|
146
|
+
partialize: (state) => ({ theme: state.theme }), // Only persist theme
|
|
147
|
+
}
|
|
148
|
+
)
|
|
149
|
+
)
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### Immer (Immutable Updates)
|
|
153
|
+
|
|
154
|
+
```tsx
|
|
155
|
+
import { create } from 'zustand'
|
|
156
|
+
import { immer } from 'zustand/middleware/immer'
|
|
157
|
+
|
|
158
|
+
export const useTodoStore = create(
|
|
159
|
+
immer((set) => ({
|
|
160
|
+
todos: [] as Todo[],
|
|
161
|
+
addTodo: (text: string) =>
|
|
162
|
+
set((state) => {
|
|
163
|
+
state.todos.push({ id: crypto.randomUUID(), text, done: false })
|
|
164
|
+
}),
|
|
165
|
+
toggleTodo: (id: string) =>
|
|
166
|
+
set((state) => {
|
|
167
|
+
const todo = state.todos.find((t) => t.id === id)
|
|
168
|
+
if (todo) todo.done = !todo.done
|
|
169
|
+
}),
|
|
170
|
+
}))
|
|
171
|
+
)
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### DevTools
|
|
175
|
+
|
|
176
|
+
```tsx
|
|
177
|
+
import { create } from 'zustand'
|
|
178
|
+
import { devtools } from 'zustand/middleware'
|
|
179
|
+
|
|
180
|
+
export const useStore = create(
|
|
181
|
+
devtools(
|
|
182
|
+
(set) => ({
|
|
183
|
+
count: 0,
|
|
184
|
+
increment: () => set((s) => ({ count: s.count + 1 }), false, 'increment'),
|
|
185
|
+
}),
|
|
186
|
+
{ name: 'AppStore' } // Name in Redux DevTools
|
|
187
|
+
)
|
|
188
|
+
)
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### Combining Multiple Middleware
|
|
192
|
+
|
|
193
|
+
```tsx
|
|
194
|
+
import { create } from 'zustand'
|
|
195
|
+
import { devtools, persist, immer } from 'zustand/middleware'
|
|
196
|
+
|
|
197
|
+
export const useStore = create(
|
|
198
|
+
devtools(
|
|
199
|
+
persist(
|
|
200
|
+
immer((set) => ({
|
|
201
|
+
// store...
|
|
202
|
+
})),
|
|
203
|
+
{ name: 'app-storage' }
|
|
204
|
+
),
|
|
205
|
+
{ name: 'AppStore' }
|
|
206
|
+
)
|
|
207
|
+
)
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
## React 19 + Server Components
|
|
211
|
+
|
|
212
|
+
Zustand is **client-only**. Pattern for Next.js App Router:
|
|
213
|
+
|
|
214
|
+
```tsx
|
|
215
|
+
// stores/useStore.ts
|
|
216
|
+
import { create } from 'zustand'
|
|
217
|
+
|
|
218
|
+
export const useStore = create<Store>((set) => ({
|
|
219
|
+
// ...
|
|
220
|
+
}))
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
```tsx
|
|
224
|
+
// components/ClientWrapper.tsx
|
|
225
|
+
'use client'
|
|
226
|
+
|
|
227
|
+
import { useStore } from '@/stores/useStore'
|
|
228
|
+
|
|
229
|
+
export function ClientWrapper({ children }) {
|
|
230
|
+
const data = useStore((s) => s.data)
|
|
231
|
+
|
|
232
|
+
return <div>{children}</div>
|
|
233
|
+
}
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
**Rules**:
|
|
237
|
+
- Stores are defined outside components (module scope)
|
|
238
|
+
- Store consumers must be in `'use client'` components
|
|
239
|
+
- Server Components can import the store type but cannot `useStore()`
|
|
240
|
+
- Use React Context to provide a store instance if you need SSR hydration
|
|
241
|
+
|
|
242
|
+
## SSR Hydration Pattern
|
|
243
|
+
|
|
244
|
+
```tsx
|
|
245
|
+
// app/providers.tsx
|
|
246
|
+
'use client'
|
|
247
|
+
|
|
248
|
+
import { type ReactNode, createContext, useContext, useRef } from 'react'
|
|
249
|
+
import { type StoreApi, useStore } from 'zustand'
|
|
250
|
+
|
|
251
|
+
// Create context for store
|
|
252
|
+
const StoreContext = createContext<StoreApi<AppStore> | null>(null)
|
|
253
|
+
|
|
254
|
+
export function StoreProvider({ children }: { children: ReactNode }) {
|
|
255
|
+
const storeRef = useRef<StoreApi<AppStore>>()
|
|
256
|
+
|
|
257
|
+
if (!storeRef.current) {
|
|
258
|
+
storeRef.current = createAppStore()
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
return (
|
|
262
|
+
<StoreContext.Provider value={storeRef.current}>
|
|
263
|
+
{children}
|
|
264
|
+
</StoreContext.Provider>
|
|
265
|
+
)
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// Hook to use the store
|
|
269
|
+
export function useAppStore<T>(selector: (state: AppStore) => T): T {
|
|
270
|
+
const store = useContext(StoreContext)
|
|
271
|
+
if (!store) throw new Error('Missing StoreProvider')
|
|
272
|
+
return useStore(store, selector)
|
|
273
|
+
}
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
## Async Actions
|
|
277
|
+
|
|
278
|
+
```tsx
|
|
279
|
+
// Async actions are just async functions in the store:
|
|
280
|
+
interface UserStore {
|
|
281
|
+
user: User | null
|
|
282
|
+
loading: boolean
|
|
283
|
+
error: Error | null
|
|
284
|
+
fetchUser: (id: string) => Promise<void>
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
export const useUserStore = create<UserStore>((set) => ({
|
|
288
|
+
user: null,
|
|
289
|
+
loading: false,
|
|
290
|
+
error: null,
|
|
291
|
+
fetchUser: async (id) => {
|
|
292
|
+
set({ loading: true, error: null })
|
|
293
|
+
try {
|
|
294
|
+
const user = await api.getUser(id)
|
|
295
|
+
set({ user, loading: false })
|
|
296
|
+
} catch (error) {
|
|
297
|
+
set({ error: error as Error, loading: false })
|
|
298
|
+
}
|
|
299
|
+
},
|
|
300
|
+
}))
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
## When to Use Zustand vs Context vs TanStack Query
|
|
304
|
+
|
|
305
|
+
| Tool | Best for |
|
|
306
|
+
|------|----------|
|
|
307
|
+
| **Zustand** | Global client state: theme, auth, cart, UI preferences |
|
|
308
|
+
| **React Context** | Dependency injection, theming, auth provider — static values that rarely change |
|
|
309
|
+
| **TanStack Query** | Server state: data fetching, caching, mutations |
|
|
310
|
+
| **useState/useReducer** | Local component state |
|
|
311
|
+
|
|
312
|
+
## Common Pitfalls
|
|
313
|
+
|
|
314
|
+
| Pitfall | Fix |
|
|
315
|
+
|---------|-----|
|
|
316
|
+
| Using Zustand for server state | Use TanStack Query for fetched data — Zustand for client-only state |
|
|
317
|
+
| `useStore()` without selector — re-renders on any change | Always use selectors: `useStore(s => s.count)` |
|
|
318
|
+
| Multiple values returned as new object every render | Use `useShallow` for object selectors |
|
|
319
|
+
| Store in Server Component | Move store usage to `'use client'` |
|
|
320
|
+
| `getState()` in render | `getState()` is for callbacks/outside React, not render |
|
|
321
|
+
| Large stores with everything in one file | Use slices pattern to separate domains |
|
|
322
|
+
| Recreating store on every render | Define store outside component or use `useRef` for context pattern |
|
|
323
|
+
|
|
324
|
+
## Verification
|
|
325
|
+
|
|
326
|
+
- [ ] Store defined outside component (module scope) or via `useRef` in provider
|
|
327
|
+
- [ ] All store consumers are in `'use client'` components
|
|
328
|
+
- [ ] Selectors used for granular subscriptions — no destructured `useStore()`
|
|
329
|
+
- [ ] `useShallow` used for multi-value object selectors
|
|
330
|
+
- [ ] Server state (fetched data) managed by TanStack Query, not Zustand
|
|
331
|
+
- [ ] Slices pattern used for stores with multiple domains
|
|
332
|
+
- [ ] `persist` middleware configured with `partialize` to avoid storing sensitive data
|
|
333
|
+
- [ ] DevTools middleware enabled (development only)
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
---
|
|
2
|
+
purpose: Project visual identity — single source of truth for mood, color, typography, layout, elevation, shapes, components, and design constraints.
|
|
3
|
+
updated: 2026-06-19
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# DESIGN.md — Project Visual Identity
|
|
7
|
+
|
|
8
|
+
> **Aesthetic Anchor:** [One evocative sentence referencing a specific era, artifact, or scene — not adjectives. Example: "A 1970s graduate lecture handout, mimeographed on off-white paper."]
|
|
9
|
+
|
|
10
|
+
## 1. Overview & Mood
|
|
11
|
+
|
|
12
|
+
- **Mood:** [2-3 words: e.g., "Architectural Minimalism", "Warm Editorial", "Brutalist Terminal"]
|
|
13
|
+
- **Specific Reference:** [A concrete scene, artifact, or era — not abstract adjectives]
|
|
14
|
+
- **Tone:** [Professional / Playful / Serious / Warm / Clinical]
|
|
15
|
+
- **Design Philosophy:** [1-2 sentences on guiding aesthetic principle]
|
|
16
|
+
|
|
17
|
+
## 2. Colors
|
|
18
|
+
|
|
19
|
+
- **Brand Palette:** `{colors.brand.primary}` `{colors.brand.secondary}` `{colors.brand.accent}`
|
|
20
|
+
- **Neutral Scale:** `{colors.neutral.50}` → `{colors.neutral.950}` (50/100/200/300/400/500/600/700/800/900/950)
|
|
21
|
+
- **Semantic Colors:** Success `{colors.semantic.success}`, Warning `{colors.semantic.warning}`, Error `{colors.semantic.error}`, Info `{colors.semantic.info}`
|
|
22
|
+
- **Contrast Floor:** WCAG 2.1 AA minimum (≥ 4.5:1 for body text)
|
|
23
|
+
- **No Pure Black:** Use `{colors.neutral.950}` instead of `#000`
|
|
24
|
+
|
|
25
|
+
## 3. Typography
|
|
26
|
+
|
|
27
|
+
- **Display Font:** `{typography.display.family}` — for H1, hero headings
|
|
28
|
+
- **Body Font:** `{typography.body.family}` — for paragraphs, UI labels
|
|
29
|
+
- **Mono Font:** `{typography.mono.family}` — for code, data, timestamps
|
|
30
|
+
- **Scale:** `{typography.scale}` (e.g., 12/14/16/18/20/24/30/36/48/60/72)
|
|
31
|
+
- **Weight Range:** `{typography.weights}` (e.g., 400/500/600/700)
|
|
32
|
+
- **Line Height:** 1.5 body, 1.2 headings
|
|
33
|
+
|
|
34
|
+
## 4. Layout & Spacing
|
|
35
|
+
|
|
36
|
+
- **Grid Base:** `{layout.grid}` (e.g., 4px or 8px)
|
|
37
|
+
- **Spacing Scale:** `{layout.spacing}` (e.g., 4/8/12/16/24/32/48/64/96)
|
|
38
|
+
- **Max Content Width:** `{layout.maxWidth}` (e.g., 1280px)
|
|
39
|
+
- **Column Count:** `{layout.columns}` (e.g., 12-column grid)
|
|
40
|
+
- **Gutter Width:** `{layout.gutter}` (e.g., 24px)
|
|
41
|
+
|
|
42
|
+
## 5. Elevation & Depth
|
|
43
|
+
|
|
44
|
+
- **Shadow Scale:** 5 levels (none / sm / md / lg / xl)
|
|
45
|
+
- **Depth Philosophy:** [Flat / Subtle depth / Heavy layering]
|
|
46
|
+
- **Z-Index Layers:** Base content → Overlays → Modals → Toasts → Tooltips
|
|
47
|
+
- **Border Usage:** When and where borders replace shadows
|
|
48
|
+
|
|
49
|
+
## 6. Shapes & Corners
|
|
50
|
+
|
|
51
|
+
- **Border Radius Scale:** `{shapes.borderRadius}` (e.g., 0/4/8/12/16/24/full)
|
|
52
|
+
- **Corner Philosophy:** [Sharp / Soft / Rounded / Pill]
|
|
53
|
+
- **Icon Style:** [Filled / Outline / Duotone / Custom]
|
|
54
|
+
- **Stroke Width:** `{shapes.strokeWidth}` (e.g., 1px or 1.5px)
|
|
55
|
+
|
|
56
|
+
## 7. Components
|
|
57
|
+
|
|
58
|
+
- **Button Hierarchy:** Primary `{components.button.primary}` / Secondary `{components.button.secondary}` / Ghost `{components.button.ghost}` / Danger `{components.button.danger}`
|
|
59
|
+
- **Input Style:** [Outlined / Filled / Underlined] with `{components.input.height}` height
|
|
60
|
+
- **Card Style:** [Elevated / Bordered / Flat] with `{components.card.padding}` padding
|
|
61
|
+
- **Modal Style:** [Centered / Slide-up / Fullscreen] with backdrop `{components.modal.backdrop}`
|
|
62
|
+
- **Navigation:** [Top bar / Sidebar / Bottom tabs] with `{components.nav.height}`
|
|
63
|
+
|
|
64
|
+
## 8. Do's and Don'ts
|
|
65
|
+
|
|
66
|
+
### Do's
|
|
67
|
+
|
|
68
|
+
- [Key principle 1 — with reasoning]
|
|
69
|
+
- [Key principle 2 — with reasoning]
|
|
70
|
+
- [Key principle 3 — with reasoning]
|
|
71
|
+
|
|
72
|
+
### Don'ts
|
|
73
|
+
|
|
74
|
+
- **Pattern:** [Anti-pattern] — **Replacement:** [Correct approach] — **Because:** [Why this matters]
|
|
75
|
+
- **Pattern:** [Anti-pattern] — **Replacement:** [Correct approach] — **Because:** [Why this matters]
|
|
76
|
+
- **Pattern:** [Anti-pattern] — **Replacement:** [Correct approach] — **Because:** [Why this matters]
|
|
@@ -4,7 +4,7 @@ purpose: Index of DAG workflows with trigger, phases, and invoking command
|
|
|
4
4
|
|
|
5
5
|
# Workflows Index
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
7 DAG workflows. All have `description` frontmatter (for `run_workflow` discovery) and use a consistent Phase format: `Agent`, `Concurrency`, `Depends on`, `Prompt`.
|
|
8
8
|
|
|
9
9
|
## Invocation
|
|
10
10
|
|
|
@@ -24,6 +24,7 @@ Workflows may compose recursively (e.g., `development-lifecycle-workflow` Phase
|
|
|
24
24
|
| `batch-implement` | 3 + merge | ≥5 independent tasks, no file conflicts | `/ship` Phase 3, `development-lifecycle-workflow` Phase 4 | One subagent per task in parallel, review, merge |
|
|
25
25
|
| `deep-research` | 2 + synthesis | Complex/multi-angle topic | `/research` (complex mode) | Fan out web searches per angle, cross-check, cited report |
|
|
26
26
|
| `development-lifecycle-workflow` | 5 | Explicit full-lifecycle multi-agent run | Manual / future `/lifecycle` | research → validate → plan → implement → verify (composes batch-implement) |
|
|
27
|
+
| `frontend-feature-workflow` | 7 | Frontend feature build (mockup or spec) | `run_workflow({ name: "frontend-feature-workflow", args: { feature: "..." } })` | design analysis → deslop → architecture → craft → implement → harden → audit |
|
|
27
28
|
| `garbage-collection` | 5 | Manual `/gc` or scheduled cadence | `/gc` | Fallow scan → grade → prioritize → optional cleanup PRs |
|
|
28
29
|
| `quality-loop` | 7 (looped) | High-risk feature, explicit quality gating | `/ship` Phase 5 (Iterative Quality Loop) | Score-gated review loop until 5/5 or escalation |
|
|
29
30
|
|