create-tigra 3.0.5 → 3.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 (83) hide show
  1. package/README.md +4 -2
  2. package/bin/create-tigra.js +5 -19
  3. package/modules/email-verification/client/hooks/useVerification.ts +3 -3
  4. package/package.json +1 -1
  5. package/template/.agents/skills/security-audit/AI-AND-LLM.md +83 -0
  6. package/template/.agents/skills/security-audit/ATTACK-CLASSES.md +130 -0
  7. package/template/.agents/skills/security-audit/CLIENT-SIDE.md +83 -0
  8. package/template/.agents/skills/security-audit/CLOUD-AND-DEPLOYMENT.md +86 -0
  9. package/template/.agents/skills/security-audit/DATA-ISOLATION-AND-LIFECYCLE.md +84 -0
  10. package/template/.agents/skills/security-audit/DESKTOP-MOBILE-AND-LOCAL-IPC.md +89 -0
  11. package/template/.agents/skills/security-audit/HUNTING.md +251 -0
  12. package/template/.agents/skills/security-audit/LICENSE +21 -0
  13. package/template/.agents/skills/security-audit/MEMORY-SAFETY-AND-BINARY.md +101 -0
  14. package/template/.agents/skills/security-audit/PROTOCOLS-RPC-AND-MESSAGING.md +81 -0
  15. package/template/.agents/skills/security-audit/RECONNAISSANCE.md +156 -0
  16. package/template/.agents/skills/security-audit/RESOURCE-EXHAUSTION-AND-AVAILABILITY.md +78 -0
  17. package/template/.agents/skills/security-audit/SKILL.md +192 -0
  18. package/template/.agents/skills/security-audit/SOURCE.md +5 -0
  19. package/template/.agents/skills/security-audit/SUPPLY-CHAIN-AND-RELEASE.md +73 -0
  20. package/template/.agents/skills/security-audit/VALIDATION-AND-REPORTING.md +186 -0
  21. package/template/.agents/skills/security-audit/WEB-PROTOCOL-AND-AUTH.md +105 -0
  22. package/template/.agents/skills/security-audit/report-schema.json +461 -0
  23. package/template/.agents/skills/security-audit/validate-coverage-ledger.cjs +872 -0
  24. package/template/.agents/skills/security-audit/validate-coverage-ledger.test.cjs +740 -0
  25. package/template/.agents/skills/security-audit/validate-findings.cjs +773 -0
  26. package/template/.agents/skills/security-audit/validate-findings.test.cjs +652 -0
  27. package/template/AGENTS.md +45 -0
  28. package/template/client/AGENTS.md +22 -0
  29. package/template/client/package-lock.json +410 -324
  30. package/template/client/package.json +3 -3
  31. package/template/client/src/app/(auth)/layout.tsx +9 -0
  32. package/template/client/src/app/(auth)/loading.tsx +7 -0
  33. package/template/client/src/app/(main)/layout.tsx +11 -0
  34. package/template/client/src/app/(main)/loading.tsx +7 -0
  35. package/template/client/src/app/globals.css +4 -0
  36. package/template/client/src/app/loading.tsx +2 -6
  37. package/template/client/src/app/not-found.tsx +2 -3
  38. package/template/client/src/app/providers.tsx +6 -3
  39. package/template/client/src/components/common/AppLink.tsx +84 -0
  40. package/template/client/src/components/common/EmptyState.tsx +2 -2
  41. package/template/client/src/components/common/Pagination.tsx +3 -2
  42. package/template/client/src/components/common/RouteLoadingShell.tsx +21 -0
  43. package/template/client/src/components/common/SmoothNavigationProvider.tsx +151 -0
  44. package/template/client/src/components/layout/Header.tsx +12 -12
  45. package/template/client/src/features/admin/hooks/useAdminSessions.ts +2 -2
  46. package/template/client/src/features/admin/hooks/useAdminUsers.ts +3 -3
  47. package/template/client/src/features/auth/components/AuthInitializer.tsx +3 -2
  48. package/template/client/src/features/auth/components/LoginForm.tsx +3 -3
  49. package/template/client/src/features/auth/components/RegisterForm.tsx +3 -3
  50. package/template/client/src/features/auth/hooks/useAuth.ts +2 -2
  51. package/template/client/src/features/auth/hooks/usePasswordReset.ts +2 -2
  52. package/template/client/src/hooks/useAppRouter.ts +40 -0
  53. package/template/client/src/styles/themes/default.css +1 -1
  54. package/template/gitignore +0 -6
  55. package/template/server/AGENTS.md +28 -0
  56. package/template/server/package-lock.json +671 -522
  57. package/template/server/package.json +8 -8
  58. package/template/_claude/QUICK_REFERENCE.md +0 -193
  59. package/template/_claude/README.md +0 -53
  60. package/template/_claude/commands/create-client.md +0 -878
  61. package/template/_claude/commands/create-server.md +0 -388
  62. package/template/_claude/hooks/restrict-paths.sh +0 -51
  63. package/template/_claude/rules/client/01-project-structure.md +0 -147
  64. package/template/_claude/rules/client/02-components-and-types.md +0 -146
  65. package/template/_claude/rules/client/03-data-and-state.md +0 -195
  66. package/template/_claude/rules/client/04-design-system.md +0 -408
  67. package/template/_claude/rules/client/05-security.md +0 -55
  68. package/template/_claude/rules/client/06-ux-checklist.md +0 -111
  69. package/template/_claude/rules/client/07-deployment.md +0 -99
  70. package/template/_claude/rules/client/08-lockfile-cross-platform.md +0 -79
  71. package/template/_claude/rules/client/core.md +0 -46
  72. package/template/_claude/rules/global/completion-reports.md +0 -178
  73. package/template/_claude/rules/global/core.md +0 -104
  74. package/template/_claude/rules/global/investigation-before-conclusions.md +0 -57
  75. package/template/_claude/rules/server/core.md +0 -52
  76. package/template/_claude/rules/server/database.md +0 -124
  77. package/template/_claude/rules/server/deployment.md +0 -78
  78. package/template/_claude/rules/server/project-conventions.md +0 -254
  79. package/template/_claude/rules/server/response-handling.md +0 -144
  80. package/template/_claude/settings.json +0 -15
  81. package/template/_claude/skills/clean-ui/SKILL.md +0 -63
  82. package/template/_claude/skills/role/SKILL.md +0 -39
  83. package/template/_claude/skills/theme/SKILL.md +0 -109
