File size: 12,085 Bytes
9eafd9f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
# Research: Full-Stack Integration & UI Experience

**Feature**: 002-fullstack-ui-integration
**Date**: 2026-01-09
**Status**: Complete

## Overview

This research document captures technical decisions, patterns, and best practices for integrating existing functionality (Specs 1 & 2) into a cohesive user experience. Since this is a polish/integration feature rather than new functionality, most decisions reference existing implementations.

## Research Areas

### 1. UI State Management Patterns

**Decision**: Use React hooks (useState, useEffect) with loading/error/data states

**Rationale**:
- Already established pattern in existing components (TaskList, TaskForm)
- Simple and effective for component-level state
- No need for global state management (Redux, Zustand) for this scope
- Aligns with Next.js App Router best practices

**Pattern**:
```typescript
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
const [data, setData] = useState<T | null>(null);
```

**Alternatives Considered**:
- React Query / TanStack Query: Overkill for current scope, adds dependency
- Redux: Too complex for simple loading/error states
- Context API: Not needed - state is component-local

**References**:
- Existing: `frontend/src/components/tasks/TaskList.tsx` (lines 10-15)
- Next.js Data Fetching: https://nextjs.org/docs/app/building-your-application/data-fetching

---

### 2. Loading State Indicators

**Decision**: Use Tailwind CSS spinner with descriptive text

**Rationale**:
- Consistent with existing Tailwind-only styling constraint
- Accessible (includes text for screen readers)
- Lightweight (no external animation libraries)
- Fast to implement and customize

**Pattern**:
```tsx
{isLoading && (
  <div className="flex items-center justify-center p-8">
    <div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600"></div>
    <span className="ml-3 text-gray-600">Loading tasks...</span>
  </div>
)}
```

**Alternatives Considered**:
- Skeleton screens: More complex, better for content-heavy pages
- Progress bars: Not suitable for indeterminate loading
- Third-party libraries (react-spinners): Adds dependency, unnecessary

**References**:
- Tailwind Animation: https://tailwindcss.com/docs/animation
- Accessibility: Include aria-live="polite" for screen readers

---

### 3. Empty State Design

**Decision**: Centered message with icon and call-to-action

**Rationale**:
- Guides users toward next action (create first task)
- Reduces confusion when no data exists
- Industry standard pattern (GitHub, Notion, Linear)
- Improves onboarding experience

**Pattern**:
```tsx
{tasks.length === 0 && !isLoading && (
  <div className="text-center py-12">
    <p className="text-gray-500 text-lg mb-4">No tasks yet</p>
    <p className="text-gray-400 mb-6">Create your first task to get started</p>
    <button className="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700">
      Create Task
    </button>
  </div>
)}
```

**Alternatives Considered**:
- Blank screen: Poor UX, users don't know what to do
- Tutorial overlay: Too intrusive for simple app
- Animated illustrations: Adds complexity, not needed

**References**:
- Empty States Best Practices: https://www.nngroup.com/articles/empty-state-design/
- Material Design Empty States: https://m2.material.io/design/communication/empty-states.html

---

### 4. Error Handling & Display

**Decision**: Inline error messages with retry button

**Rationale**:
- Keeps user in context (no modal dialogs)
- Provides actionable recovery (retry button)
- Consistent with existing API error handling
- Follows progressive disclosure principle

**Pattern**:
```tsx
{error && (
  <div className="bg-red-50 border border-red-200 rounded-md p-4 mb-4">
    <div className="flex items-start">
      <div className="flex-1">
        <h3 className="text-sm font-medium text-red-800">Error</h3>
        <p className="text-sm text-red-700 mt-1">{error}</p>
      </div>
      <button
        onClick={handleRetry}
        className="ml-3 text-sm font-medium text-red-600 hover:text-red-500"
      >
        Retry
      </button>
    </div>
  </div>
)}
```

**Alternatives Considered**:
- Toast notifications: Disappear too quickly, users miss them
- Modal dialogs: Disruptive, blocks entire UI
- Console.error only: Not user-facing, poor UX

