@famgia/omnify-laravel 0.0.118 → 0.0.120

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 (36) hide show
  1. package/dist/{chunk-3YANFHE5.js → chunk-NMX3TLZT.js} +35 -6
  2. package/dist/{chunk-3YANFHE5.js.map → chunk-NMX3TLZT.js.map} +1 -1
  3. package/dist/index.cjs +34 -5
  4. package/dist/index.cjs.map +1 -1
  5. package/dist/index.d.cts +5 -0
  6. package/dist/index.d.ts +5 -0
  7. package/dist/index.js +1 -1
  8. package/dist/plugin.cjs +34 -5
  9. package/dist/plugin.cjs.map +1 -1
  10. package/dist/plugin.js +1 -1
  11. package/package.json +4 -4
  12. package/stubs/ai-guides/claude-checklists/react.md.stub +108 -0
  13. package/stubs/ai-guides/claude-rules/laravel-controllers.md.stub +57 -0
  14. package/stubs/ai-guides/claude-rules/laravel-migrations.md.stub +47 -0
  15. package/stubs/ai-guides/claude-rules/laravel-tests.md.stub +52 -0
  16. package/stubs/ai-guides/claude-rules/naming.md.stub +5 -0
  17. package/stubs/ai-guides/claude-rules/performance.md.stub +5 -0
  18. package/stubs/ai-guides/claude-rules/react-components.md.stub +67 -0
  19. package/stubs/ai-guides/claude-rules/schema-yaml.md.stub +69 -0
  20. package/stubs/ai-guides/claude-rules/security.md.stub +5 -0
  21. package/stubs/ai-guides/cursor/omnify-schema.mdc.stub +339 -0
  22. package/stubs/ai-guides/cursor/react-design.mdc.stub +693 -0
  23. package/stubs/ai-guides/cursor/react-form.mdc.stub +277 -0
  24. package/stubs/ai-guides/cursor/react-services.mdc.stub +304 -0
  25. package/stubs/ai-guides/cursor/react.mdc.stub +336 -0
  26. package/stubs/ai-guides/cursor/schema-create.mdc.stub +344 -0
  27. package/stubs/ai-guides/react/README.md.stub +221 -0
  28. package/stubs/ai-guides/react/antd-guide.md.stub +457 -0
  29. package/stubs/ai-guides/react/checklist.md.stub +108 -0
  30. package/stubs/ai-guides/react/datetime-guide.md.stub +137 -0
  31. package/stubs/ai-guides/react/design-philosophy.md.stub +363 -0
  32. package/stubs/ai-guides/react/i18n-guide.md.stub +211 -0
  33. package/stubs/ai-guides/react/laravel-integration.md.stub +181 -0
  34. package/stubs/ai-guides/react/service-pattern.md.stub +180 -0
  35. package/stubs/ai-guides/react/tanstack-query.md.stub +339 -0
  36. package/stubs/ai-guides/react/types-guide.md.stub +671 -0
