aigent-team 0.1.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.
Files changed (71) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +253 -0
  3. package/dist/chunk-N3RYHWTR.js +267 -0
  4. package/dist/cli.js +576 -0
  5. package/dist/index.d.ts +234 -0
  6. package/dist/index.js +27 -0
  7. package/package.json +67 -0
  8. package/templates/shared/git-workflow.md +44 -0
  9. package/templates/shared/project-conventions.md +48 -0
  10. package/templates/teams/ba/agent.yaml +25 -0
  11. package/templates/teams/ba/references/acceptance-criteria.md +87 -0
  12. package/templates/teams/ba/references/api-contract-design.md +110 -0
  13. package/templates/teams/ba/references/requirements-analysis.md +83 -0
  14. package/templates/teams/ba/references/user-story-mapping.md +73 -0
  15. package/templates/teams/ba/skill.md +85 -0
  16. package/templates/teams/be/agent.yaml +34 -0
  17. package/templates/teams/be/conventions.md +102 -0
  18. package/templates/teams/be/references/api-design.md +91 -0
  19. package/templates/teams/be/references/async-processing.md +86 -0
  20. package/templates/teams/be/references/auth-security.md +58 -0
  21. package/templates/teams/be/references/caching.md +79 -0
  22. package/templates/teams/be/references/database.md +65 -0
  23. package/templates/teams/be/references/error-handling.md +106 -0
  24. package/templates/teams/be/references/observability.md +83 -0
  25. package/templates/teams/be/references/review-checklist.md +50 -0
  26. package/templates/teams/be/references/testing.md +100 -0
  27. package/templates/teams/be/review-checklist.md +54 -0
  28. package/templates/teams/be/skill.md +71 -0
  29. package/templates/teams/devops/agent.yaml +35 -0
  30. package/templates/teams/devops/conventions.md +133 -0
  31. package/templates/teams/devops/references/ci-cd.md +218 -0
  32. package/templates/teams/devops/references/cost-optimization.md +218 -0
  33. package/templates/teams/devops/references/disaster-recovery.md +199 -0
  34. package/templates/teams/devops/references/docker.md +237 -0
  35. package/templates/teams/devops/references/infrastructure-as-code.md +238 -0
  36. package/templates/teams/devops/references/kubernetes.md +397 -0
  37. package/templates/teams/devops/references/monitoring.md +224 -0
  38. package/templates/teams/devops/references/review-checklist.md +149 -0
  39. package/templates/teams/devops/references/security.md +225 -0
  40. package/templates/teams/devops/review-checklist.md +72 -0
  41. package/templates/teams/devops/skill.md +131 -0
  42. package/templates/teams/fe/agent.yaml +28 -0
  43. package/templates/teams/fe/conventions.md +80 -0
  44. package/templates/teams/fe/references/accessibility.md +92 -0
  45. package/templates/teams/fe/references/component-architecture.md +87 -0
  46. package/templates/teams/fe/references/css-styling.md +89 -0
  47. package/templates/teams/fe/references/forms.md +73 -0
  48. package/templates/teams/fe/references/performance.md +104 -0
  49. package/templates/teams/fe/references/review-checklist.md +51 -0
  50. package/templates/teams/fe/references/security.md +90 -0
  51. package/templates/teams/fe/references/state-management.md +117 -0
  52. package/templates/teams/fe/references/testing.md +112 -0
  53. package/templates/teams/fe/review-checklist.md +53 -0
  54. package/templates/teams/fe/skill.md +68 -0
  55. package/templates/teams/lead/agent.yaml +18 -0
  56. package/templates/teams/lead/references/cross-team-coordination.md +68 -0
  57. package/templates/teams/lead/references/quality-gates.md +64 -0
  58. package/templates/teams/lead/references/task-decomposition.md +69 -0
  59. package/templates/teams/lead/skill.md +83 -0
  60. package/templates/teams/qa/agent.yaml +32 -0
  61. package/templates/teams/qa/conventions.md +130 -0
  62. package/templates/teams/qa/references/ci-integration.md +337 -0
  63. package/templates/teams/qa/references/e2e-testing.md +292 -0
  64. package/templates/teams/qa/references/mocking.md +249 -0
  65. package/templates/teams/qa/references/performance-testing.md +288 -0
  66. package/templates/teams/qa/references/review-checklist.md +143 -0
  67. package/templates/teams/qa/references/security-testing.md +271 -0
  68. package/templates/teams/qa/references/test-data.md +275 -0
  69. package/templates/teams/qa/references/test-strategy.md +192 -0
  70. package/templates/teams/qa/review-checklist.md +53 -0
  71. package/templates/teams/qa/skill.md +131 -0