**References**:
- Existing: `frontend/src/lib/api.ts` APIError class
- Error Message Guidelines: https://www.nngroup.com/articles/error-message-guidelines/

---

### 5. Responsive Design Breakpoints

**Decision**: Use Tailwind's default breakpoints (sm: 640px, md: 768px, lg: 1024px)

**Rationale**:
- Already configured in existing tailwind.config.ts
- Industry-standard breakpoints
- Covers mobile (320px-767px), tablet (768px-1023px), desktop (1024px+)
- No custom breakpoints needed for this scope

**Pattern**:
```tsx
<div className="grid gap-6 lg:grid-cols-3 md:grid-cols-2 grid-cols-1">
  {/* Mobile: 1 column, Tablet: 2 columns, Desktop: 3 columns */}
</div>
```

**Breakpoint Strategy**:
- **Mobile (<768px)**: Single column, stacked layout
- **Tablet (768px-1023px)**: Two columns where appropriate
- **Desktop (≥1024px)**: Three columns, full layout

**Alternatives Considered**:
- Custom breakpoints: Unnecessary complexity
- Container queries: Not widely supported yet
- Fixed pixel widths: Not responsive

**References**:
- Existing: `frontend/tailwind.config.ts`
- Tailwind Responsive Design: https://tailwindcss.com/docs/responsive-design

---

### 6. Touch Target Sizing

**Decision**: Minimum 44x44px for all interactive elements

**Rationale**:
- WCAG 2.1 Level AAA guideline (44x44px)
- Apple Human Interface Guidelines (44x44pt)
- Material Design (48x48dp)
- Prevents accidental taps on mobile devices

**Pattern**:
```tsx
<button className="min-h-[44px] min-w-[44px] px-4 py-2">
  Click Me
</button>
```

**Implementation**:
- Buttons: `min-h-[44px]` class
- Links: Adequate padding (py-2 px-3 minimum)
- Form inputs: `h-11` or `h-12` classes
- Checkboxes: `w-5 h-5` (20px) with larger clickable area via padding

**Alternatives Considered**:
- 48x48px: More generous but takes more space
- 40x40px: Below accessibility guidelines
- Variable sizing: Inconsistent, harder to maintain

**References**:
- WCAG 2.1 Success Criterion 2.5.5: https://www.w3.org/WAI/WCAG21/Understanding/target-size.html
- Apple HIG: https://developer.apple.com/design/human-interface-guidelines/ios/visual-design/adaptivity-and-layout/

---

### 7. API Client Error Handling

**Decision**: Centralized error handling in fetchAPI with typed errors

**Rationale**:
- Already implemented in `frontend/src/lib/api.ts`
- Consistent error structure across all API calls
- TypeScript types for error responses
- Automatic 401 handling with signin redirect

**Existing Implementation**:
```typescript
class APIError extends Error {
  constructor(
    message: string,
    public status: number,
    public errorCode?: string,
    public fieldErrors?: Record<string, string[]>
  ) {
    super(message);
    this.name = 'APIError';
  }
}
```

**Enhancement Needed**: None - existing implementation is sufficient

**Alternatives Considered**:
- Per-component error handling: Inconsistent, duplicated code
- Global error boundary: Too coarse-grained, loses context
- Axios interceptors: Adds dependency, fetch is sufficient

**References**:
- Existing: `frontend/src/lib/api.ts` (lines 6-16, 18-59)

---

### 8. Form Validation Patterns

**Decision**: Client-side validation with inline error messages

**Rationale**:
- Already implemented in SignUpForm and SignInForm
- Immediate feedback improves UX
- Reduces unnecessary API calls
- Backend validation still enforced (defense in depth)

**Existing Pattern**:
```typescript
const [errors, setErrors] = useState<Record<string, string>>({});

const validateEmail = (email: string): boolean => {
  const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
  return emailRegex.test(email);
};

// Display errors inline
{errors.email && (
  <p className="text-red-600 text-sm mt-1">{errors.email}</p>
)}
```

**Enhancement Needed**: None - existing validation is sufficient