@@ -1,146 +0,0 @@
1
- > **SCOPE**: These rules apply specifically to the **client** directory (Next.js App Router).
2
-
3
- # Components & Types
4
-
5
- ## Component Rules
6
-
7
- - **Server Components by default.** Only add `'use client'` for hooks, state, or event handlers.
8
- - **Max 250 lines** per component. Split if exceeded.
9
- - **Max 5 props.** Group related props into an object if more are needed.
10
- - **Max 3 levels** of JSX nesting. Extract sub-components if deeper.
11
- - **Internal ordering**: hooks → event handlers → effects → early returns → render.
12
- - **Handler naming**: `handle<Event>` for internal handlers, `on<Event>` for callback props.
13
- - **Wrap handlers in `useCallback`** when passed to child components (Client Components only).
14
- - **Use `useMemo`** for expensive computations in Client Components.
15
-
16
- ### Anti-patterns
17
-
18
- - Do NOT add `'use client'` to components that have no interactivity — keep them as Server Components.
19
- - Do NOT fetch data in Client Components when a Server Component can fetch it and pass as props.
20
- - Do NOT use inline styles. Use Tailwind + `cn()` for conditional classes.
21
-
22
- ---
23
-
24
- ## TypeScript Rules
25
-
26
- - **Strict mode ON.** No `any` — use `unknown` if the type is truly unknown.
27
- - **Explicit return types** on all functions.
28
- - **`interface`** for component props and object shapes. **`type`** for unions, intersections, utilities.
29
- - **Prefer string unions** over enums: `type UserRole = 'USER' | 'ADMIN'`
30
- - **Infer form types from Zod**: `type FormData = z.infer<typeof formSchema>`
31
- - **Always use `import type`** for type-only imports.
32
-
33
- ---
34
-
35
- ## API Response Types
36
-
37
- ```typescript
38
- // lib/api/api.types.ts
39
-
40
- export interface ApiResponse<T> {
41
- success: boolean;
42
- message: string;
43
- data: T;
44
- }
45
-
46
- export interface PaginatedApiResponse<T> {
47
- success: boolean;
48
- message: string;
49
- data: {
50
- items: T[];
51
- pagination: {
52
- page: number;
53
- limit: number;
54
- totalItems: number;
55
- totalPages: number;
56
- hasNextPage: boolean;
57
- hasPreviousPage: boolean;
58
- };
59
- };
60
- }
61
-
62
- export interface ApiError {
63
- success: false;
64
- error: {
65
- code: string;
66
- message: string;
67
- };
68
- }
69
-
70
- export interface PaginationParams {
71
- page?: number;
72
- limit?: number;
73
- }
74
- ```
75
-
76
- ---
77
-
78
- ## Domain Types
79
-
80
- ```typescript
81
- // features/auth/types/auth.types.ts
82
-
83
- export interface IUser {
84
- id: string;
85
- email: string;
86
- firstName: string;
87
- lastName: string;
88
- role: UserRole;
89
- isActive: boolean;
90
- avatarUrl: string | null;
91
- createdAt: string;
92
- updatedAt: string;
93
- }
94
-
95
- export type UserRole = 'USER' | 'ADMIN';
96
-
97
- export interface ILoginRequest {
98
- email: string;
99
- password: string;
100
- }
101
-
102
- export interface IRegisterRequest {
103
- email: string;
104
- password: string;
105
- firstName: string;
106
- lastName: string;
107
- }
108
-
109
- // No IAuthTokens — tokens are stored in httpOnly cookies, never exposed to JS.
110
-
111
- export interface IAuthState {
112
- user: IUser | null;
113
- isAuthenticated: boolean;
114
- isInitializing: boolean; // true until first getMe() resolves
115
- isLoggingOut: boolean; // true during logout API call
116
- }
117
- ```
118
-
119
- ```typescript
120
- // features/<domain>/types/<domain>.types.ts — example pattern
121
-
122
- export interface Item {
123
- id: string;
124
- ownerId: string;
125
- title: string;
126
- description: string | null;
127
- isActive: boolean;
128
- createdAt: string;
129
- updatedAt: string;
130
- }
131
-
132
- export interface CreateItemRequest {
133
- title: string;
134
- description?: string;
135
- }
136
-
137
- export interface UpdateItemRequest {
138
- title?: string;
139
- description?: string;
140
- }
141
-
142
- export interface ItemFilters {
143
- search?: string;
144
- sortBy?: 'createdAt' | 'title';
145
- }
146
- ```
@@ -1,195 +0,0 @@
1
- > **SCOPE**: These rules apply specifically to the **client** directory (Next.js App Router).
2
-
3
- # Data, State & API Integration
4
-
5
- ## State Decision Matrix
6
-
7
- | State Type | Tool | When |
8
- |---|---|---|
9
- | Server data (initial page load) | Server Components | SEO-critical, page-level data |
10
- | Server data (client-triggered) | React Query | User actions, real-time updates, mutations |
11
- | Global client state | Redux | Auth user + init/logout state — **nothing else** |
12
- | Local UI state | `useState` / `useReducer` | Modals, hover, form inputs |
13
- | URL-shareable state | `useSearchParams` | Filters, pagination, search query |
14
-
15
- ### Anti-patterns
16
-
17
- - **No server state in Redux.** Use Server Components or React Query.
18
- - **No UI state in Redux** (modals, loading). Use local state.
19
- - **Prefer Server Component fetch** over client-side `useQuery` when the data is available at page level.
20
-
21
- ---
22
-
23
- ## React Query Config
24
-
25
- Defaults in `app/providers.tsx`:
26
-
27
- ```typescript
28
- staleTime: 30 * 1000 // 30s — short enough that back-navigation refetches
29
- gcTime: 5 * 60 * 1000 // 5 min
30
- refetchOnWindowFocus: true // catch cross-tab edits
31
- refetchOnMount: true // always refetch stale data on mount
32
- retry: 1
33
- ```
34
-
35
- **Why these values matter**: With a long `staleTime` (e.g. 5 min) and `refetchOnWindowFocus: false`, navigating back to a list page after editing a record on another page will show stale data until the user hard-refreshes. Keep `staleTime` short and let invalidation + remount refetch do their job.
36
-
37
- ### Query Key Factory Pattern
38
-
39
- ```typescript
40
- export const itemKeys = {
41
- all: ['items'] as const,
42
- lists: () => [...itemKeys.all, 'list'] as const,
43
- list: (filters: ItemFilters) => [...itemKeys.lists(), filters] as const,
44
- details: () => [...itemKeys.all, 'detail'] as const,
45
- detail: (id: string) => [...itemKeys.details(), id] as const,
46
- };
47
- ```
48
-
49
- ### Mutations
50
-
51
- On success:
52
- 1. **`queryClient.invalidateQueries({ queryKey: ... })`** — refreshes any client-fetched data (React Query).
53
- 2. **`router.refresh()`** — refreshes any Server-Component-rendered data on the next route the user navigates to. Without this, the Next.js Router Cache will serve stale RSC payloads on back-navigation, and your edit will not appear until a hard refresh.
54
- 3. Show a toast.
55
- 4. Navigate if needed.
56
-
57
- On error: `toast.error(getErrorMessage(error))`.
58
-
59
- **Always call both `invalidateQueries` AND `router.refresh()`** unless you are 100% certain no Server Component on any reachable route reads the mutated data. The two caches are independent — invalidating one does not touch the other.
60
-
61
- ```typescript
62
- const router = useRouter();
63
- const queryClient = useQueryClient();
64
-
65
- const mutation = useMutation({
66
- mutationFn: (data) => itemService.updateItem(id, data),
67
- onSuccess: () => {
68
- queryClient.invalidateQueries({ queryKey: itemKeys.all });
69
- router.refresh();
70
- toast.success('Item updated');
71
- },
72
- onError: (error) => toast.error(getErrorMessage(error)),
73
- });
74
- ```
75
-
76
- ### Next.js Router Cache
77
-
78
- `next.config.ts` sets `experimental.staleTimes: { dynamic: 0, static: 30 }` to minimize client-side Router Cache reuse. `static: 30` is the **Next 16.2+ minimum** — the config schema rejects values below 30, and an invalid value is silently ignored (re-enabling the default Router Cache). `dynamic: 0` is what protects data pages. **Never raise these values above these minimums** — doing so reintroduces the back-navigation stale-data bug across every page that uses Server Components for data fetching.
79
-
80
- ---
81
-
82
- ## Redux
83
-
84
- **Scope**: Auth only. Single slice: `authSlice` with actions: `setUser`, `setInitialized`, `setLoggingOut`, `logout`.
85
-
86
- Typed hooks in `store/hooks.ts`: `useAppDispatch`, `useAppSelector`.
87
-
88
- State shape:
89
- ```typescript
90
- { user: IUser | null; isAuthenticated: boolean; isInitializing: boolean; isLoggingOut: boolean }
91
- ```
92
-
93
- **Not persisted to localStorage** — auth state is hydrated by `AuthInitializer`, which calls the `useCurrentUser()` hook. `useCurrentUser()` is a React Query wrapper around `authService.getMe()` that syncs the result into Redux via a side effect. Tokens are stored in httpOnly cookies (not accessible from JS).
94
-
95
- **Refreshing the current user**: any mutation that changes the logged-in user's own data (profile update, role change, avatar upload, email verification, subscription change, etc.) MUST invalidate the auth query so Redux picks up the new values:
96
-
97
- ```typescript
98
- import { authKeys } from '@/features/auth/hooks/useCurrentUser';
99
-
100
- queryClient.invalidateQueries({ queryKey: authKeys.me() });
101
- ```
102
-
103
- Without this, Redux will hold the stale snapshot from initial page load until the next window-focus refetch (30s staleTime), or until logout/hard refresh. Never write directly to the auth slice from outside the auth feature — always go through invalidation.
104
-
105
- ---
106
-
107
- ## Axios Config
108
-
109
- `lib/api/axios.config.ts` — singleton `apiClient`:
110
-
111
- - **Base URL**: `process.env.NEXT_PUBLIC_API_BASE_URL` (fallback `http://localhost:8000/api/v1`)
112
- - **Timeout**: 30s
113
- - **`withCredentials: true`**: Sends httpOnly cookies automatically with every request.
114
- - **No request interceptor** — cookies handle auth, no `Authorization` header needed.
115
- - **Response interceptor**: On 401, attempts token refresh via `/auth/refresh` (cookie sent automatically). Queues concurrent 401s to avoid multiple refresh attempts. If refresh fails, dispatches `logout()` and redirects to `/login`.
116
-
117
- ---
118
-
119
- ## Service Pattern
120
-
121
- Services are **classes**, singleton-exported, using `apiClient` and `API_ENDPOINTS`.
122
-
123
- ```typescript
124
- class ItemService {
125
- async getItems(params?: ItemFilters & PaginationParams): Promise<PaginatedData<Item>>
126
- async getItem(id: string): Promise<Item>
127
- async createItem(data: CreateItemRequest): Promise<Item>
128
- async updateItem(id: string, data: UpdateItemRequest): Promise<Item>
129
- async deleteItem(id: string): Promise<void>
130
- }
131
- export const itemService = new ItemService();
132
- ```
133
-
134
- Auth service methods: `register`, `login`, `logout`, `refreshToken`, `getMe`, `requestPasswordReset`, `resetPassword`.
135
-
136
- ---
137
-
138
- ## Error Handling
139
-
140
- ```typescript
141
- // lib/utils/error.ts
142
- export const getErrorMessage = (error: unknown): string => {
143
- // Checks: axios error → ApiError shape → network error → generic Error → fallback string
144
- };
145
- ```
146
-
147
- **Toast library**: `sonner`. Use `toast.success()`, `toast.error(getErrorMessage(error))`.
148
-
149
- ---
150
-
151
- ## Next.js Caching Defaults
152
-
153
- | Data type | Strategy | Example |
154
- |---|---|---|
155
- | General content | `next: { revalidate: 60 }` | Items list |
156
- | User-specific | `cache: 'no-store'` | User profile |
157
- | Static lookups | `cache: 'force-cache'` | Categories, settings |
158
-
159
- Use `revalidatePath()` / `revalidateTag()` in Server Actions after mutations.
160
-
161
- ---
162
-
163
- ## Forms
164
-
165
- **Approach**: Hybrid — React Hook Form + Zod for client-side validation, Server Action for submission.
166
-
167
- ### Password Schema Requirements
168
-
169
- ```typescript
170
- z.string()
171
- .min(8, 'Min 8 characters')
172
- .regex(/[A-Z]/, 'Must contain uppercase')
173
- .regex(/[a-z]/, 'Must contain lowercase')
174
- .regex(/[0-9]/, 'Must contain number')
175
- ```
176
-
177
- ### File Upload Validation
178
-
179
- - Allowed types: `image/jpeg`, `image/png`, `image/webp`
180
- - Max size: 5MB
181
- - Validate extension AND MIME type
182
-
183
- ### Form Rules
184
-
185
- - Show field-level errors below the field (red text + red border).
186
- - Disable submit button during submission.
187
- - Never clear the form on error — preserve user input.
188
- - Use `useFormStatus` for pending states in Server Action forms.
189
-
190
- ---
191
-
192
- ## Utility Defaults
193
-
194
- - **Default currency**: `USD` for `formatCurrency`.
195
- - **Date format**: `Intl.DateTimeFormat('en-US', { year: 'numeric', month: 'long', day: 'numeric' })`.