@@ -0,0 +1,80 @@
1
+ ## Component Architecture
2
+
3
+ - Use functional components exclusively. Class components are legacy — migrate when touching existing ones.
4
+ - Props interface is the component's contract. Design it like a public API:
5
+ - Use discriminated unions for variants: `type ButtonVariant = 'primary' | 'secondary' | 'ghost'` — not `isPrimary`, `isSecondary` booleans
6
+ - Required props first, optional with sensible defaults
7
+ - Callback props follow `onAction` naming: `onClick`, `onChange`, `onSubmit`
8
+ - Avoid `children` prop when the content structure is predictable — use named slots/props instead
9
+ - Co-locate everything for a component in one directory:
10
+ ```
11
+ Button/
12
+ ├── Button.tsx # Component
13
+ ├── Button.test.tsx # Tests
14
+ ├── Button.stories.tsx # Storybook
15
+ ├── Button.module.css # Styles (if not using Tailwind)
16
+ └── index.ts # Public export (only export what consumers need)
17
+ ```
18
+ - Component layers — enforce separation:
19
+ - **Primitives**: Design system atoms (Button, Input, Modal). No business logic. No API calls.
20
+ - **Composites**: Combine primitives for generic patterns (SearchBar, DataTable, FormField). Still no domain knowledge.
21
+ - **Features**: Domain-specific components (UserProfile, InvoiceList). Can fetch data, contain business logic.
22
+
23
+ ## State Management
24
+
25
+ - **Local state** (`useState`): UI-only state (open/closed, active tab, form input). This is the default.
26
+ - **Server state** (React Query/TanStack Query): All data from APIs. Never store server data in useState/Zustand. React Query handles caching, revalidation, and deduplication.
27
+ - **Global client state** (Zustand/Jotai): Cross-component UI state (theme, sidebar collapsed, toast queue). Keep this minimal — if it comes from the server, it belongs in React Query.
28
+ - **URL state** (search params): Anything the user should be able to bookmark or share (filters, pagination, selected tab). Use `useSearchParams` or a URL state library.
29
+ - **Never** duplicate server state into client stores. This causes sync bugs that are extremely hard to debug in production.
30
+
31
+ ## Performance Rules
32
+
33
+ - **Measure first, optimize second.** Don't add `useMemo`/`useCallback` prophylactically. Add them when React DevTools Profiler shows a measurable problem (>16ms render).
34
+ - Lazy load routes with `React.lazy()` + Suspense. Every route should be a separate chunk.
35
+ - Heavy components (charts, rich text editors, maps) get `dynamic(() => import(...), { ssr: false })` in Next.js.
36
+ - Images: Always use the framework's `<Image>` component. Set explicit `width`/`height` to prevent CLS. Use `priority` only for above-the-fold hero images.
37
+ - Fonts: Use `next/font` or `@fontsource`. Preload only the weights/subsets you actually use. `font-display: swap` always.
38
+ - Lists with >50 items must use virtualization (`react-window` or `@tanstack/react-virtual`). No exceptions.
39
+ - Avoid layout thrashing: batch DOM reads and writes. Never read `offsetHeight` inside a loop that modifies styles.
40
+
41
+ ## CSS & Styling
42
+
43
+ - Tailwind is preferred. Use `@apply` sparingly — only in base component styles where utility classes become unreadable (>6 classes).
44
+ - If using CSS modules, follow BEM-like naming: `.card`, `.card__header`, `.card--highlighted`.
45
+ - Never use inline `style={{}}` for layout or spacing. Only for truly dynamic values (calculated positions, user-selected colors).
46
+ - Design tokens (colors, spacing, typography) come from the design system / Tailwind config. Never hardcode hex values or pixel sizes.
47
+ - Z-index scale: define in a central config. Use semantic names (dropdown: 100, modal: 200, toast: 300, tooltip: 400). Never use arbitrary z-index values.
48
+
49
+ ## Forms
50
+
51
+ - Use React Hook Form + Zod for all forms. Define the Zod schema first — it serves as both validation and TypeScript type.
52
+ - Validate on blur for individual fields, on submit for the full form. Show inline errors immediately after blur.
53
+ - Disable submit button only during submission (not for validation). Show validation errors instead of hiding the submit action.
54
+ - Multi-step forms: persist partial state to sessionStorage or URL params. Users who accidentally navigate away should not lose data.
55
+ - File uploads: show progress, support drag-and-drop, validate file type/size client-side before upload.
56
+
57
+ ## Error Handling
58
+
59
+ - Wrap feature sections with React Error Boundaries. A chart crashing should not take down the entire page.
60
+ - API errors: distinguish between 4xx (show user-actionable message) and 5xx (show generic "something went wrong" + retry).
61
+ - Network errors: detect offline state (`navigator.onLine` + `online`/`offline` events). Show persistent banner when offline. Queue mutations for retry.
62
+ - Race conditions: cancel in-flight requests on component unmount (`AbortController` in useEffect cleanup). Cancel previous search requests on new input (debounce + abort).
63
+ - Never show raw error messages to users. Map API error codes to human-readable messages. Log raw errors to monitoring (Sentry/DataDog).
64
+
65
+ ## Testing
66
+
67
+ - Test from the user's perspective. Query by role (`getByRole('button', { name: 'Submit' })`), not by test ID.
68
+ - Test behavior, not implementation: "when user clicks submit, success message appears" — not "when submit handler is called, setState is invoked".
69
+ - Snapshot tests are banned for component output. They break on every style change and catch nothing meaningful. Use visual regression (Chromatic/Percy) instead.
70
+ - Test keyboard navigation for all interactive components.
71
+ - Mock network requests with MSW (Mock Service Worker), not by mocking fetch/axios directly.
72
+ - Every bug fix must include a test that would have caught the bug.
73
+
74
+ ## Security
75
+
76
+ - Never use `dangerouslySetInnerHTML` without sanitizing with DOMPurify first.
77
+ - Never construct URLs from user input without validation. Use `URL` constructor and whitelist allowed origins.
78
+ - CSRF: ensure all mutation requests include the CSRF token. Framework should handle this — verify it's configured.
79
+ - Sensitive data (tokens, PII) must never appear in URL query params, localStorage, or client-side logs.
80
+ - Content Security Policy: work with DevOps to set strict CSP headers. Report violations to a monitoring endpoint.
@@ -0,0 +1,92 @@
1
+ # Accessibility (WCAG 2.1 AA)
2
+
3
+ ## Keyboard Navigation
4
+
5
+ Every interactive element must be operable via keyboard:
6
+ - **Tab**: Move focus to next interactive element
7
+ - **Shift+Tab**: Move focus backward
8
+ - **Enter/Space**: Activate buttons, links, checkboxes
9
+ - **Escape**: Close modals, dropdowns, tooltips
10
+ - **Arrow keys**: Navigate within lists, menus, tabs, radio groups
11
+ - **Home/End**: Jump to first/last item in list
12
+
13
+ **Focus management rules:**
14
+ - Focus order must match visual order (no `tabindex > 0`)
15
+ - Modals trap focus — Tab cycles within modal, cannot escape to background
16
+ - After modal closes, focus returns to the element that opened it
17
+ - After deleting an item, focus moves to next item or parent container
18
+ - Skip links: first Tab stop on page should be "Skip to main content"
19
+
20
+ **Visible focus indicator:**
21
+ ```css
22
+ :focus-visible {
23
+ outline: 2px solid var(--focus-color);
24
+ outline-offset: 2px;
25
+ }
26
+ /* Never: *:focus { outline: none; } */
27
+ ```
28
+
29
+ ## ARIA Attributes
30
+
31
+ **Use semantic HTML first** — ARIA is a last resort when HTML semantics are insufficient:
32
+ ```html
33
+ <!-- GOOD: semantic HTML, no ARIA needed -->
34
+ <button>Submit</button>
35
+ <nav><ul>...</ul></nav>
36
+
37
+ <!-- BAD: div with ARIA role -->
38
+ <div role="button" tabindex="0" onclick="...">Submit</div>
39
+ ```
40
+
41
+ **Common ARIA patterns:**
42
+ - `aria-label`: Label for elements without visible text (icon buttons)
43
+ - `aria-labelledby`: Reference another element as label
44
+ - `aria-describedby`: Additional description (error messages, help text)
45
+ - `aria-expanded`: Toggle state for accordions, dropdowns
46
+ - `aria-live="polite"`: Announce dynamic content changes (toast, status)
47
+ - `aria-hidden="true"`: Hide decorative elements from screen readers
48
+ - `role="alert"`: Immediately announce urgent messages
49
+
50
+ **Dynamic content announcement:**
51
+ ```tsx
52
+ // Status messages read by screen reader
53
+ <div aria-live="polite" aria-atomic="true">
54
+ {submitStatus === 'success' && 'Form submitted successfully'}
55
+ {submitStatus === 'error' && 'Submission failed. Please try again.'}
56
+ </div>
57
+ ```
58
+
59
+ ## Color & Contrast
60
+
61
+ - Text contrast: minimum 4.5:1 ratio (3:1 for large text ≥ 24px)
62
+ - UI component contrast: minimum 3:1 against background
63
+ - Never rely on color alone to convey information — add icons, text, or patterns
64
+ - Test with color blindness simulators (Chrome DevTools → Rendering → Emulate vision deficiency)
65
+
66
+ ## Touch Targets
67
+
68
+ - Minimum 44x44px for all interactive elements on mobile
69
+ - Adequate spacing between targets (minimum 8px gap)
70
+ - Inline links within text paragraphs are exempt but should have generous padding
71
+
72
+ ## Testing
73
+
74
+ **Automated (catches ~30% of issues):**
75
+ - axe-core: `npm run test:a11y` or Storybook axe addon
76
+ - Lighthouse accessibility audit (target: 100 score)
77
+ - eslint-plugin-jsx-a11y for static analysis
78
+
79
+ **Manual (catches remaining ~70%):**
80
+ - **Keyboard test**: Unplug mouse, navigate entire feature with keyboard only
81
+ - **Screen reader test**: VoiceOver (Mac), NVDA (Windows), or TalkBack (Android)
82
+ - **Zoom test**: 200% browser zoom — no content clipped or overlapping
83
+ - **Reduced motion**: `prefers-reduced-motion` media query respected — no essential animations
84
+
85
+ ## Common Mistakes
86
+
87
+ - `<div onClick>` instead of `<button>` — div has no keyboard support, no role, no focus
88
+ - Placeholder text as the only label — disappears on input, not announced by all screen readers
89
+ - Auto-playing video/audio without controls or mute option
90
+ - Form errors only shown on submit — show inline on blur
91
+ - Modal without focus trap — user tabs into background content
92
+ - Image carousel without pause control and keyboard navigation
@@ -0,0 +1,87 @@
1
+ # Component Architecture
2
+
3
+ ## Props Interface Design
4
+
5
+ - Props interface is the component's contract. Design it like a public API:
6
+ - Use discriminated unions for variants: `type ButtonVariant = 'primary' | 'secondary' | 'ghost'` — not `isPrimary`, `isSecondary` booleans
7
+ - Required props first, optional with sensible defaults
8
+ - Callback props follow `onAction` naming: `onClick`, `onChange`, `onSubmit`
9
+ - Avoid `children` prop when the content structure is predictable — use named slots/props
10
+ - Use `React.forwardRef` if the component wraps a DOM element consumers may need to reference
11
+ - Spread remaining props onto the root element: `{...rest}` for flexibility (className, data-*, aria-*)
12
+
13
+ ## Component File Structure
14
+
15
+ ```
16
+ Button/
17
+ ├── Button.tsx # Component implementation
18
+ ├── Button.test.tsx # Tests (behavior-based, not snapshot)
19
+ ├── Button.stories.tsx # Storybook stories for all states
20
+ ├── Button.module.css # Styles (if not using Tailwind)
21
+ └── index.ts # Public export only — never re-export internals
22
+ ```
23
+
24
+ ## Component Layers — Enforce Separation
25
+
26
+ **Primitives** (design system atoms):
27
+ - Button, Input, Modal, Tooltip, Badge, Avatar
28
+ - No business logic. No API calls. No domain knowledge.
29
+ - Accept generic props. Fully configurable via props.
30
+
31
+ **Composites** (domain-agnostic patterns):
32
+ - SearchBar, DataTable, FormField, Pagination, FileUpload
33
+ - Combine primitives for reusable UI patterns
34
+ - Still no domain knowledge — works in any project
35
+
36
+ **Features** (domain-specific):
37
+ - UserProfile, InvoiceList, CheckoutForm, DashboardWidget
38
+ - Can fetch data, contain business logic
39
+ - Use primitives and composites internally
40
+
41
+ **Rules**:
42
+ - Primitives never import composites or features
43
+ - Composites never import features
44
+ - Features can import anything below them
45
+
46
+ ## Visual States — Every Component Must Handle
47
+
48
+ 1. **Default**: Normal interactive state
49
+ 2. **Loading**: Skeleton placeholder, not spinner (preserves layout, reduces CLS)
50
+ 3. **Error**: Inline error message with retry action. Not just red text — explain what went wrong.
51
+ 4. **Empty**: Meaningful empty state — illustration + call to action, not blank space
52
+ 5. **Disabled**: Visually distinct, not interactive, cursor: not-allowed, aria-disabled
53
+ 6. **Focused**: Visible focus ring (2px solid, high contrast). Never `outline: none` without replacement.
54
+ 7. **Hover**: Subtle visual feedback. Must not be the only way to discover functionality.
55
+
56
+ ## Composition Patterns
57
+
58
+ **Compound Components** (for complex UI with shared state):
59
+ ```tsx
60
+ <Select>
61
+ <Select.Trigger>Choose option</Select.Trigger>
62
+ <Select.Content>
63
+ <Select.Item value="a">Option A</Select.Item>
64
+ <Select.Item value="b">Option B</Select.Item>
65
+ </Select.Content>
66
+ </Select>
67
+ ```
68
+
69
+ **Render Props** (for customizable rendering):
70
+ ```tsx
71
+ <DataTable
72
+ data={users}
73
+ renderRow={(user) => <UserRow key={user.id} user={user} />}
74
+ />
75
+ ```
76
+
77
+ **Slot Props** (named content areas):
78
+ ```tsx
79
+ <Card
80
+ header={<h3>Title</h3>}
81
+ footer={<Button>Save</Button>}
82
+ >
83
+ Body content
84
+ </Card>
85
+ ```
86
+
87
+ Prefer these over single mega-component with 20+ props.
@@ -0,0 +1,89 @@
1
+ # CSS & Styling
2
+
3
+ ## Tailwind Conventions
4
+
5
+ - Tailwind is the default styling approach. Use utility classes directly in JSX.
6
+ - Use `@apply` sparingly — only in base component styles where utilities exceed 6 classes:
7
+ ```css
8
+ /* OK: Complex base style */
9
+ .btn-primary { @apply px-4 py-2 rounded-lg font-medium text-white bg-blue-600 hover:bg-blue-700 focus-visible:ring-2; }
10
+
11
+ /* BAD: Simple style that should stay as utilities */
12
+ .my-margin { @apply mt-4; }
13
+ ```
14
+ - **Never hardcode colors/spacing** — use Tailwind's design tokens:
15
+ ```tsx
16
+ // BAD
17
+ <div style={{ color: '#3B82F6', padding: '16px' }}>
18
+ // GOOD
19
+ <div className="text-blue-500 p-4">
20
+ ```
21
+
22
+ ## Design Tokens
23
+
24
+ All visual values come from the design system / Tailwind config:
25
+ - Colors: `text-primary`, `bg-surface`, `border-muted` — defined in `tailwind.config`
26
+ - Spacing: Tailwind's scale (4, 8, 12, 16, 20, 24, 32, 40, 48, 64px)
27
+ - Typography: `text-sm`, `text-base`, `text-lg` — consistent scale
28
+ - Shadows: `shadow-sm`, `shadow-md`, `shadow-lg` — predefined elevation
29
+ - Radii: `rounded`, `rounded-lg`, `rounded-full` — consistent corner rounding
30
+
31
+ ## Z-Index Scale
32
+
33
+ Define in Tailwind config, use semantic names:
34
+ ```javascript
35
+ zIndex: {
36
+ dropdown: '100',
37
+ sticky: '200',
38
+ overlay: '300',
39
+ modal: '400',
40
+ toast: '500',
41
+ tooltip: '600',
42
+ }
43
+ ```
44
+ **Never use arbitrary z-index** (`z-[9999]`). If you need a new level, add it to the scale.
45
+
46
+ ## Responsive Design
47
+
48
+ - **Mobile-first**: Write base styles for mobile, add `md:` and `lg:` for larger screens
49
+ - **Breakpoints**: `sm` (640px), `md` (768px), `lg` (1024px), `xl` (1280px), `2xl` (1536px)
50
+ - **Test at**: 320px (small mobile), 375px (iPhone), 768px (iPad), 1024px (laptop), 1440px (desktop)
51
+ - Use `clamp()` for fluid typography: `font-size: clamp(1rem, 2.5vw, 1.5rem)`
52
+ - No horizontal scrollbar at any viewport width
53
+
54
+ ## CSS Modules (if not using Tailwind)
55
+
56
+ - File naming: `Component.module.css`
57
+ - Class naming: BEM-like — `.card`, `.card__header`, `.card--highlighted`
58
+ - Import as object: `import styles from './Button.module.css'`
59
+ - Composition over nesting:
60
+ ```css
61
+ .button { /* base */ }
62
+ .primary { composes: button; /* extends */ }
63
+ ```
64
+
65
+ ## Dark Mode
66
+
67
+ - Use CSS variables for all colors:
68
+ ```css
69
+ :root { --bg-primary: #ffffff; --text-primary: #111827; }
70
+ .dark { --bg-primary: #111827; --text-primary: #f9fafb; }
71
+ ```
72
+ - Tailwind: `dark:bg-gray-900 dark:text-white`
73
+ - Test both modes for every component — screenshots in Storybook
74
+ - Respect `prefers-color-scheme` for default, allow user override
75
+
76
+ ## Animation
77
+
78
+ - Respect `prefers-reduced-motion`:
79
+ ```css
80
+ @media (prefers-reduced-motion: reduce) {
81
+ *, *::before, *::after {
82
+ animation-duration: 0.01ms !important;
83
+ transition-duration: 0.01ms !important;
84
+ }
85
+ }
86
+ ```
87
+ - Use CSS transitions for simple state changes (hover, focus, open/close)
88
+ - Use Framer Motion for complex animations (mount/unmount, layout, gestures)
89
+ - Animation should serve UX (guide attention, show relationships) — not decoration
@@ -0,0 +1,73 @@
1
+ # Forms
2
+
3
+ ## Stack: React Hook Form + Zod
4
+
5
+ Define the Zod schema first — it serves as both validation and TypeScript type:
6
+ ```typescript
7
+ const loginSchema = z.object({
8
+ email: z.string().email('Invalid email address'),
9
+ password: z.string().min(8, 'Password must be at least 8 characters'),
10
+ });
11
+
12
+ type LoginForm = z.infer<typeof loginSchema>;
13
+
14
+ const { register, handleSubmit, formState: { errors } } = useForm<LoginForm>({
15
+ resolver: zodResolver(loginSchema),
16
+ });
17
+ ```
18
+
19
+ ## Validation UX
20
+
21
+ - **Field-level**: Validate on blur (when user leaves the field). Show error immediately.
22
+ - **Form-level**: Validate on submit. Scroll to first error. Focus the error field.
23
+ - **Inline errors**: Show directly below the field, not in a toast or alert banner.
24
+ - **Error text**: Explain what's wrong AND how to fix it: "Password must be at least 8 characters" — not just "Invalid password".
25
+ - **Submit button**: Never disable for validation. Show errors instead. Disable only during submission (loading state).
26
+
27
+ ## Multi-step Forms
28
+
29
+ - Persist partial state to sessionStorage or URL params — users who navigate away should not lose data.
30
+ - Validate each step before proceeding to next.
31
+ - Show progress indicator (step 2 of 4).
32
+ - Allow navigation back to previous steps without losing data.
33
+ - Final step shows summary for review before submit.
34
+
35
+ ```typescript
36
+ // Persist form state to sessionStorage
37
+ const { watch, reset } = useForm({ defaultValues: loadFromSession() });
38
+
39
+ useEffect(() => {
40
+ const subscription = watch((data) => {
41
+ sessionStorage.setItem('checkout-form', JSON.stringify(data));
42
+ });
43
+ return () => subscription.unsubscribe();
44
+ }, [watch]);
45
+ ```
46
+
47
+ ## File Uploads
48
+
49
+ - Drag-and-drop zone with click-to-browse fallback
50
+ - Validate file type and size client-side before upload
51
+ - Show upload progress bar (not just spinner)
52
+ - Support multiple files if applicable
53
+ - Preview for images, file name + size for documents
54
+ - Cancel upload action
55
+
56
+ ## Error Handling
57
+
58
+ - Network error: "Connection failed. Check your internet and try again." + retry button
59
+ - Server validation error (422): Map field errors to inline messages
60
+ - Timeout: "This is taking longer than expected. Please try again."
61
+ - Duplicate submission prevention: Disable submit on click, re-enable on error
62
+
63
+ ## Accessibility
64
+
65
+ - Every input has a visible `<label>` element (not just placeholder)
66
+ - Error messages linked with `aria-describedby`:
67
+ ```tsx
68
+ <input aria-describedby="email-error" aria-invalid={!!errors.email} />
69
+ {errors.email && <span id="email-error" role="alert">{errors.email.message}</span>}
70
+ ```
71
+ - Required fields marked with `aria-required="true"` and visible indicator
72
+ - Form submission result announced with `aria-live="polite"`
73
+ - Tab order follows visual layout — label → input → error → next field
@@ -0,0 +1,104 @@
1
+ # Frontend Performance
2
+
3
+ ## Core Web Vitals Targets
4
+
5
+ | Metric | Good | Needs Improvement | Poor |
6
+ |--------|------|-------------------|------|
7
+ | LCP (Largest Contentful Paint) | < 2.5s | 2.5s - 4s | > 4s |
8
+ | INP (Interaction to Next Paint) | < 200ms | 200ms - 500ms | > 500ms |
9
+ | CLS (Cumulative Layout Shift) | < 0.1 | 0.1 - 0.25 | > 0.25 |
10
+
11
+ ## Performance Audit Procedure
12
+
13
+ 1. **Measure baseline**: Lighthouse CI or `web-vitals` library. Record LCP, INP, CLS.
14
+ 2. **Bundle analysis**: `npx next build --analyze` or `npx source-map-explorer`. Flag deps > 50KB.
15
+ 3. **Render profiling**: React DevTools Profiler. Components re-rendering >2x per action = problem.
16
+ 4. **Network waterfall**: DevTools Network tab. Sequential requests → parallelize. Unnecessary client fetches → move server-side.
17
+ 5. **Memory check**: DevTools Memory tab during navigation. Growing RSS = leak. Look for detached DOM, uncleaned listeners.
18
+ 6. **Fix → Re-measure → Compare** against baseline.
19
+
20
+ ## Code Splitting
21
+
22
+ - **Route-based** (minimum): Every route = separate chunk via `React.lazy()` + Suspense
23
+ - **Component-level**: Heavy widgets (charts, editors, maps) via `dynamic(() => import(...), { ssr: false })`
24
+ - **Conditional**: Features behind feature flags loaded only when enabled
25
+
26
+ ```typescript
27
+ // Route-level splitting
28
+ const Dashboard = lazy(() => import('./pages/Dashboard'));
29
+
30
+ // Component-level for heavy widgets
31
+ const Chart = dynamic(() => import('./components/Chart'), {
32
+ ssr: false,
33
+ loading: () => <ChartSkeleton />,
34
+ });
35
+ ```
36
+
37
+ ## Rendering Optimization
38
+
39
+ **When to use `useMemo` / `useCallback`:**
40
+ - Only when React DevTools Profiler shows a measurable problem (>16ms render)
41
+ - For expensive computations (sorting/filtering large arrays)
42
+ - For referential equality in dependency arrays of child components using `React.memo`
43
+ - **Never** prophylactically "just in case"
44
+
45
+ **Virtualization** — mandatory for lists > 50 items:
46
+ ```typescript
47
+ import { useVirtualizer } from '@tanstack/react-virtual';
48
+ // Renders only visible items + buffer. 10,000 items = ~20 DOM nodes.
49
+ ```
50
+
51
+ **Avoid layout thrashing:**
52
+ ```typescript
53
+ // BAD: Read-write-read-write cycle forces reflow each time
54
+ items.forEach(item => {
55
+ const height = item.offsetHeight; // Read → forces reflow
56
+ item.style.height = height + 10 + 'px'; // Write
57
+ });
58
+
59
+ // GOOD: Batch reads, then batch writes
60
+ const heights = items.map(item => item.offsetHeight);
61
+ items.forEach((item, i) => {
62
+ item.style.height = heights[i] + 10 + 'px';
63
+ });
64
+ ```
65
+
66
+ ## Images
67
+
68
+ - Always use framework `<Image>` component (Next.js, Nuxt, etc.)
69
+ - Set explicit `width` and `height` to prevent CLS
70
+ - Use `priority` only for above-the-fold hero images
71
+ - Lazy load all below-fold images (default behavior)
72
+ - Format: WebP/AVIF with JPEG fallback
73
+ - Responsive: use `sizes` attribute for art direction
74
+
75
+ ## Fonts
76
+
77
+ - Use `next/font` or `@fontsource` for self-hosting
78
+ - Preload only the weights/subsets you use (Latin: ~15KB vs All: ~100KB+)
79
+ - `font-display: swap` always — show fallback font immediately
80
+ - Limit to 2 font families max
81
+
82
+ ## Bundle Hygiene
83
+
84
+ - No dependency > 20KB gzipped without team discussion
85
+ - Check for duplicates: `npm ls <package>` — multiple versions = bundle bloat
86
+ - Import specific modules: `import { debounce } from 'lodash-es/debounce'` not `import _ from 'lodash'`
87
+ - Barrel files (`index.ts` re-exporting everything) kill tree-shaking — avoid in hot paths
88
+
89
+ ## Streaming & Suspense
90
+
91
+ ```tsx
92
+ // Progressive loading with Suspense boundaries
93
+ <Suspense fallback={<HeaderSkeleton />}>
94
+ <Header />
95
+ </Suspense>
96
+ <Suspense fallback={<ContentSkeleton />}>
97
+ <MainContent /> {/* Streams as data arrives */}
98
+ </Suspense>
99
+ <Suspense fallback={<SidebarSkeleton />}>
100
+ <Sidebar /> {/* Independent loading */}
101
+ </Suspense>
102
+ ```
103
+
104
+ Each Suspense boundary loads independently — user sees progressive content, not a blank page.
@@ -0,0 +1,51 @@
1
+ # Frontend Review Checklist
2
+
3
+ ### Component Design
4
+ - [ ] Props interface is minimal and hard to misuse (union types > boolean flags)
5
+ - [ ] Component has single responsibility — not mixing data fetching with presentation
6
+ - [ ] Ref forwarding implemented if component wraps a DOM element
7
+ - [ ] No barrel file re-exports that kill tree-shaking
8
+
9
+ ### Rendering & Performance
10
+ - [ ] No unnecessary re-renders — checked with React DevTools Profiler
11
+ - [ ] `useMemo`/`useCallback` used only with measured justification
12
+ - [ ] Heavy components (>50KB) are lazy loaded
13
+ - [ ] Lists with >50 items use virtualization
14
+ - [ ] Images use framework `<Image>` component with explicit dimensions
15
+ - [ ] No layout thrashing (DOM reads inside style-modifying loops)
16
+
17
+ ### Accessibility (WCAG 2.1 AA)
18
+ - [ ] All interactive elements reachable and operable via keyboard
19
+ - [ ] Focus management: logical order, modals trap focus, focus returns after close
20
+ - [ ] ARIA attributes correct: `role`, `aria-label`, `aria-expanded`, `aria-live`
21
+ - [ ] Color contrast meets 4.5:1 (text) / 3:1 (UI components)
22
+ - [ ] Touch targets minimum 44x44px on mobile
23
+ - [ ] Tested with screen reader or axe-core
24
+
25
+ ### States & Error Handling
26
+ - [ ] All async operations handle: loading (skeleton), error (message + retry), empty, success
27
+ - [ ] React Error Boundary wraps the feature section
28
+ - [ ] Race conditions handled: useEffect cleanup cancels in-flight requests
29
+ - [ ] Stale closures checked in async callbacks
30
+
31
+ ### Responsive & Visual
32
+ - [ ] Tested at 320px, 768px, 1024px, 1440px
33
+ - [ ] No horizontal scrollbar at any viewport
34
+ - [ ] Dark mode works (if supported)
35
+
36
+ ### Security
37
+ - [ ] No `dangerouslySetInnerHTML` without DOMPurify
38
+ - [ ] User-generated content escaped
39
+ - [ ] No sensitive data in URL params or localStorage
40
+ - [ ] External URLs validated — no open redirect vectors
41
+
42
+ ### Testing
43
+ - [ ] Tests query by role/label, not test ID
44
+ - [ ] Key user interactions and error cases covered
45
+ - [ ] No snapshot tests for component output
46
+ - [ ] Accessibility assertions included
47
+
48
+ ### Bundle
49
+ - [ ] No new dependency > 20KB gzipped without discussion
50
+ - [ ] No duplicate packages
51
+ - [ ] Specific imports (not barrel file imports)
@@ -0,0 +1,90 @@
1
+ # Frontend Security
2
+
3
+ ## XSS Prevention
4
+
5
+ **Never use `dangerouslySetInnerHTML` without sanitization:**
6
+ ```typescript
7
+ import DOMPurify from 'dompurify';
8
+
9
+ // GOOD: Sanitized
10
+ <div dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(userContent) }} />
11
+
12
+ // BAD: Raw user content
13
+ <div dangerouslySetInnerHTML={{ __html: userContent }} />
14
+ ```
15
+
16
+ **React auto-escapes JSX** — but watch for:
17
+ - `href={userInput}` — can execute `javascript:alert('xss')`. Validate URL scheme.
18
+ - `style={userControlledObject}` — can inject CSS expressions in older browsers.
19
+ - Template literals in `<script>` tags (SSR) — server-rendered user data must be escaped.
20
+
21
+ **URL validation:**
22
+ ```typescript
23
+ function isValidUrl(input: string): boolean {
24
+ try {
25
+ const url = new URL(input);
26
+ return ['http:', 'https:'].includes(url.protocol);
27
+ } catch {
28
+ return false;
29
+ }
30
+ }
31
+ ```
32
+
33
+ ## Authentication Token Handling
34
+
35
+ - Access tokens: store in memory (variable/React state). Lost on refresh = by design (use refresh flow).
36
+ - Refresh tokens: `httpOnly`, `Secure`, `SameSite=Strict` cookie. Never accessible to JavaScript.
37
+ - **Never store tokens in**: localStorage, sessionStorage, URL query params, cookies accessible to JS.
38
+ - Clear tokens on logout: revoke refresh token server-side, clear in-memory access token.
39
+
40
+ ## CSRF Protection
41
+
42
+ - All mutation requests (POST, PUT, DELETE) must include CSRF token
43
+ - Framework handles this — verify it's configured:
44
+ - Next.js: use `next-csrf` or custom middleware
45
+ - SPA: include token from `X-CSRF-Token` header or cookie
46
+ - Same-origin policy + `SameSite=Strict` cookies provide baseline protection
47
+
48
+ ## Content Security Policy (CSP)
49
+
50
+ Work with DevOps to set strict CSP headers:
51
+ ```
52
+ Content-Security-Policy:
53
+ default-src 'self';
54
+ script-src 'self' 'nonce-{random}';
55
+ style-src 'self' 'unsafe-inline'; /* Tailwind needs this */
56
+ img-src 'self' data: https:;
57
+ connect-src 'self' https://api.example.com;
58
+ frame-ancestors 'none';
59
+ ```
60
+
61
+ - Report violations to a monitoring endpoint: `report-uri /csp-report`
62
+ - Start in report-only mode, then enforce after fixing violations
63
+
64
+ ## Sensitive Data
65
+
66
+ - Never log PII (email, name, phone) to console in production
67
+ - Never put sensitive data in URL query params (visible in browser history, logs, analytics)
68
+ - Mask sensitive fields in error reports (Sentry: `beforeSend` hook)
69
+ - Clear sensitive form data from memory after submission
70
+
71
+ ## Third-party Scripts
72
+
73
+ - Audit all third-party scripts — each is an XSS vector
74
+ - Load analytics/tracking via tag manager, not inline scripts
75
+ - Use `integrity` attribute for CDN scripts (SRI — Subresource Integrity)
76
+ - Sandbox iframes: `sandbox="allow-scripts allow-same-origin"`
77
+
78
+ ## Open Redirect Prevention
79
+
80
+ ```typescript
81
+ // BAD: Redirect to user-controlled URL
82
+ const returnUrl = searchParams.get('returnUrl');
83
+ router.push(returnUrl); // Could be https://evil.com
84
+
85
+ // GOOD: Validate against allowed paths
86
+ const returnUrl = searchParams.get('returnUrl');
87
+ if (returnUrl?.startsWith('/') && !returnUrl.startsWith('//')) {
88
+ router.push(returnUrl); // Relative path only
89
+ }
90
+ ```