@@ -0,0 +1,221 @@
1
+ # Frontend Architecture Guide
2
+
3
+ > **Related docs:**
4
+ > - [Design Philosophy](./design-philosophy.md) ⭐ **Start here** - Architecture, principles
5
+ > - [Types Guide](./types-guide.md) - Where to define types
6
+ > - [Service Pattern](./service-pattern.md) - API services
7
+ > - [TanStack Query](./tanstack-query.md) - Data fetching
8
+ > - [Ant Design](./antd-guide.md) - UI components
9
+ > - [i18n](./i18n-guide.md) - Multi-language
10
+ > - [DateTime](./datetime-guide.md) - Day.js, UTC handling
11
+ > - [Laravel Integration](./laravel-integration.md) - Backend integration
12
+ > - [Checklists](./checklist.md) - Before commit, new resource
13
+
14
+ ## Overview
15
+
16
+ See [Design Philosophy](./design-philosophy.md) for architecture diagram and principles.
17
+
18
+ **Stack**: Next.js 16 + TypeScript + Ant Design 6 + TanStack Query + Axios
19
+
20
+ ---
21
+
22
+ ## Directory Structure
23
+
24
+ ```
25
+ frontend/src/
26
+ ├── app/ # Next.js App Router (Pages)
27
+ │ ├── layout.tsx # Root: Providers wrapper
28
+ │ ├── page.tsx # Public: Home page
29
+ │ │
30
+ │ ├── (auth)/ # Group: Auth pages (no layout)
31
+ │ │ ├── login/page.tsx
32
+ │ │ └── register/page.tsx
33
+ │ │
34
+ │ └── (dashboard)/ # Group: Protected pages
35
+ │ ├── layout.tsx # Shared: Sidebar + Header
36
+ │ ├── page.tsx # /dashboard
37
+ │ └── users/ # Resource: Users
38
+ │ ├── page.tsx # GET /users (List)
39
+ │ ├── new/page.tsx # POST /users (Create)
40
+ │ └── [id]/
41
+ │ ├── page.tsx # GET /users/:id (Show)
42
+ │ └── edit/page.tsx # PUT /users/:id (Edit)
43
+
44
+ ├── features/ # Feature-specific components & hooks
45
+ │ ├── users/ # User feature
46
+ │ │ ├── UserTable.tsx # Only used in users feature
47
+ │ │ ├── UserForm.tsx
48
+ │ │ └── useUserFilters.ts # Feature-specific hook
49
+ │ └── posts/
50
+ │ ├── PostCard.tsx
51
+ │ └── PostEditor.tsx
52
+
53
+ ├── components/ # SHARED components (2+ features)
54
+ │ ├── layouts/ # Layout wrappers
55
+ │ │ ├── DashboardLayout.tsx
56
+ │ │ └── AuthLayout.tsx
57
+ │ └── common/ # Reusable UI
58
+ │ ├── DataTable.tsx # Generic table
59
+ │ └── PageHeader.tsx
60
+
61
+ ├── services/ # API Service Layer (ALWAYS here)
62
+ │ ├── auth.ts # POST /login, /logout, /register
63
+ │ └── users.ts # CRUD /api/users
64
+
65
+ ├── hooks/ # SHARED hooks (2+ features)
66
+ │ ├── useAuth.ts # App-wide auth
67
+ │ └── useDebounce.ts # Utility hook
68
+
69
+ ├── lib/ # Core Infrastructure
70
+ │ ├── api.ts # Axios instance + interceptors
71
+ │ ├── query.tsx # QueryClient provider
72
+ │ ├── queryKeys.ts # Query key factory
73
+ │ └── dayjs.ts # Day.js config + utilities
74
+
75
+ ├── i18n/ # Internationalization
76
+ │ ├── config.ts # Locales config
77
+ │ ├── request.ts # Server-side locale detection
78
+ │ └── messages/ # Translation files
79
+ │ ├── ja.json
80
+ │ ├── en.json
81
+ │ └── vi.json
82
+
83
+ └── types/ # TypeScript Types
84
+ └── model/ # Omnify auto-generated types
85
+ ```
86
+
87
+ ---
88
+
89
+ ## When to Use Which Folder
90
+
91
+ ### Decision Rules
92
+
93
+ | Question | Answer | Location |
94
+ | ------------------------------------ | ----------- | --------------------- |
95
+ | Component used in how many features? | 1 feature | `features/{feature}/` |
96
+ | Component used in how many features? | 2+ features | `components/common/` |
97
+ | Is it a layout wrapper? | Yes | `components/layouts/` |
98
+ | Is it a service (API calls)? | Yes | `services/` (ALWAYS) |
99
+ | Hook used in how many features? | 1 feature | `features/{feature}/` |
100
+ | Hook used in how many features? | 2+ features | `hooks/` |
101
+
102
+ ### Flowchart
103
+
104
+ ```
105
+ ┌─────────────────────────────────────────────────────────┐
106
+ │ NEW COMPONENT │
107
+ └─────────────────────┬───────────────────────────────────┘
108
+
109
+ Used in how many features?
110
+
111
+ ┌─────────────┴─────────────┐
112
+ │ │
113
+ 1 feature 2+ features
114
+ │ │
115
+ ▼ ▼
116
+ features/{feature}/ components/common/
117
+ UserTable.tsx DataTable.tsx
118
+ ```
119
+
120
+ ```
121
+ ┌─────────────────────────────────────────────────────────┐
122
+ │ NEW HOOK │
123
+ └─────────────────────┬───────────────────────────────────┘
124
+
125
+ Used in how many features?
126
+
127
+ ┌─────────────┴─────────────┐
128
+ │ │
129
+ 1 feature 2+ features
130
+ │ │
131
+ ▼ ▼
132
+ features/{feature}/ hooks/
133
+ useUserFilters.ts useDebounce.ts
134
+ ```
135
+
136
+ ```
137
+ ┌─────────────────────────────────────────────────────────┐
138
+ │ NEW SERVICE │
139
+ └─────────────────────┬───────────────────────────────────┘
140
+
141
+ ALWAYS
142
+
143
+
144
+ services/
145
+ users.ts
146
+ ```
147
+
148
+ ### Examples
149
+
150
+ ```typescript
151
+ // ❌ WRONG: Service in features folder
152
+ features/users/services/users.ts
153
+
154
+ // ✅ CORRECT: Service always centralized
155
+ services/users.ts
156
+ ```
157
+
158
+ ```typescript
159
+ // ❌ WRONG: Feature-specific component in components/
160
+ components/users/UserTable.tsx // Only used in users feature
161
+
162
+ // ✅ CORRECT: Feature-specific in features/
163
+ features/users/UserTable.tsx
164
+ ```
165
+
166
+ ```typescript
167
+ // ❌ WRONG: Shared component in features/
168
+ features/users/DataTable.tsx // Used in users AND posts
169
+
170
+ // ✅ CORRECT: Shared in components/
171
+ components/common/DataTable.tsx
172
+ ```
173
+
174
+ ---
175
+
176
+ ## Naming Conventions
177
+
178
+ ### Files
179
+
180
+ | Type | Pattern | Example |
181
+ | --------- | ------------------------ | ------------------------------- |
182
+ | Component | PascalCase | `UserForm.tsx`, `DataTable.tsx` |
183
+ | Hook | camelCase + `use` prefix | `useAuth.ts`, `useUsers.ts` |
184
+ | Service | camelCase | `users.ts`, `auth.ts` |
185
+ | Utility | camelCase | `utils.ts`, `formatters.ts` |
186
+ | Type | camelCase or PascalCase | `types.ts`, `User.ts` |
187
+ | Page | lowercase | `page.tsx`, `layout.tsx` |
188
+
189
+ ### Code
190
+
191
+ | Type | Pattern | Example |
192
+ | -------------- | --------------------- | --------------------------- |
193
+ | Component | PascalCase | `function UserForm()` |
194
+ | Hook | camelCase + `use` | `function useAuth()` |
195
+ | Service object | camelCase + `Service` | `const userService = {}` |
196
+ | Interface | PascalCase | `interface User` |
197
+ | Type | PascalCase | `type UserFormData` |
198
+ | Constant | UPPER_SNAKE_CASE | `const API_TIMEOUT = 30000` |
199
+ | Function | camelCase | `function formatDate()` |
200
+ | Variable | camelCase | `const userData = ...` |
201
+
202
+ ---
203
+
204
+ ## Types
205
+
206
+ See [Types Guide](./types-guide.md) for complete type definition rules.
207
+
208
+ **Quick reference:**
209
+
210
+ | Type | Location |
211
+ | ------------------ | --------------------------------------- |
212
+ | Model (User, Post) | `@/types/model` (Omnify auto-generated) |
213
+ | Input types | Service file (colocated) |
214
+ | Props | Component file |
215
+ | API Response | `lib/api.ts` |
216
+
217
+ **Omnify files:**
218
+ - `base/`, `rules/`, `enum/` → ❌ DO NOT EDIT
219
+ - `User.ts` (root level) → ✅ CAN EDIT (extension)
220
+
221
+ See also: [Omnify TypeScript Guide](../omnify/typescript-guide.md)
@@ -0,0 +1,457 @@
1
+ # Ant Design Guide
2
+
3
+ > **Related:** [README](./README.md) | [i18n](./i18n-guide.md)
4
+
5
+ ## ⚠️ IMPORTANT: Use Ant Design First
6
+
7
+ **ALWAYS check if Ant Design has a component before creating your own.**
8
+
9
+ Ant Design provides 60+ components: https://ant.design/components/overview
10
+
11
+ ```typescript
12
+ // ✅ DO: Use Ant Design components
13
+ import { Table, Form, Input, Button, Modal, Card, Descriptions } from "antd";
14
+
15
+ // ❌ DON'T: Create custom components that Ant Design already has
16
+ // DON'T create: CustomTable, CustomModal, CustomForm, CustomButton
17
+ // DON'T create: DataGrid, Popup, FormInput
18
+
19
+ // ✅ DO: Extend Ant Design if needed
20
+ function UserTable(props: { users: User[] }) {
21
+ return <Table dataSource={props.users} columns={...} />; // Wraps AntD Table
22
+ }
23
+
24
+ // ❌ DON'T: Build from scratch
25
+ function UserTable(props: { users: User[] }) {
26
+ return <table><tbody>{users.map(...)}</tbody></table>; // WRONG!
27
+ }
28
+ ```
29
+
30
+ ---
31
+
32
+ ## ⚠️ No New Libraries Without Permission
33
+
34
+ **DO NOT install new npm packages without explicit user approval.**
35
+
36
+ ```bash
37
+ # ❌ DON'T: Install without asking
38
+ npm install lodash
39
+ npm install moment
40
+ npm install react-table
41
+
42
+ # ✅ DO: Ask first
43
+ "Do you want to install library X for Y?"
44
+ ```
45
+
46
+ **Already installed libraries (use these):**
47
+ - UI: `antd`, `@ant-design/icons`
48
+ - HTTP: `axios`
49
+ - State: `@tanstack/react-query`
50
+ - Styling: `tailwindcss`
51
+ - i18n: `next-intl`
52
+
53
+ ---
54
+
55
+ ## When to Create a Component
56
+
57
+ | Create Component | Don't Create |
58
+ | ------------------------------- | ----------------------------- |
59
+ | Used in 2+ places | Used only once |
60
+ | Has own state/logic (>50 lines) | Simple markup (<30 lines) |
61
+ | Needs unit testing | Trivial display |
62
+ | Complex props interface | Few inline props |
63
+ | **Ant Design doesn't have it** | **Ant Design already has it** |
64
+
65
+ ---
66
+
67
+ ## Container vs Presentational
68
+
69
+ ```typescript
70
+ // ============================================================================
71
+ // CONTAINER COMPONENT (Smart) - pages or complex components
72
+ // - Fetches data
73
+ // - Handles mutations
74
+ // - Contains business logic
75
+ // ============================================================================
76
+
77
+ // app/(dashboard)/users/page.tsx
78
+ "use client";
79
+
80
+ import { useState } from "react";
81
+ import { useQuery } from "@tanstack/react-query";
82
+ import { userService, UserListParams } from "@/services/users";
83
+ import { queryKeys } from "@/lib/queryKeys";
84
+ import { UserTable } from "@/components/tables/UserTable";
85
+
86
+ export default function UsersPage() {
87
+ const [filters, setFilters] = useState<UserListParams>({ page: 1 });
88
+
89
+ const { data, isLoading } = useQuery({
90
+ queryKey: queryKeys.users.list(filters),
91
+ queryFn: () => userService.list(filters),
92
+ });
93
+
94
+ return (
95
+ <UserTable
96
+ users={data?.data ?? []}
97
+ loading={isLoading}
98
+ pagination={data?.meta}
99
+ onPageChange={(page) => setFilters({ ...filters, page })}
100
+ />
101
+ );
102
+ }
103
+
104
+ // ============================================================================
105
+ // PRESENTATIONAL COMPONENT (Dumb) - reusable UI
106
+ // - Receives data via props
107
+ // - No data fetching
108
+ // - No business logic
109
+ // ============================================================================
110
+
111
+ // components/tables/UserTable.tsx
112
+ import { Table } from "antd";
113
+ import type { User } from "@/types/model";
114
+ import type { PaginatedResponse } from "@/lib/api";
115
+
116
+ interface UserTableProps {
117
+ users: User[];
118
+ loading: boolean;
119
+ pagination?: PaginatedResponse<User>["meta"];
120
+ onPageChange: (page: number) => void;
121
+ }
122
+
123
+ export function UserTable({ users, loading, pagination, onPageChange }: UserTableProps) {
124
+ return (
125
+ <Table
126
+ dataSource={users}
127
+ loading={loading}
128
+ rowKey="id"
129
+ pagination={{
130
+ current: pagination?.current_page,
131
+ total: pagination?.total,
132
+ onChange: onPageChange,
133
+ }}
134
+ columns={[
135
+ { title: "ID", dataIndex: "id" },
136
+ { title: "Name", dataIndex: "name" },
137
+ { title: "Email", dataIndex: "email" },
138
+ ]}
139
+ />
140
+ );
141
+ }
142
+ ```
143
+
144
+ ---
145
+
146
+ ## Form Pattern with Laravel Validation
147
+
148
+ ```typescript
149
+ "use client";
150
+
151
+ import { Form, Input, Button, message } from "antd";
152
+ import { useMutation, useQueryClient } from "@tanstack/react-query";
153
+ import { useTranslations } from "next-intl";
154
+ import { getFormErrors } from "@/lib/api";
155
+ import { queryKeys } from "@/lib/queryKeys";
156
+ import { userService } from "@/services/users";
157
+
158
+ export default function UserForm() {
159
+ const t = useTranslations();
160
+ const [form] = Form.useForm();
161
+ const queryClient = useQueryClient();
162
+
163
+ const mutation = useMutation({
164
+ mutationFn: userService.create,
165
+ onSuccess: () => {
166
+ queryClient.invalidateQueries({ queryKey: queryKeys.users.all });
167
+ message.success(t("messages.created"));
168
+ form.resetFields();
169
+ },
170
+ onError: (error) => {
171
+ // This maps Laravel's 422 { errors: { email: ["Already exists"] } }
172
+ // to Ant Design's form.setFields format
173
+ form.setFields(getFormErrors(error));
174
+ },
175
+ });
176
+
177
+ return (
178
+ <Form
179
+ form={form}
180
+ layout="vertical"
181
+ onFinish={(values) => mutation.mutate(values)}
182
+ >
183
+ <Form.Item
184
+ name="name"
185
+ label={t("common.name")}
186
+ rules={[{ required: true }]}
187
+ >
188
+ <Input />
189
+ </Form.Item>
190
+
191
+ <Form.Item
192
+ name="email"
193
+ label={t("auth.email")}
194
+ rules={[{ required: true }, { type: "email" }]}
195
+ >
196
+ <Input />
197
+ </Form.Item>
198
+
199
+ <Form.Item>
200
+ <Button
201
+ type="primary"
202
+ htmlType="submit"
203
+ loading={mutation.isPending}
204
+ >
205
+ {t("common.save")}
206
+ </Button>
207
+ </Form.Item>
208
+ </Form>
209
+ );
210
+ }
211
+ ```
212
+
213
+ ---
214
+
215
+ ## ⚠️ Ant Design 6+ Breaking Changes & Deprecated Props
216
+
217
+ > **CRITICAL**: Always use the latest prop names. Using deprecated props will show console warnings and may break in future versions.
218
+
219
+ ### Deprecated Props Reference Table
220
+
221
+ | Component | ❌ Deprecated | ✅ Use Instead | Warning Message |
222
+ | ------------ | -------------------------- | ----------------------- | -------------------------------------------------- |
223
+ | **Divider** | `orientation` | `titlePlacement` | `orientation` is used for direction, use `titlePlacement` |
224
+ | Modal | `visible` | `open` | |
225
+ | Drawer | `visible` | `open` | |
226
+ | Dropdown | `visible` | `open` | |
227
+ | Tooltip | `visible` | `open` | |
228
+ | Popover | `visible` | `open` | |
229
+ | Popconfirm | `visible` | `open` | |
230
+ | Select | `dropdownMatchSelectWidth` | `popupMatchSelectWidth` | |
231
+ | TreeSelect | `dropdownMatchSelectWidth` | `popupMatchSelectWidth` | |
232
+ | Cascader | `dropdownMatchSelectWidth` | `popupMatchSelectWidth` | |
233
+ | AutoComplete | `dropdownMatchSelectWidth` | `popupMatchSelectWidth` | |
234
+ | Table | `filterDropdownVisible` | `filterDropdownOpen` | |
235
+ | DatePicker | `dropdownClassName` | `popupClassName` | |
236
+ | TimePicker | `dropdownClassName` | `popupClassName` | |
237
+ | Mentions | `dropdownClassName` | `popupClassName` | |
238
+ | Tag | `closable` | `closeIcon={false}` | Use `closeIcon={false}` to hide close icon |
239
+ | Notification | `message` | `description` | Some API changes in v6 |
240
+
241
+ ```typescript
242
+ // ❌ DON'T: Use deprecated props (causes console warnings)
243
+ <Divider orientation="left">Title</Divider>
244
+ <Modal visible={isOpen}>
245
+ <Dropdown visible={show}>
246
+ <Select dropdownMatchSelectWidth={false}>
247
+
248
+ // ✅ DO: Use new props (Ant Design 6+)
249
+ <Divider titlePlacement="left">Title</Divider>
250
+ <Modal open={isOpen}>
251
+ <Dropdown open={show}>
252
+ <Select popupMatchSelectWidth={false}>
253
+ ```
254
+
255
+ ---
256
+
257
+ ## 🚨 Common Ant Design 6+ Mistakes
258
+
259
+ ### 1. Divider - `orientation` vs `titlePlacement`
260
+
261
+ ```typescript
262
+ // ❌ WRONG: This will show a deprecation warning!
263
+ <Divider orientation="left">Section Title</Divider>
264
+ // Warning: [antd: Divider] `orientation` is used for direction, please use `titlePlacement` replace this
265
+
266
+ // ✅ CORRECT: Use titlePlacement for title position
267
+ <Divider titlePlacement="left">Section Title</Divider>
268
+ <Divider titlePlacement="center">Section Title</Divider>
269
+ <Divider titlePlacement="right">Section Title</Divider>
270
+
271
+ // For horizontal/vertical dividers, use `type`:
272
+ <Divider type="horizontal" /> // default
273
+ <Divider type="vertical" />
274
+ ```
275
+
276
+ ### 2. Modal/Drawer - `visible` vs `open`
277
+
278
+ ```typescript
279
+ // ❌ WRONG
280
+ const [visible, setVisible] = useState(false);
281
+ <Modal visible={visible} onCancel={() => setVisible(false)}>
282
+
283
+ // ✅ CORRECT
284
+ const [open, setOpen] = useState(false);
285
+ <Modal open={open} onCancel={() => setOpen(false)}>
286
+ ```
287
+
288
+ ### 3. Form.Item - `dependencies` must be array
289
+
290
+ ```typescript
291
+ // ❌ WRONG: dependencies as string
292
+ <Form.Item dependencies="password">
293
+
294
+ // ✅ CORRECT: dependencies as array
295
+ <Form.Item dependencies={['password']}>
296
+ ```
297
+
298
+ ### 4. Table - Column `render` function signature
299
+
300
+ ```typescript
301
+ // ❌ WRONG: Using wrong parameter order
302
+ columns={[{
303
+ render: (record, text) => <span>{text}</span> // WRONG ORDER!
304
+ }]}
305
+
306
+ // ✅ CORRECT: (text, record, index)
307
+ columns={[{
308
+ render: (text, record, index) => <span>{text}</span>
309
+ }]}
310
+ ```
311
+
312
+ ### 5. Select/TreeSelect - Option rendering
313
+
314
+ ```typescript
315
+ // ❌ WRONG: Using children in v6+
316
+ <Select>
317
+ <Select.Option value="1">Option 1</Select.Option>
318
+ </Select>
319
+
320
+ // ✅ PREFERRED: Use options prop (better performance)
321
+ <Select options={[
322
+ { value: '1', label: 'Option 1' },
323
+ { value: '2', label: 'Option 2' },
324
+ ]} />
325
+ ```
326
+
327
+ ### 6. DatePicker - Dayjs instead of Moment
328
+
329
+ ```typescript
330
+ // ❌ WRONG: Ant Design 6+ uses dayjs, not moment
331
+ import moment from 'moment';
332
+ <DatePicker value={moment(date)} />
333
+
334
+ // ✅ CORRECT: Use dayjs
335
+ import dayjs from 'dayjs';
336
+ <DatePicker value={dayjs(date)} />
337
+ ```
338
+
339
+ ### 7. ConfigProvider - Theme customization
340
+
341
+ ```typescript
342
+ // ❌ WRONG: Old less variable approach
343
+ @primary-color: #1890ff;
344
+
345
+ // ✅ CORRECT: Use ConfigProvider theme token
346
+ <ConfigProvider
347
+ theme={{
348
+ token: {
349
+ colorPrimary: '#1890ff',
350
+ borderRadius: 6,
351
+ },
352
+ }}
353
+ >
354
+ <App />
355
+ </ConfigProvider>
356
+ ```
357
+
358
+ ### 8. App Component - message/notification/modal
359
+
360
+ ```typescript
361
+ // ❌ WRONG: Direct import (won't respect ConfigProvider)
362
+ import { message } from 'antd';
363
+ message.success('Done!');
364
+
365
+ // ✅ CORRECT: Use App.useApp() hook
366
+ import { App } from 'antd';
367
+
368
+ function MyComponent() {
369
+ const { message, notification, modal } = App.useApp();
370
+
371
+ const handleClick = () => {
372
+ message.success('Done!'); // Respects ConfigProvider theme
373
+ };
374
+ }
375
+
376
+ // Wrap your app with App component
377
+ <ConfigProvider theme={...}>
378
+ <App>
379
+ <YourApp />
380
+ </App>
381
+ </ConfigProvider>
382
+ ```
383
+
384
+ ### 9. Icons - Named imports required
385
+
386
+ ```typescript
387
+ // ❌ WRONG: Default import
388
+ import Icon from '@ant-design/icons';
389
+ <Icon type="user" />
390
+
391
+ // ✅ CORRECT: Named imports
392
+ import { UserOutlined, EditOutlined } from '@ant-design/icons';
393
+ <UserOutlined />
394
+ <EditOutlined />
395
+ ```
396
+
397
+ ### 10. Grid - `xs`, `sm`, etc. as objects
398
+
399
+ ```typescript
400
+ // ❌ CAREFUL: Mixing number and object syntax
401
+ <Col xs={24} sm={{ span: 12, offset: 6 }}>
402
+
403
+ // ✅ PREFERRED: Be consistent
404
+ <Col xs={{ span: 24 }} sm={{ span: 12, offset: 6 }}>
405
+ // OR
406
+ <Col xs={24} sm={12}>
407
+ ```
408
+
409
+ ---
410
+
411
+ ## Anti-Patterns
412
+
413
+ ```typescript
414
+ // ❌ Creating components that Ant Design already has
415
+ function CustomButton({ children }) { ... } // Use <Button> from antd
416
+ function CustomModal({ visible }) { ... } // Use <Modal> from antd
417
+ function CustomTable({ data }) { ... } // Use <Table> from antd
418
+ function DataGrid({ rows }) { ... } // Use <Table> from antd
419
+
420
+ // ❌ Installing libraries without permission
421
+ npm install lodash // Ask first!
422
+ npm install react-icons // Use @ant-design/icons
423
+ npm install styled-components // Use Tailwind CSS
424
+
425
+ // ❌ API call in component (bypass service layer)
426
+ function UserList() {
427
+ const { data } = useQuery({
428
+ queryKey: ["users"],
429
+ queryFn: () => axios.get("/api/users"), // WRONG: Use service
430
+ });
431
+ }
432
+
433
+ // ❌ Business logic in component
434
+ function UserList() {
435
+ const users = data?.filter(u => u.active).sort((a, b) => a.name > b.name);
436
+ // Move to service or utility function
437
+ }
438
+
439
+ // ❌ Hardcoded strings - use i18n
440
+ <Button>Save</Button> // WRONG
441
+ <Button>{t("common.save")}</Button> // CORRECT
442
+
443
+ // ❌ Multiple sources of truth
444
+ const [users, setUsers] = useState([]); // Local state
445
+ const { data } = useQuery({ ... }); // Server state
446
+ // Pick one: TanStack Query for server data
447
+
448
+ // ❌ Prop drilling
449
+ <Parent data={data}>
450
+ <Child data={data}>
451
+ <GrandChild data={data} /> // Use Context or pass minimal props
452
+ </Child>
453
+ </Parent>
454
+
455
+ // ❌ Giant components (>200 lines)
456
+ // Split into smaller components or extract hooks
457
+ ```