**Alternatives Considered**:
- Form libraries (React Hook Form, Formik): Overkill for simple forms
- Schema validation (Zod, Yup): Adds complexity, not needed
- Server-side only: Poor UX, slow feedback

**References**:
- Existing: `frontend/src/components/auth/SignUpForm.tsx` (lines 20-40)
- Existing: `frontend/src/components/auth/SignInForm.tsx`

---

### 9. Optimistic UI Updates

**Decision**: Update UI immediately, rollback on error

**Rationale**:
- Improves perceived performance
- Makes app feel responsive
- Standard pattern for modern web apps
- Easy to implement with React state

**Pattern**:
```typescript
const handleToggleComplete = async (taskId: number) => {
  // Optimistic update
  setTasks(tasks.map(t =>
    t.id === taskId ? { ...t, completed: !t.completed } : t
  ));

  try {
    await patchTask(taskId, { completed: !task.completed });
  } catch (error) {
    // Rollback on error
    setTasks(tasks.map(t =>
      t.id === taskId ? { ...t, completed: task.completed } : t
    ));
    setError('Failed to update task');
  }
};
```

**Alternatives Considered**:
- Wait for server response: Slower, less responsive
- No rollback: Inconsistent state on errors
- Pessimistic updates: Poor UX

**References**:
- React Optimistic Updates: https://react.dev/reference/react/useOptimistic
- Existing: Partially implemented in TaskItem component

---

### 10. Environment Configuration

**Decision**: Use .env files with clear documentation

**Rationale**:
- Already established in Specs 1 & 2
- Standard practice for web applications
- Keeps secrets out of source code
- Easy to configure for different environments

**Existing Configuration**:
- Backend: `backend/.env` (DATABASE_URL, BETTER_AUTH_SECRET, JWT_ALGORITHM, JWT_EXPIRATION_DAYS)
- Frontend: `frontend/.env.local` (NEXT_PUBLIC_API_URL, BETTER_AUTH_SECRET)

**Enhancement Needed**: Document in README files and quickstart.md

**Alternatives Considered**:
- Hardcoded values: Security risk, not flexible
- Config files: Less standard than .env
- Cloud secret managers: Overkill for local development

**References**:
- Existing: `backend/.env`, `frontend/.env.local`
- Next.js Environment Variables: https://nextjs.org/docs/app/building-your-application/configuring/environment-variables

---

## Summary of Decisions

| Area | Decision | Status |
|------|----------|--------|
| UI State Management | React hooks (useState, useEffect) | ✅ Existing |
| Loading Indicators | Tailwind CSS spinner with text | 🔄 To implement |
| Empty States | Centered message with CTA | 🔄 To implement |
| Error Display | Inline errors with retry button | 🔄 To implement |
| Responsive Design | Tailwind default breakpoints | ✅ Existing |
| Touch Targets | Minimum 44x44px | 🔄 To verify |
| API Error Handling | Centralized fetchAPI with typed errors | ✅ Existing |
| Form Validation | Client-side with inline errors | ✅ Existing |
| Optimistic Updates | Immediate UI update with rollback | 🔄 To implement |
| Environment Config | .env files with documentation | ✅ Existing |

**Legend**:
- ✅ Existing: Already implemented in Specs 1 & 2
- 🔄 To implement: Needs to be added in this feature
- 🔄 To verify: Needs to be checked/refined

## Implementation Priorities

Based on user story priorities (P1-P5):

1. **P1 (Authentication Flow)**: Verify existing implementation works end-to-end
2. **P2 (UI States)**: Implement loading, empty, and error states
3. **P3 (Responsive Design)**: Verify and refine responsive layouts
4. **P4 (API Communication)**: Verify centralized API client works correctly
5. **P5 (Environment Setup)**: Document configuration in README files

## Next Steps

1. Generate `data-model.md` (reference existing User and Task entities)
2. Generate `contracts/` (document existing API endpoints)
3. Generate `quickstart.md` (testing and setup guide)
4. Proceed to task generation (`/sp.tasks`)