@nebulit/embuilder 0.1.40 → 0.1.41

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 (24) hide show
  1. package/package.json +1 -1
  2. package/templates/.claude/skills/sample-slices/templates/.slices/index.json +1 -1
  3. package/templates/.claude/skills/ui-analyze-slices/SKILL.md +102 -0
  4. package/templates/.claude/skills/ui-build-slice-ui/SKILL.md +228 -0
  5. package/templates/.claude/skills/ui-generate-api/SKILL.md +141 -0
  6. package/templates/.claude/skills/ui-generate-hook/SKILL.md +118 -0
  7. package/templates/.claude/skills/ui-generate-types/SKILL.md +223 -0
  8. package/templates/.claude/skills/ui-read-ui-prompts/SKILL.md +192 -0
  9. package/templates/.claude/skills/ui-scaffold-component/SKILL.md +274 -0
  10. package/templates/frontend/prompt.md +250 -90
  11. package/templates/.claude/skills/sample-slices/templates/Cart/additem/slice.json +0 -979
  12. package/templates/.claude/skills/sample-slices/templates/Cart/archiveitem/slice.json +0 -529
  13. package/templates/.claude/skills/sample-slices/templates/Cart/cartitems/slice.json +0 -1072
  14. package/templates/.claude/skills/sample-slices/templates/Cart/cartwithproducts/slice.json +0 -394
  15. package/templates/.claude/skills/sample-slices/templates/Cart/changedprices/slice.json +0 -88
  16. package/templates/.claude/skills/sample-slices/templates/Cart/changeinventory/slice.json +0 -264
  17. package/templates/.claude/skills/sample-slices/templates/Cart/changeprice/slice.json +0 -308
  18. package/templates/.claude/skills/sample-slices/templates/Cart/clearcart/slice.json +0 -358
  19. package/templates/.claude/skills/sample-slices/templates/Cart/inventories/slice.json +0 -203
  20. package/templates/.claude/skills/sample-slices/templates/Cart/publishcart/slice.json +0 -876
  21. package/templates/.claude/skills/sample-slices/templates/Cart/removeitem/slice.json +0 -560
  22. package/templates/.claude/skills/sample-slices/templates/Cart/submitcart/slice.json +0 -708
  23. package/templates/.claude/skills/sample-slices/templates/Cart/submittedcartdata/slice.json +0 -399
  24. package/templates/.claude/skills/sample-slices/templates/index.json +0 -108
