# 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(null); const [data, setData] = useState(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 && (
Loading tasks...
)} ``` **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 && (

No tasks yet

Create your first task to get started

)} ``` **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 && (

Error

{error}

)} ``` **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
{/* Mobile: 1 column, Tablet: 2 columns, Desktop: 3 columns */}
``` **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 ``` **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 ) { 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>({}); const validateEmail = (email: string): boolean => { const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; return emailRegex.test(email); }; // Display errors inline {errors.email && (

{errors.email}

)} ``` **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`)