@@ -0,0 +1,223 @@
1
+ ---
2
+ skill_name: ui-generate-types
3
+ description: Generate TypeScript interfaces from slice field definitions
4
+ version: 1.0.0
5
+ author: Frontend Development Team
6
+ tags: [ui, typescript, types, interfaces, codegen]
7
+ ---
8
+
9
+ # Type Generator Skill
10
+
11
+ Generate TypeScript interfaces from slice field definitions.
12
+
13
+ ## Instructions
14
+
15
+ You will be provided with:
16
+ - Slice JSON file path
17
+ - Entity name
18
+
19
+ Your task is to:
20
+
21
+ 1. **Read the slice JSON file** to understand:
22
+ - All fields and their types
23
+ - Required vs optional fields
24
+ - Field descriptions
25
+
26
+ 2. **Generate TypeScript interfaces**:
27
+ - **Entity interface**: Represents the domain object (for STATE_VIEW slices)
28
+ - **Params interface**: Represents parameters for commands (for STATE_CHANGE slices)
29
+
30
+ 3. **Map slice field types to TypeScript types**:
31
+ - String → `string`
32
+ - Int, Long, Double, Decimal → `number`
33
+ - Boolean → `boolean`
34
+ - Date, DateTime → `string` (ISO format)
35
+ - Time → `string`
36
+ - UUID → `string`
37
+ - Enum → `union type` or `enum`
38
+
39
+ 4. **Add interfaces to** `src/types/index.ts`
40
+
41
+ ## Type Mapping
42
+
43
+ | Slice Type | TypeScript Type | Notes |
44
+ |------------|----------------|-------|
45
+ | String | `string` | |
46
+ | Int | `number` | |
47
+ | Long | `number` | |
48
+ | Double | `number` | |
49
+ | Decimal | `number` | |
50
+ | Boolean | `boolean` | |
51
+ | Date | `string` | ISO date string (YYYY-MM-DD) |
52
+ | DateTime | `string` | ISO datetime string |
53
+ | Time | `string` | HH:mm format |
54
+ | UUID | `string` | |
55
+ | Enum | `'value1' \| 'value2'` | Union type |
56
+
57
+ ## Interface Templates
58
+
59
+ ### For STATE_VIEW (Entity Interface)
60
+
61
+ ```typescript
62
+ /**
63
+ * {Entity description}
64
+ */
65
+ export interface {Entity} {
66
+ /** Unique identifier */
67
+ {id_field}: string;
68
+
69
+ /** {Field description} */
70
+ {field_name}: {field_type};
71
+
72
+ /** Optional field */
73
+ {optional_field}?: {field_type};
74
+
75
+ /** Created timestamp */
76
+ created_at?: string;
77
+
78
+ /** Updated timestamp */
79
+ updated_at?: string;
80
+ }
81
+ ```
82
+
83
+ ### For STATE_CHANGE (Params Interface)
84
+
85
+ ```typescript
86
+ /**
87
+ * Parameters for {action} {entity}
88
+ */
89
+ export interface {Action}{Entity}Params {
90
+ /** {Field description} */
91
+ {field_name}: {field_type};
92
+
93
+ /** Optional parameter */
94
+ {optional_field}?: {field_type};
95
+ }
96
+ ```
97
+
98
+ ## Output Format
99
+
100
+ Provide:
101
+
102
+ 1. **TypeScript interfaces** formatted and documented
103
+ 2. **Location** where to add (typically `src/types/index.ts`)
104
+ 3. **Notes** on any special type considerations
105
+
106
+ Example:
107
+
108
+ ```
109
+ # Types Generated
110
+
111
+ ## Add to src/types/index.ts
112
+
113
+ /**
114
+ * Represents an event in the system
115
+ */
116
+ export interface Event {
117
+ /** Unique event identifier */
118
+ event_id: string;
119
+
120
+ /** Event name */
121
+ name: string;
122
+
123
+ /** Event date in YYYY-MM-DD format */
124
+ date: string;
125
+
126
+ /** Start time in HH:mm format */
127
+ start_time: string;
128
+
129
+ /** End time in HH:mm format */
130
+ end_time: string;
131
+
132
+ /** Number of persons */
133
+ persons: number;
134
+
135
+ /** Created timestamp */
136
+ created_at?: string;
137
+ }
138
+
139
+ /**
140
+ * Parameters for creating a new event
141
+ */
142
+ export interface CreateEventParams {
143
+ /** Event name (max 100 characters) */
144
+ name: string;
145
+
146
+ /** Event date in YYYY-MM-DD format */
147
+ date: string;
148
+
149
+ /** Start time in HH:mm format */
150
+ startTime: string;
151
+
152
+ /** End time in HH:mm format */
153
+ endTime: string;
154
+
155
+ /** Number of persons (must be positive) */
156
+ persons: number;
157
+ }
158
+
159
+ ## Notes
160
+
161
+ - Date fields use ISO string format for compatibility with HTML date inputs
162
+ - Time fields use HH:mm format
163
+ - Field names in params use camelCase (frontend convention)
164
+ - Field names in entity match database column names (snake_case)
165
+ ```
166
+
167
+ ## Special Cases
168
+
169
+ ### Optional Fields
170
+
171
+ Mark fields as optional with `?` when:
172
+ - The slice indicates the field is not required
173
+ - The field has a default value
174
+ - The field is generated (like timestamps, IDs)
175
+
176
+ ### Enums
177
+
178
+ For enum fields, create either:
179
+
180
+ **Option 1: Union Type (preferred for simple cases)**
181
+ ```typescript
182
+ export type EventStatus = 'pending' | 'confirmed' | 'cancelled';
183
+
184
+ export interface Event {
185
+ status: EventStatus;
186
+ }
187
+ ```
188
+
189
+ **Option 2: Enum (for complex cases with values)**
190
+ ```typescript
191
+ export enum EventStatus {
192
+ Pending = 'PENDING',
193
+ Confirmed = 'CONFIRMED',
194
+ Cancelled = 'CANCELLED',
195
+ }
196
+ ```
197
+
198
+ ### Nested Objects
199
+
200
+ If the slice includes nested structures:
201
+ ```typescript
202
+ export interface Address {
203
+ street: string;
204
+ city: string;
205
+ zipCode: string;
206
+ }
207
+
208
+ export interface Customer {
209
+ id: string;
210
+ name: string;
211
+ address: Address;
212
+ }
213
+ ```
214
+
215
+ ## Notes
216
+
217
+ - Always add JSDoc comments for interfaces and fields
218
+ - Include validation constraints in comments (max length, min/max values, etc.)
219
+ - Keep entity interfaces separate from params interfaces
220
+ - For params, use camelCase field names (frontend convention)
221
+ - For entities, match the database schema field names
222
+ - Check if types already exist before adding duplicates
223
+ - Export all types from `src/types/index.ts`
@@ -0,0 +1,192 @@
1
+ ---
2
+ skill_name: ui-read-ui-prompts
3
+ description: Find and parse UI prompts from slice definitions and related files
4
+ version: 1.0.0
5
+ author: Frontend Development Team
6
+ tags: [ui, prompts, requirements, design, validation]
7
+ ---
8
+
9
+ # UI Prompt Reader Skill
10
+
11
+ Find and parse UI prompts from slice definitions and related files.
12
+
13
+ ## Instructions
14
+
15
+ You will be provided with:
16
+ - Slice JSON file path
17
+ - Slice folder path (e.g., `/backend/src/slices/<slice name>/`)
18
+
19
+ Your task is to:
20
+
21
+ 1. **Read the slice JSON file** to extract:
22
+ - `codeGen.uiPrompts` array (if present)
23
+ - Any UI-related metadata in the slice definition
24
+
25
+ 2. **Check for `ui-prompt.md`** in the slice folder:
26
+ - Read the file if it exists
27
+ - Parse its content for design requirements, validation rules, and UX flows
28
+
29
+ 3. **Extract and organize UI requirements**:
30
+ - Design specifications (layout, styling, format)
31
+ - Validation rules (required fields, formats, constraints)
32
+ - UX flow instructions (user journey, interactions)
33
+ - Accessibility requirements
34
+ - Error handling specifications
35
+
36
+ 4. **Provide structured output** that can guide component implementation
37
+
38
+ ## UI Prompt Structure
39
+
40
+ UI prompts typically contain:
41
+
42
+ ### Design Specifications
43
+ - Layout preferences (grid, cards, table, list)
44
+ - Styling guidelines (colors, spacing, typography)
45
+ - Format requirements (date formats, number formats)
46
+ - Responsive design considerations
47
+
48
+ ### Validation Rules
49
+ - Required fields
50
+ - Field length constraints (min/max)
51
+ - Value constraints (min/max values, ranges)
52
+ - Format validations (email, phone, URL, patterns)
53
+ - Cross-field validations (end date > start date)
54
+
55
+ ### UX Flow
56
+ - User journey steps
57
+ - Interaction patterns (click → open dialog → fill form → submit → refresh)
58
+ - Success/error feedback (toasts, notifications, messages)
59
+ - Loading states
60
+ - Empty states
61
+
62
+ ### Accessibility
63
+ - ARIA labels
64
+ - Keyboard navigation
65
+ - Screen reader support
66
+ - Focus management
67
+
68
+ ## Output Format
69
+
70
+ Provide a structured summary:
71
+
72
+ ```
73
+ # UI Prompts Analysis
74
+
75
+ ## Source: {slice name}
76
+
77
+ ### From codeGen.uiPrompts:
78
+ 1. "{prompt text}"
79
+ 2. "{prompt text}"
80
+
81
+ ### From ui-prompt.md:
82
+
83
+ #### Design Specifications:
84
+ - Layout: {description}
85
+ - Styling: {description}
86
+ - Formats: {description}
87
+
88
+ #### Validation Rules:
89
+ | Field | Rule | Message |
90
+ |-------|------|---------|
91
+ | {field} | {rule} | {error message} |
92
+
93
+ #### UX Flow:
94
+ 1. {step}
95
+ 2. {step}
96
+ 3. {step}
97
+
98
+ #### Special Requirements:
99
+ - {requirement}
100
+ - {requirement}
101
+
102
+ ### Implementation Guidance:
103
+
104
+ Based on the prompts, the implementation should:
105
+ 1. {specific action based on prompt}
106
+ 2. {specific action based on prompt}
107
+
108
+ ### Code Snippets:
109
+
110
+ {Any specific code patterns or examples from the prompts}
111
+ ```
112
+
113
+ ## Example
114
+
115
+ For an events management slice with ui-prompt.md:
116
+
117
+ ```markdown
118
+ # Events Management UI
119
+
120
+ ## Design
121
+ - Use card layout for event list
122
+ - Display date in DD.MM.YYYY format
123
+ - Show time in 24-hour format (HH:mm)
124
+ - Use responsive 3-column grid on desktop, 1-column on mobile
125
+
126
+ ## Validation
127
+ - Name: Required, max 100 characters
128
+ - Date: Required, cannot be in the past
129
+ - Start time: Required
130
+ - End time: Required, must be after start time
131
+ - Persons: Required, must be > 0
132
+
133
+ ## UX Flow
134
+ 1. User clicks "Create Event" button
135
+ 2. Modal dialog opens with form
136
+ 3. User fills form fields
137
+ 4. On submit, show loading state
138
+ 5. On success, close dialog and show success toast
139
+ 6. Refresh event list automatically
140
+ 7. On error, show error message in dialog
141
+ ```
142
+
143
+ Your output would be:
144
+
145
+ ```
146
+ # UI Prompts Analysis
147
+
148
+ ## Source: Events Management
149
+
150
+ ### From ui-prompt.md:
151
+
152
+ #### Design Specifications:
153
+ - Layout: Card layout for event list with 3-column grid (desktop) / 1-column (mobile)
154
+ - Date Format: DD.MM.YYYY
155
+ - Time Format: 24-hour format (HH:mm)
156
+ - Component: Use Bulma cards and columns
157
+
158
+ #### Validation Rules:
159
+ | Field | Rule | Message |
160
+ |-------|------|---------|
161
+ | name | Required, max 100 chars | "Name is required (max 100 characters)" |
162
+ | date | Required, not in past | "Date cannot be in the past" |
163
+ | start_time | Required | "Start time is required" |
164
+ | end_time | Required, > start_time | "End time must be after start time" |
165
+ | persons | Required, > 0 | "Number of persons must be positive" |
166
+
167
+ #### UX Flow:
168
+ 1. Click "Create Event" button
169
+ 2. Modal dialog opens with form
170
+ 3. Fill form fields with validation
171
+ 4. Submit → Loading state
172
+ 5. Success → Close dialog + Success toast + Refresh list
173
+ 6. Error → Show error in dialog
174
+
175
+ ### Implementation Guidance:
176
+
177
+ 1. Use Bulma modal with `is-active` class for dialog
178
+ 2. Implement date formatting with `toLocaleDateString('de-DE')`
179
+ 3. Add form validation before submit
180
+ 4. Use `useMutation` onSuccess callback for toast and list refresh
181
+ 5. Implement responsive grid with `columns is-multiline` and `column is-one-third`
182
+ 6. Add cross-field validation for start/end time comparison
183
+ ```
184
+
185
+ ## Notes
186
+
187
+ - If no `ui-prompt.md` exists, rely solely on `codeGen.uiPrompts`
188
+ - If no UI prompts are found, provide general best practices
189
+ - Extract specific implementation details (formats, layouts, validations)
190
+ - Translate requirements into actionable coding tasks
191
+ - Identify any custom components or patterns needed
192
+ - Note any conflicts between prompts and suggest resolutions
@@ -0,0 +1,274 @@
1
+ ---
2
+ skill_name: ui-scaffold-component
3
+ description: Scaffold React components (List, Dialog, Page) from slice definitions using Bulma CSS
4
+ version: 1.0.0
5
+ author: Frontend Development Team
6
+ tags: [ui, components, react, bulma, scaffolding]
7
+ ---
8
+
9
+ # Component Scaffolder Skill
10
+
11
+ Scaffold React components (List, Dialog, Page) from slice definitions using Bulma CSS.
12
+
13
+ ## Instructions
14
+
15
+ You will be provided with:
16
+ - Slice JSON file paths (one or more in the same group)
17
+ - Component type to scaffold (List, Dialog, Page, or Auto)
18
+ - Domain/entity name
19
+
20
+ Your task is to:
21
+
22
+ 1. **Read all slice JSON files** to understand:
23
+ - Fields and their types
24
+ - Which slices are STATE_VIEW (for lists)
25
+ - Which slices are STATE_CHANGE (for forms/dialogs)
26
+ - UI prompts from `codeGen.uiPrompts`
27
+
28
+ 2. **Scaffold appropriate components**:
29
+ - **List Component**: For STATE_VIEW slices (displays data in cards/table)
30
+ - **Dialog Component**: For STATE_CHANGE slices (forms for create/update)
31
+ - **Page Component**: Combines list and dialogs into a complete page
32
+
33
+ 3. **Use Bulma CSS exclusively** for all styling:
34
+ - Layout: `columns`, `column`, `container`, `section`
35
+ - Components: `card`, `button`, `modal`, `box`, `table`
36
+ - Form elements: `field`, `control`, `label`, `input`, `select`, `textarea`
37
+ - Utilities: `is-primary`, `is-fullwidth`, `has-text-centered`, etc.
38
+
39
+ 4. **Integrate generated hooks**:
40
+ - Import and use query hooks in list components
41
+ - Import and use mutation hooks in dialog components
42
+ - Handle loading and error states
43
+
44
+ ## Component Templates
45
+
46
+ ### List Component (for STATE_VIEW)
47
+
48
+ ```typescript
49
+ import React from 'react';
50
+ import { use{Entity} } from '@/hooks/api';
51
+ import type { {Entity} } from '@/types';
52
+
53
+ export function {Entity}List() {
54
+ const { data: {entities}, isLoading, error } = use{Entity}();
55
+
56
+ if (isLoading) {
57
+ return <div className="has-text-centered p-6">Loading...</div>;
58
+ }
59
+
60
+ if (error) {
61
+ return (
62
+ <div className="notification is-danger">
63
+ Error loading {entities}: {error.message}
64
+ </div>
65
+ );
66
+ }
67
+
68
+ if (!{entities} || {entities}.length === 0) {
69
+ return (
70
+ <div className="notification is-info">
71
+ No {entities} found.
72
+ </div>
73
+ );
74
+ }
75
+
76
+ return (
77
+ <div className="columns is-multiline">
78
+ {{entities}.map(({entity}) => (
79
+ <div key={{entity}.id} className="column is-one-third">
80
+ <div className="card">
81
+ <div className="card-content">
82
+ <p className="title is-5">{{entity}.name}</p>
83
+ {/* Add more fields based on slice definition */}
84
+ </div>
85
+ </div>
86
+ </div>
87
+ ))}
88
+ </div>
89
+ );
90
+ }
91
+ ```
92
+
93
+ ### Dialog Component (for STATE_CHANGE)
94
+
95
+ ```typescript
96
+ import React, { useState } from 'react';
97
+ import { use{Action}{Entity} } from '@/hooks/api';
98
+ import type { {Action}{Entity}Params } from '@/types';
99
+
100
+ interface {Action}{Entity}DialogProps {
101
+ isOpen: boolean;
102
+ onClose: () => void;
103
+ }
104
+
105
+ export function {Action}{Entity}Dialog({ isOpen, onClose }: {Action}{Entity}DialogProps) {
106
+ const { mutate: {actionCamelCase}{Entity}, isPending } = use{Action}{Entity}();
107
+ const [formData, setFormData] = useState<{Action}{Entity}Params>({
108
+ // Initialize with default values based on slice fields
109
+ });
110
+
111
+ const handleSubmit = (e: React.FormEvent) => {
112
+ e.preventDefault();
113
+ {actionCamelCase}{Entity}(formData, {
114
+ onSuccess: () => {
115
+ onClose();
116
+ // Reset form or show success message
117
+ },
118
+ });
119
+ };
120
+
121
+ if (!isOpen) return null;
122
+
123
+ return (
124
+ <div className={`modal ${isOpen ? 'is-active' : ''}`}>
125
+ <div className="modal-background" onClick={onClose}></div>
126
+ <div className="modal-card">
127
+ <header className="modal-card-head">
128
+ <p className="modal-card-title">{Action} {Entity}</p>
129
+ <button className="delete" onClick={onClose}></button>
130
+ </header>
131
+ <section className="modal-card-body">
132
+ <form onSubmit={handleSubmit}>
133
+ {/* Generate form fields based on slice definition */}
134
+ <div className="field">
135
+ <label className="label">Field Name</label>
136
+ <div className="control">
137
+ <input
138
+ className="input"
139
+ type="text"
140
+ value={formData.fieldName}
141
+ onChange={(e) => setFormData({ ...formData, fieldName: e.target.value })}
142
+ required
143
+ />
144
+ </div>
145
+ </div>
146
+ </form>
147
+ </section>
148
+ <footer className="modal-card-foot">
149
+ <button
150
+ className="button is-primary"
151
+ onClick={handleSubmit}
152
+ disabled={isPending}
153
+ >
154
+ {isPending ? 'Saving...' : 'Save'}
155
+ </button>
156
+ <button className="button" onClick={onClose}>
157
+ Cancel
158
+ </button>
159
+ </footer>
160
+ </div>
161
+ </div>
162
+ );
163
+ }
164
+ ```
165
+
166
+ ### Page Component (Composition)
167
+
168
+ ```typescript
169
+ import React, { useState } from 'react';
170
+ import { {Entity}List } from './{Entity}List';
171
+ import { Create{Entity}Dialog } from './Create{Entity}Dialog';
172
+
173
+ export function {Entity}Page() {
174
+ const [isCreateDialogOpen, setIsCreateDialogOpen] = useState(false);
175
+
176
+ return (
177
+ <div className="container">
178
+ <section className="section">
179
+ <div className="level">
180
+ <div className="level-left">
181
+ <div className="level-item">
182
+ <h1 className="title">{Entities}</h1>
183
+ </div>
184
+ </div>
185
+ <div className="level-right">
186
+ <div className="level-item">
187
+ <button
188
+ className="button is-primary"
189
+ onClick={() => setIsCreateDialogOpen(true)}
190
+ >
191
+ Create {Entity}
192
+ </button>
193
+ </div>
194
+ </div>
195
+ </div>
196
+
197
+ <{Entity}List />
198
+
199
+ <Create{Entity}Dialog
200
+ isOpen={isCreateDialogOpen}
201
+ onClose={() => setIsCreateDialogOpen(false)}
202
+ />
203
+ </section>
204
+ </div>
205
+ );
206
+ }
207
+ ```
208
+
209
+ ## Form Field Generation
210
+
211
+ Based on field types in slice JSON, generate appropriate form inputs:
212
+
213
+ - **String**: `<input className="input" type="text" />`
214
+ - **Number**: `<input className="input" type="number" />`
215
+ - **Date**: `<input className="input" type="date" />`
216
+ - **Time**: `<input className="input" type="time" />`
217
+ - **Boolean**: `<input type="checkbox" className="checkbox" />`
218
+ - **Enum/Select**: `<div className="select"><select>...</select></div>`
219
+ - **Textarea**: `<textarea className="textarea" />`
220
+
221
+ ## Output Format
222
+
223
+ Provide:
224
+
225
+ 1. **Component files** with full paths
226
+ 2. **Import statements** needed
227
+ 3. **Integration notes** for adding to routes or parent components
228
+
229
+ Example:
230
+
231
+ ```
232
+ # Components Scaffolded
233
+
234
+ ## File: src/components/events/EventList.tsx
235
+
236
+ [Component code]
237
+
238
+ ## File: src/components/events/CreateEventDialog.tsx
239
+
240
+ [Component code]
241
+
242
+ ## File: src/components/events/EventsPage.tsx
243
+
244
+ [Component code]
245
+
246
+ ## Integration
247
+
248
+ Add to routes:
249
+ import { EventsPage } from '@/components/events/EventsPage';
250
+
251
+ // In router configuration:
252
+ { path: '/events', element: <EventsPage /> }
253
+ ```
254
+
255
+ ## Bulma CSS Guidelines
256
+
257
+ - Use `columns` and `column` for responsive grid layouts
258
+ - Use `card` for displaying entity items
259
+ - Use `modal` for dialogs (add `is-active` class when open)
260
+ - Use `button is-primary` for primary actions
261
+ - Use `notification` for messages (with `is-danger`, `is-info`, etc.)
262
+ - Use `field`, `control`, `label`, `input` for forms
263
+ - Use `level` for horizontal layouts with items on left/right
264
+ - Use `section` and `container` for page layout
265
+
266
+ ## Notes
267
+
268
+ - Always create components in `src/components/{domain}/` directory
269
+ - Use TypeScript with proper types imported from `@/types`
270
+ - Include loading and error states
271
+ - Handle form validation based on required fields
272
+ - Close dialogs on successful mutations
273
+ - Use semantic HTML elements
274
+ - Follow React best practices (controlled components, proper event handling)