@adlas/create-app 1.0.52 → 1.0.53

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.
@@ -11,19 +11,25 @@ This document provides comprehensive guidelines for converting Figma designs to
11
11
  **❌ NEVER use screenshots** - Screenshots lose design data, measurements, and context
12
12
 
13
13
  **✅ ALWAYS use Figma MCP server with node links**:
14
+
14
15
  ```typescript
15
16
  // Use get_design_context tool with node-id from Figma URL
16
17
  // Example URL: https://figma.com/design/:fileKey/:fileName?node-id=8486-1580
17
18
  // Extract node-id: 8486-1580 → use as: "8486:1580"
18
19
 
19
- mcp__figma-dev-mode-mcp-server__get_design_context({
20
- nodeId: "8486:1580",
21
- clientLanguages: "typescript",
22
- clientFrameworks: "react,nextjs"
23
- })
20
+ mcp__figma -
21
+ dev -
22
+ mode -
23
+ mcp -
24
+ server__get_design_context({
25
+ nodeId: "8486:1580",
26
+ clientLanguages: "typescript",
27
+ clientFrameworks: "react,nextjs",
28
+ });
24
29
  ```
25
30
 
26
31
  **Benefits of using Figma MCP**:
32
+
27
33
  - ✅ Get exact measurements, colors, and spacing
28
34
  - ✅ Access design tokens and styles
29
35
  - ✅ See component structure and hierarchy
@@ -54,6 +60,7 @@ mcp__figma-dev-mode-mcp-server__get_design_context({
54
60
  ### CRITICAL: Component Styles Must Be Configured, Not Inline
55
61
 
56
62
  **❌ WRONG - Inline component styles**:
63
+
57
64
  ```tsx
58
65
  // DON'T: Apply component-specific styles inline via className
59
66
  <Button className="h-10 rounded-full bg-[#19ffa3] px-4 text-sm text-black">
@@ -70,6 +77,7 @@ mcp__figma-dev-mode-mcp-server__get_design_context({
70
77
  ```
71
78
 
72
79
  **✅ CORRECT - Use props and configured variants**:
80
+
73
81
  ```tsx
74
82
  // Step 1: Configure variants in component wrapper
75
83
  // File: src/components/ui/Button.tsx
@@ -117,6 +125,7 @@ import { Button } from '@/components/ui';
117
125
  ```
118
126
 
119
127
  **Component Style Rules**:
128
+
120
129
  - ✅ **Configure in wrapper**: All component-specific styles (height, padding, colors, text size)
121
130
  - ✅ **Set defaultVariants**: Define defaults in wrapper so you don't repeat them in usage
122
131
  - ✅ **Use theme colors**: `bg-primary`, `bg-secondary`, `bg-success`, `bg-danger`, `bg-warning` from hero.ts
@@ -129,6 +138,7 @@ import { Button } from '@/components/ui';
129
138
  - ❌ **NEVER repeat defaultVariants**: Don't specify `size="md"` if `md` is already the default
130
139
 
131
140
  **Color Usage Rules**:
141
+
132
142
  ```tsx
133
143
  // ✅ CORRECT - Use theme colors from hero.ts or globals.css
134
144
  color: {
@@ -150,6 +160,7 @@ secondary, success, danger, warning, default, foreground, background
150
160
  ```
151
161
 
152
162
  **What goes where**:
163
+
153
164
  ```tsx
154
165
  // In Button.tsx configuration:
155
166
  const Button = extendVariants(HerouiButton, {
@@ -194,6 +205,7 @@ import { Icon } from '@/components/ui';
194
205
  ### Data Must Be Mapped from Constants
195
206
 
196
207
  **❌ WRONG - Hardcoded data**:
208
+
197
209
  ```tsx
198
210
  <DropdownMenu>
199
211
  <DropdownItem key="option1">Option 1</DropdownItem>
@@ -203,16 +215,17 @@ import { Icon } from '@/components/ui';
203
215
  ```
204
216
 
205
217
  **✅ CORRECT - Map from constants**:
218
+
206
219
  ```tsx
207
220
  // File: src/config/menuOptions.ts
208
221
  export const productMenuItems = [
209
- { key: 'analytics', labelKey: 'product.analytics', href: '/analytics' },
210
- { key: 'insights', labelKey: 'product.insights', href: '/insights' },
211
- { key: 'reports', labelKey: 'product.reports', href: '/reports' },
222
+ { key: "analytics", labelKey: "product.analytics", href: "/analytics" },
223
+ { key: "insights", labelKey: "product.insights", href: "/insights" },
224
+ { key: "reports", labelKey: "product.reports", href: "/reports" },
212
225
  ];
213
226
 
214
227
  // Usage:
215
- import { productMenuItems } from '@/config/menuOptions';
228
+ import { productMenuItems } from "@/config/menuOptions";
216
229
 
217
230
  <DropdownMenu>
218
231
  {productMenuItems.map((item) => (
@@ -220,7 +233,7 @@ import { productMenuItems } from '@/config/menuOptions';
220
233
  {t(item.labelKey)}
221
234
  </DropdownItem>
222
235
  ))}
223
- </DropdownMenu>
236
+ </DropdownMenu>;
224
237
  ```
225
238
 
226
239
  ---
@@ -228,11 +241,14 @@ import { productMenuItems } from '@/config/menuOptions';
228
241
  ## 🎨 Component Priority & Usage Strategy
229
242
 
230
243
  ### 1. Check HeroUI First
244
+
231
245
  Before creating ANY component, check if HeroUI provides it:
246
+
232
247
  - **HeroUI Documentation**: https://heroui.com/docs/components
233
248
  - **HeroUI Figma Kit**: https://www.figma.com/design/kFGcjHsNKZx7zh2NxEJXYt/HeroUI-Figma-Kit--Community---Community-
234
249
 
235
250
  ### 2. Component Selection Flow
251
+
236
252
  ```
237
253
  1. Does HeroUI have this component?
238
254
  → YES: Use HeroUI component (via @/components/ui wrapper if exists)
@@ -248,6 +264,7 @@ Before creating ANY component, check if HeroUI provides it:
248
264
  ```
249
265
 
250
266
  ### 3. Example Decision Tree
267
+
251
268
  ```tsx
252
269
  // Need a Button?
253
270
  import { Button } from '@/components/ui'; // ✅ Use HeroUI Button wrapper
@@ -266,10 +283,12 @@ import { Input } from '@/components/ui'; // ✅ Use HeroUI Input wrapper
266
283
  ## 📁 Project Structure
267
284
 
268
285
  ### Pages Location
286
+
269
287
  - **With i18n**: `src/app/[locale]/(route-group)/page.tsx`
270
288
  - **Without i18n**: `src/app/(route-group)/page.tsx`
271
289
 
272
290
  ### Components Location
291
+
273
292
  ```
274
293
  src/components/
275
294
  ├── ui/ # Reusable UI components (HeroUI wrappers)
@@ -279,6 +298,7 @@ src/components/
279
298
  ```
280
299
 
281
300
  ### Styling
301
+
282
302
  - **Global styles**: `src/styles/globals.css`
283
303
  - **Theme config**: `src/styles/hero.ts`
284
304
  - **Approach**: Tailwind CSS utility classes ONLY
@@ -291,6 +311,7 @@ src/components/
291
311
  ### Navigation Components
292
312
 
293
313
  #### Navbar (HeroUI)
314
+
294
315
  **CRITICAL**: Always use HeroUI Navbar component for navigation bars:
295
316
 
296
317
  ```tsx
@@ -302,8 +323,8 @@ import {
302
323
  NavbarMenu,
303
324
  NavbarMenuItem,
304
325
  NavbarMenuToggle,
305
- } from '@heroui/react';
306
- import { Button } from '@/components/ui';
326
+ } from "@heroui/react";
327
+ import { Button } from "@/components/ui";
307
328
 
308
329
  <Navbar maxWidth="full" className="bg-black border-b-2">
309
330
  {/* Logo */}
@@ -314,14 +335,16 @@ import { Button } from '@/components/ui';
314
335
  {/* Desktop Menu */}
315
336
  <NavbarContent className="hidden lg:flex" justify="center">
316
337
  <NavbarItem>
317
- <Button variant="light">Menu Item</Button> {/* size="md" omitted - it's default */}
338
+ <Button variant="light">Menu Item</Button>{" "}
339
+ {/* size="md" omitted - it's default */}
318
340
  </NavbarItem>
319
341
  </NavbarContent>
320
342
 
321
343
  {/* CTA */}
322
344
  <NavbarContent className="hidden lg:flex" justify="end">
323
345
  <NavbarItem>
324
- <Button color="primary">CTA</Button> {/* size="md" omitted - it's default */}
346
+ <Button color="primary">CTA</Button>{" "}
347
+ {/* size="md" omitted - it's default */}
325
348
  </NavbarItem>
326
349
  </NavbarContent>
327
350
 
@@ -331,13 +354,16 @@ import { Button } from '@/components/ui';
331
354
  {/* Mobile Menu */}
332
355
  <NavbarMenu>
333
356
  <NavbarMenuItem>
334
- <Button variant="light" fullWidth>Menu Item</Button>
357
+ <Button variant="light" fullWidth>
358
+ Menu Item
359
+ </Button>
335
360
  </NavbarMenuItem>
336
361
  </NavbarMenu>
337
- </Navbar>
362
+ </Navbar>;
338
363
  ```
339
364
 
340
365
  **Key Points**:
366
+
341
367
  - ✅ Use `Navbar` from `@heroui/react`
342
368
  - ✅ Use `Button` from `@/components/ui` for menu items
343
369
  - ✅ Use props (`color`, `size`, `variant`) NOT className for styles
@@ -345,48 +371,128 @@ import { Button } from '@/components/ui';
345
371
  - ❌ DON'T use custom `<header>` or `<nav>` tags
346
372
 
347
373
  #### Dropdown Menus in Navbar
374
+
348
375
  **CRITICAL**: Always use HeroUI Dropdown components for dropdown menus:
349
376
 
377
+ ⚠️ **IMPORTANT - Dropdown Styling Must Match Figma Design Exactly**:
378
+
379
+ HeroUI Dropdown components have default styles that often DON'T match Figma designs. You MUST:
380
+
381
+ 1. ✅ Get design context from Figma using `get_design_context` tool
382
+ 2. ✅ Check exact colors, spacing, layout, borders from the design
383
+ 3. ✅ Use `classNames` prop to override default styles
384
+ 4. ✅ Pay attention to: background color, text color, borders, spacing, grid layout
385
+ 5. ❌ Don't assume default HeroUI styles will match the design
386
+
387
+ **Common Dropdown Styling Issues**:
388
+
389
+ - Default dropdown has light background, design might use dark background
390
+ - Default text color might be wrong (e.g., white text on white background)
391
+ - Default spacing (gaps, padding) rarely matches Figma exactly
392
+ - Grid layout for multi-column dropdowns needs explicit configuration
393
+ - Section headings need specific color/size overrides
394
+
350
395
  ```tsx
351
396
  import {
352
397
  Dropdown,
353
398
  DropdownTrigger,
354
399
  DropdownMenu,
355
400
  DropdownItem,
401
+ DropdownSection, // For grouped items
356
402
  } from '@heroui/react';
357
403
  import { Button, Icon } from '@/components/ui';
358
404
 
359
- // Dropdown with menu items from config
360
- {item.hasDropdown && item.items && item.items.length > 0 ? (
361
- <Dropdown>
362
- <DropdownTrigger>
363
- <Button
364
- variant="light"
365
- endContent={<Icon name="ChevronDownIcon" className="size-5" />}
366
- >
367
- {t(item.labelKey)}
368
- </Button>
369
- </DropdownTrigger>
370
- <DropdownMenu aria-label={t(item.labelKey)}>
371
- {item.items.map(subItem => (
372
- <DropdownItem key={subItem.key} href={subItem.href}>
405
+ // WRONG - Using defaults without checking Figma design
406
+ <Dropdown>
407
+ <DropdownTrigger>
408
+ <Button variant="light" endContent={<Icon name="ChevronDownIcon" />}>
409
+ {t(item.labelKey)}
410
+ </Button>
411
+ </DropdownTrigger>
412
+ <DropdownMenu>
413
+ {item.items.map(subItem => (
414
+ <DropdownItem key={subItem.key} href={subItem.href}>
415
+ {t(subItem.labelKey)}
416
+ </DropdownItem>
417
+ ))}
418
+ </DropdownMenu>
419
+ </Dropdown>
420
+
421
+ // ✅ CORRECT - Matching exact Figma design with classNames
422
+ <Dropdown
423
+ classNames={{
424
+ // Match Figma background, border, border-radius, padding
425
+ content: 'bg-[#0A0A0A] border border-[#1F1F1F] rounded-2xl p-8 min-w-[650px]',
426
+ }}
427
+ >
428
+ <DropdownTrigger>
429
+ <Button
430
+ variant="light"
431
+ endContent={<Icon name="ChevronDownIcon" className="size-4 text-white" />}
432
+ className="gap-1 text-base font-normal text-white"
433
+ >
434
+ {t(item.labelKey)}
435
+ </Button>
436
+ </DropdownTrigger>
437
+ <DropdownMenu
438
+ aria-label={t(item.labelKey)}
439
+ className="grid grid-cols-2 gap-8 p-0" // Two-column layout with exact spacing
440
+ itemClasses={{
441
+ base: 'rounded-none p-0 data-[hover=true]:bg-transparent',
442
+ title: 'text-lg font-semibold text-white', // Match Figma text color
443
+ description: 'text-sm text-[#999999] leading-relaxed',
444
+ }}
445
+ >
446
+ <DropdownSection
447
+ title="Core Features"
448
+ showDivider={false}
449
+ classNames={{
450
+ heading: 'text-xs font-medium text-[#666666] uppercase tracking-wider mb-6 px-0',
451
+ group: 'flex flex-col gap-8', // Match exact gap from Figma
452
+ }}
453
+ >
454
+ {coreItems.map(subItem => (
455
+ <DropdownItem
456
+ key={subItem.key}
457
+ description={t(subItem.descriptionKey)}
458
+ href={subItem.href}
459
+ classNames={{
460
+ base: 'flex gap-4 p-0 rounded-none data-[hover=true]:bg-transparent',
461
+ wrapper: 'flex flex-col gap-1',
462
+ }}
463
+ startContent={
464
+ subItem.iconName ? (
465
+ <div className="flex size-12 shrink-0 items-center justify-center rounded-lg border border-primary/40 bg-[#0D1F18] p-3">
466
+ <Icon name={subItem.iconName} className="size-6 text-primary" />
467
+ </div>
468
+ ) : null
469
+ }
470
+ >
373
471
  {t(subItem.labelKey)}
374
472
  </DropdownItem>
375
473
  ))}
376
- </DropdownMenu>
377
- </Dropdown>
378
- ) : (
379
- <Button variant="light">
380
- {t(item.labelKey)}
381
- </Button>
382
- )}
474
+ </DropdownSection>
475
+ </DropdownMenu>
476
+ </Dropdown>
383
477
  ```
384
478
 
479
+ **Dropdown Styling Checklist**:
480
+
481
+ - [ ] Check Figma design context for exact colors (background, text, borders)
482
+ - [ ] Verify spacing values (gap between items, padding, margins)
483
+ - [ ] Confirm layout structure (single column, two columns, grid)
484
+ - [ ] Match border radius, border width, and border colors
485
+ - [ ] Override default hover states if needed (`data-[hover=true]:bg-transparent`)
486
+ - [ ] Check section heading styles (color, size, spacing)
487
+ - [ ] Verify icon sizes and colors match design
488
+ - [ ] Test with actual content to ensure layout matches Figma
489
+
385
490
  **Example Menu Configuration** (`src/config/menuItems.ts`):
491
+
386
492
  ```tsx
387
493
  export type MenuItem = {
388
494
  key: string;
389
- labelKey: 'product' | 'useCases' | 'resources' | 'company' | 'pricing';
495
+ labelKey: "product" | "useCases" | "resources" | "company" | "pricing";
390
496
  href?: string;
391
497
  hasDropdown?: boolean;
392
498
  items?: Array<{
@@ -398,24 +504,37 @@ export type MenuItem = {
398
504
 
399
505
  export const navbarMenuItems: MenuItem[] = [
400
506
  {
401
- key: 'product',
402
- labelKey: 'product',
507
+ key: "product",
508
+ labelKey: "product",
403
509
  hasDropdown: true,
404
510
  items: [
405
- { key: 'analytics', labelKey: 'navbar.analytics', href: NAVIGATION_URLS.ROOT },
406
- { key: 'dashboard', labelKey: 'navbar.dashboard', href: NAVIGATION_URLS.ROOT },
407
- { key: 'reports', labelKey: 'navbar.reports', href: NAVIGATION_URLS.ROOT },
511
+ {
512
+ key: "analytics",
513
+ labelKey: "navbar.analytics",
514
+ href: NAVIGATION_URLS.ROOT,
515
+ },
516
+ {
517
+ key: "dashboard",
518
+ labelKey: "navbar.dashboard",
519
+ href: NAVIGATION_URLS.ROOT,
520
+ },
521
+ {
522
+ key: "reports",
523
+ labelKey: "navbar.reports",
524
+ href: NAVIGATION_URLS.ROOT,
525
+ },
408
526
  ],
409
527
  },
410
528
  {
411
- key: 'pricing',
412
- labelKey: 'pricing',
529
+ key: "pricing",
530
+ labelKey: "pricing",
413
531
  href: NAVIGATION_URLS.ROOT,
414
532
  },
415
533
  ];
416
534
  ```
417
535
 
418
536
  **Key Points**:
537
+
419
538
  - ✅ Always check `items && items.length > 0` before rendering dropdown
420
539
  - ✅ Use `Icon` component with proper name (e.g., `ChevronDownIcon`)
421
540
  - ✅ Use `endContent` prop for icons in buttons
@@ -425,9 +544,11 @@ export const navbarMenuItems: MenuItem[] = [
425
544
  - ❌ DON'T render dropdown without checking array exists
426
545
 
427
546
  ### Form Components
547
+
428
548
  All located in `src/components/ui/`:
429
549
 
430
550
  #### Input Fields
551
+
431
552
  ```tsx
432
553
  import { Input, PasswordInput, NumberInput, Textarea } from '@/components/ui';
433
554
 
@@ -463,6 +584,7 @@ import { Input, PasswordInput, NumberInput, Textarea } from '@/components/ui';
463
584
  ```
464
585
 
465
586
  #### Selection Components
587
+
466
588
  ```tsx
467
589
  import { Select, RadioGroup, Checkbox, Autocomplete } from '@/components/ui';
468
590
 
@@ -495,16 +617,18 @@ import { Select, RadioGroup, Checkbox, Autocomplete } from '@/components/ui';
495
617
  ```
496
618
 
497
619
  #### Date & Time
620
+
498
621
  ```tsx
499
- import { DatePicker } from '@/components/ui';
622
+ import { DatePicker } from "@/components/ui";
500
623
 
501
624
  <DatePicker
502
625
  label="Select Date"
503
626
  placeholderValue={new CalendarDate(2024, 1, 1)}
504
- />
627
+ />;
505
628
  ```
506
629
 
507
630
  #### Buttons
631
+
508
632
  ```tsx
509
633
  import { Button } from '@/components/ui';
510
634
 
@@ -522,6 +646,7 @@ import { Button } from '@/components/ui';
522
646
  ```
523
647
 
524
648
  #### Other Components
649
+
525
650
  ```tsx
526
651
  import { Modal, Chip, Breadcrumbs, Tabs, Icon } from '@/components/ui';
527
652
 
@@ -561,23 +686,27 @@ import { Modal, Chip, Breadcrumbs, Tabs, Icon } from '@/components/ui';
561
686
  **CRITICAL WORKFLOW**: Icons must follow this exact process:
562
687
 
563
688
  #### Step 1: Export SVG from Figma
689
+
564
690
  1. Select the icon in Figma design
565
691
  2. Export as SVG (not PNG/JPG)
566
692
  3. Download the SVG file
567
693
 
568
694
  #### Step 2: Place in Icons Folder
695
+
569
696
  ```bash
570
697
  # Place SVG file in src/assets/icons/
571
698
  mv downloaded-icon.svg src/assets/icons/icon-name.svg
572
699
  ```
573
700
 
574
701
  #### Step 3: Generate React Components
702
+
575
703
  ```bash
576
704
  # Run the icon generation script
577
705
  pnpm generate-icons
578
706
  ```
579
707
 
580
708
  This command will:
709
+
581
710
  - Convert all SVG files in `src/assets/icons/` to React components
582
711
  - Place them in `src/components/icons/`
583
712
  - **Automatically add "Icon" suffix** to all component names (configured in `svgr.config.mjs`)
@@ -585,9 +714,35 @@ This command will:
585
714
  - Update `src/components/icons/index.ts` with exports
586
715
 
587
716
  **Icon Naming Convention**:
588
- - SVG filename: `chevron-down.svg` or `chevron-down-icon.svg`
589
- - Generated component: `ChevronDownIcon.tsx` (Icon suffix added automatically)
590
- - The svgr config ensures ALL icons end with "Icon" suffix regardless of SVG filename
717
+
718
+ ⚠️ **IMPORTANT - Icon Naming Inconsistency**:
719
+ The `pnpm generate-icons` script has inconsistent behavior regarding the "Icon" suffix:
720
+
721
+ - Some generated files have "Icon" suffix: `ChevronDownIcon.tsx`, `CloseIcon.tsx`, `EyeIcon.tsx`
722
+ - Some generated files do NOT have "Icon" suffix: `Code.tsx`, `Bag.tsx`, `Magnifier.tsx`, `Stars.tsx`, `WidgetAdd.tsx`
723
+
724
+ **However, the exports in `src/components/icons/index.ts` ALWAYS add "Icon" suffix**:
725
+
726
+ ```typescript
727
+ // Even if the file is Code.tsx, the export is:
728
+ export { default as CodeIcon } from "./Code";
729
+ export { default as BagIcon } from "./Bag";
730
+ export { default as MagnifierIcon } from "./Magnifier";
731
+ ```
732
+
733
+ **What This Means For You**:
734
+
735
+ 1. ✅ **ALWAYS use the exported name WITH "Icon" suffix** when using the Icon component
736
+ 2. ✅ Check `src/components/icons/index.ts` to see the actual exported names
737
+ 3. ✅ The Icon component requires the exported name (e.g., `"CodeIcon"`, `"BagIcon"`)
738
+ 4. ❌ The filename doesn't matter - only the export name matters
739
+
740
+ **Example**:
741
+
742
+ - SVG filename: `code.svg` or `bag.svg`
743
+ - Generated component file: `Code.tsx` or `Bag.tsx` (may or may not have Icon suffix)
744
+ - Exported name: `CodeIcon` or `BagIcon` (ALWAYS has Icon suffix)
745
+ - Usage: `<Icon name="CodeIcon" />` or `<Icon name="BagIcon" />`
591
746
 
592
747
  #### Step 4: Use in Code
593
748
 
@@ -603,6 +758,7 @@ import { Icon } from '@/components/ui';
603
758
  ```
604
759
 
605
760
  **❌ WRONG USAGE - DO NOT import individual icon components**:
761
+
606
762
  ```tsx
607
763
  // ❌ WRONG - Don't import and use individual icon components
608
764
  import { ChevronDownIcon, CloseIcon } from '@/components/icons';
@@ -611,6 +767,7 @@ import { ChevronDownIcon, CloseIcon } from '@/components/icons';
611
767
  ```
612
768
 
613
769
  **Available Icons** (auto-generated):
770
+
614
771
  - ChevronDownIcon, ChevronRightIcon
615
772
  - CloseIcon, MenuIcon
616
773
  - EyeIcon, EyeSlashIcon
@@ -620,11 +777,13 @@ import { ChevronDownIcon, CloseIcon } from '@/components/icons';
620
777
  - And more...
621
778
 
622
779
  **Icon Names**:
780
+
623
781
  - Icon names are PascalCase with "Icon" suffix (e.g., `ChevronDownIcon`)
624
782
  - Generated from SVG filename: `chevron-down.svg` → component `ChevronDownIcon`
625
783
  - The Icon component uses the exact component name from `@/components/icons`
626
784
 
627
785
  **❌ DO NOT**:
786
+
628
787
  - Import individual icon components directly
629
788
  - Use kebab-case names (use `ChevronDownIcon` not `chevron-down`)
630
789
  - Use Lucide, Font Awesome, or other icon libraries
@@ -633,6 +792,7 @@ import { ChevronDownIcon, CloseIcon } from '@/components/icons';
633
792
  - Hardcode SVG paths directly in components
634
793
 
635
794
  **✅ DO**:
795
+
636
796
  - Always use `<Icon name="IconName" />` pattern with PascalCase
637
797
  - Always export from Figma as SVG
638
798
  - Use `pnpm generate-icons` to create components
@@ -645,6 +805,7 @@ import { ChevronDownIcon, CloseIcon } from '@/components/icons';
645
805
  #### Step 1: Check Existing Images First
646
806
 
647
807
  **BEFORE implementing or exporting from Figma**:
808
+
648
809
  1. Check `public/images/index.ts` to see if the image/logo already exists
649
810
  2. Check `public/images/logos/` directory for available logo files
650
811
  3. Only export from Figma if the asset doesn't exist
@@ -656,16 +817,19 @@ ls public/images/logos/
656
817
  ```
657
818
 
658
819
  **Why this matters**:
820
+
659
821
  - Avoid duplicate assets
660
822
  - User may have already exported the assets
661
823
  - Maintain consistency with existing naming conventions
662
824
 
663
825
  #### Step 2: Export from Figma (if needed)
826
+
664
827
  1. **For logos**: Export as SVG (preferred) or PNG if source is raster
665
828
  2. **For images**: Export as PNG, JPG, or WebP based on image type
666
829
  3. Use appropriate resolution (2x or 3x for retina displays)
667
830
 
668
831
  #### Step 3: Place in Public Folder
832
+
669
833
  ```bash
670
834
  # Place logo/image files in public/
671
835
  public/
@@ -691,36 +855,36 @@ public/
691
855
  */
692
856
 
693
857
  const LOGOS = {
694
- PRIMARY_CIRCLE: '/images/logos/logo-circle-primary.svg',
695
- SECONDARY_CIRCLE: '/images/logos/logo-circle-secondary.svg',
696
- FULL: '/images/logos/logo-full.svg',
697
- FULL_BLACK: '/images/logos/logo-full-black.svg',
698
- FULL_WHITE: '/images/logos/logo-full-white.svg',
699
- ICON: '/images/logos/logo-icon.svg',
858
+ PRIMARY_CIRCLE: "/images/logos/logo-circle-primary.svg",
859
+ SECONDARY_CIRCLE: "/images/logos/logo-circle-secondary.svg",
860
+ FULL: "/images/logos/logo-full.svg",
861
+ FULL_BLACK: "/images/logos/logo-full-black.svg",
862
+ FULL_WHITE: "/images/logos/logo-full-white.svg",
863
+ ICON: "/images/logos/logo-icon.svg",
700
864
  } as const;
701
865
 
702
866
  const AUTH = {
703
- LOGIN_BG: '/images/auth/login-background.jpg',
704
- SIGNUP_BG: '/images/auth/signup-background.jpg',
705
- RESET_PASSWORD: '/images/auth/reset-password.jpg',
867
+ LOGIN_BG: "/images/auth/login-background.jpg",
868
+ SIGNUP_BG: "/images/auth/signup-background.jpg",
869
+ RESET_PASSWORD: "/images/auth/reset-password.jpg",
706
870
  } as const;
707
871
 
708
872
  const WEBSITE = {
709
- HOME_HERO: '/images/website/home-hero.webp',
710
- HOME_NEWSLETTER: '/images/website/home-newsletter.webp',
711
- ABOUT_HEADER: '/images/website/about-header.jpg',
712
- CONTACT_MAP: '/images/website/contact-map.png',
873
+ HOME_HERO: "/images/website/home-hero.webp",
874
+ HOME_NEWSLETTER: "/images/website/home-newsletter.webp",
875
+ ABOUT_HEADER: "/images/website/about-header.jpg",
876
+ CONTACT_MAP: "/images/website/contact-map.png",
713
877
  } as const;
714
878
 
715
879
  const SERVICES = {
716
- HEADER: '/images/services/services-header.webp',
717
- FEATURE_1: '/images/services/feature-1.jpg',
718
- FEATURE_2: '/images/services/feature-2.jpg',
880
+ HEADER: "/images/services/services-header.webp",
881
+ FEATURE_1: "/images/services/feature-1.jpg",
882
+ FEATURE_2: "/images/services/feature-2.jpg",
719
883
  } as const;
720
884
 
721
885
  const PRODUCTS = {
722
- THUMBNAIL_DEFAULT: '/images/products/thumbnail-default.png',
723
- HERO: '/images/products/hero-banner.jpg',
886
+ THUMBNAIL_DEFAULT: "/images/products/thumbnail-default.png",
887
+ HERO: "/images/products/hero-banner.jpg",
724
888
  } as const;
725
889
 
726
890
  export const IMAGES = {
@@ -774,12 +938,14 @@ import Image from 'next/image';
774
938
  ```
775
939
 
776
940
  **Preference Order**:
941
+
777
942
  1. ✅ **SVG** - Best for logos, icons, and vector graphics (scalable, small file size)
778
943
  2. ✅ **WebP** - Modern format for photos (smaller than PNG/JPG)
779
944
  3. ✅ **PNG** - For images requiring transparency
780
945
  4. ✅ **JPG** - For photos without transparency
781
946
 
782
947
  **❌ DO NOT**:
948
+
783
949
  - Put images in `src/` folder
784
950
  - Import images as modules unless necessary
785
951
  - Use base64 encoded images inline
@@ -788,6 +954,7 @@ import Image from 'next/image';
788
954
  - Use hardcoded strings like `src="/images/logos/bina.png"` - Use `src={IMAGES.LOGOS.BINA}` instead
789
955
 
790
956
  **✅ DO**:
957
+
791
958
  - Always place in `public/` directory
792
959
  - Create centralized image constants file (src/config/images.ts)
793
960
  - Organize image paths by category (LOGOS, AUTH, WEBSITE, SERVICES)
@@ -804,27 +971,30 @@ import Image from 'next/image';
804
971
  ### CRITICAL: Use Theme Colors, NOT Custom Values
805
972
 
806
973
  **Colors are defined in two places**:
974
+
807
975
  1. **`src/styles/hero.ts`** - HeroUI theme colors (primary, secondary, etc.)
808
976
  2. **`src/styles/globals.css`** - Additional custom theme colors
809
977
 
810
978
  ### Available Theme Colors
811
979
 
812
980
  #### From hero.ts (Primary Color Palette):
981
+
813
982
  ```typescript
814
983
  // Primary green shades (defined in hero.ts)
815
- primary-50 // #E6FFF0 (lightest)
816
- primary-100 // #CBFFE0
817
- primary-200 // #AEFFD1
818
- primary-300 // #8EFFC2
819
- primary-400 // #66FFB2
820
- primary-500 // #19FFA3 (default primary)
821
- primary-600 // #25C780
822
- primary-700 // #26915F
823
- primary-800 // #215F40
824
- primary-900 // #173123 (darkest)
984
+ primary - 50; // #E6FFF0 (lightest)
985
+ primary - 100; // #CBFFE0
986
+ primary - 200; // #AEFFD1
987
+ primary - 300; // #8EFFC2
988
+ primary - 400; // #66FFB2
989
+ primary - 500; // #19FFA3 (default primary)
990
+ primary - 600; // #25C780
991
+ primary - 700; // #26915F
992
+ primary - 800; // #215F40
993
+ primary - 900; // #173123 (darkest)
825
994
  ```
826
995
 
827
996
  #### HeroUI Default Colors:
997
+
828
998
  ```tsx
829
999
  // Semantic colors (built into HeroUI)
830
1000
  bg-primary text-primary border-primary
@@ -840,6 +1010,7 @@ bg-background text-background border-background
840
1010
  ### Color Usage Examples
841
1011
 
842
1012
  **✅ CORRECT - Use theme colors**:
1013
+
843
1014
  ```tsx
844
1015
  // In component configuration (NO hover states)
845
1016
  color: {
@@ -853,6 +1024,7 @@ className="bg-primary-50 text-primary-900"
853
1024
  ```
854
1025
 
855
1026
  **❌ WRONG - Custom color values or hover states**:
1027
+
856
1028
  ```tsx
857
1029
  // DON'T use hex values or hover states in config
858
1030
  color: {
@@ -872,11 +1044,13 @@ color: {
872
1044
  ### When to Add Custom Colors
873
1045
 
874
1046
  **Only add custom colors to hero.ts if**:
1047
+
875
1048
  1. Color is NOT in the existing palette
876
1049
  2. Color is used in multiple places (reusable)
877
1050
  3. Color is part of the design system
878
1051
 
879
1052
  **Steps to add custom color**:
1053
+
880
1054
  ```typescript
881
1055
  // 1. Add to hero.ts theme
882
1056
  export default heroui({
@@ -885,9 +1059,9 @@ export default heroui({
885
1059
  colors: {
886
1060
  // Add new color palette
887
1061
  accent: {
888
- 50: '#...',
889
- 500: '#...',
890
- 900: '#...',
1062
+ 50: "#...",
1063
+ 500: "#...",
1064
+ 900: "#...",
891
1065
  },
892
1066
  },
893
1067
  },
@@ -895,7 +1069,7 @@ export default heroui({
895
1069
  });
896
1070
 
897
1071
  // 2. Use in components
898
- className="bg-accent text-accent-900"
1072
+ className = "bg-accent text-accent-900";
899
1073
  ```
900
1074
 
901
1075
  ---
@@ -907,21 +1081,23 @@ className="bg-accent text-accent-900"
907
1081
  **CRITICAL**: Always use closest standard Tailwind class instead of custom arbitrary values
908
1082
 
909
1083
  **Common Conversions**:
1084
+
910
1085
  ```tsx
911
1086
  // ❌ WRONG - Custom arbitrary values
912
- className="h-[41px] w-[54.6px]"
913
- className="p-[24px]"
914
- className="text-[14px]"
915
- className="gap-[11px]"
1087
+ className = "h-[41px] w-[54.6px]";
1088
+ className = "p-[24px]";
1089
+ className = "text-[14px]";
1090
+ className = "gap-[11px]";
916
1091
 
917
1092
  // ✅ CORRECT - Standard Tailwind classes
918
- className="h-10 w-14" // h-10 = 40px, w-14 = 56px (closest to 54.6px)
919
- className="p-6" // p-6 = 24px
920
- className="text-sm" // text-sm = 14px
921
- className="gap-3" // gap-3 = 12px (closest to 11px)
1093
+ className = "h-10 w-14"; // h-10 = 40px, w-14 = 56px (closest to 54.6px)
1094
+ className = "p-6"; // p-6 = 24px
1095
+ className = "text-sm"; // text-sm = 14px
1096
+ className = "gap-3"; // gap-3 = 12px (closest to 11px)
922
1097
  ```
923
1098
 
924
1099
  **Tailwind Size Reference**:
1100
+
925
1101
  ```css
926
1102
  /* Spacing Scale (padding, margin, gap, etc.) */
927
1103
  0.5 = 2px 4 = 16px 12 = 48px
@@ -945,11 +1121,13 @@ auto, full, screen, fit, min, max
945
1121
  ```
946
1122
 
947
1123
  **Only use arbitrary values when**:
1124
+
948
1125
  - Exact pixel value is required by design system
949
1126
  - No standard Tailwind class is close enough
950
1127
  - Using design tokens/CSS variables: `bg-[var(--custom-color)]`
951
1128
 
952
1129
  **Examples**:
1130
+
953
1131
  ```tsx
954
1132
  // ✅ Good - Using standard classes
955
1133
  <div className="h-10 w-full p-6 text-sm">
@@ -959,6 +1137,7 @@ auto, full, screen, fit, min, max
959
1137
  ```
960
1138
 
961
1139
  ### Responsive Breakpoints (Mobile-First)
1140
+
962
1141
  ```css
963
1142
  /* Mobile */
964
1143
  4xs: 320px /* iPhone SE */
@@ -979,6 +1158,7 @@ xl: 1280px /* MacBook Air */
979
1158
  ```
980
1159
 
981
1160
  ### Usage Example
1161
+
982
1162
  ```tsx
983
1163
  <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
984
1164
  {/* Mobile: 1 column, Tablet: 2 columns, Desktop: 3 columns */}
@@ -986,7 +1166,9 @@ xl: 1280px /* MacBook Air */
986
1166
  ```
987
1167
 
988
1168
  ### HeroUI Color System
1169
+
989
1170
  Use these semantic colors from HeroUI theme:
1171
+
990
1172
  - `bg-background` - Main background
991
1173
  - `bg-foreground` - Text color background
992
1174
  - `bg-default` / `bg-default-50` to `bg-default-900` - Gray scale
@@ -997,6 +1179,7 @@ Use these semantic colors from HeroUI theme:
997
1179
  - `bg-danger` - Error/danger states
998
1180
 
999
1181
  ### Common Patterns
1182
+
1000
1183
  ```tsx
1001
1184
  // Card
1002
1185
  <div className="rounded-lg bg-white p-6 shadow-md">
@@ -1020,19 +1203,20 @@ Use these semantic colors from HeroUI theme:
1020
1203
  ## 📝 Form Implementation with Zod
1021
1204
 
1022
1205
  ### Pattern to Follow
1206
+
1023
1207
  ```tsx
1024
- 'use client';
1208
+ "use client";
1025
1209
 
1026
- import { zodResolver } from '@hookform/resolvers/zod';
1027
- import { useForm } from 'react-hook-form';
1028
- import { z } from 'zod';
1210
+ import { zodResolver } from "@hookform/resolvers/zod";
1211
+ import { useForm } from "react-hook-form";
1212
+ import { z } from "zod";
1029
1213
 
1030
- import { Button, Input } from '@/components/ui';
1214
+ import { Button, Input } from "@/components/ui";
1031
1215
 
1032
1216
  // 1. Define schema
1033
1217
  const schema = z.object({
1034
- email: z.string().email('Invalid email'),
1035
- password: z.string().min(8, 'Password must be at least 8 characters'),
1218
+ email: z.string().email("Invalid email"),
1219
+ password: z.string().min(8, "Password must be at least 8 characters"),
1036
1220
  });
1037
1221
 
1038
1222
  type FormData = z.infer<typeof schema>;
@@ -1059,7 +1243,7 @@ export default function LoginForm() {
1059
1243
  <Input
1060
1244
  label="Email"
1061
1245
  type="email"
1062
- {...register('email')}
1246
+ {...register("email")}
1063
1247
  errorMessage={errors.email?.message}
1064
1248
  isInvalid={!!errors.email}
1065
1249
  />
@@ -1067,7 +1251,7 @@ export default function LoginForm() {
1067
1251
  <Input
1068
1252
  label="Password"
1069
1253
  type="password"
1070
- {...register('password')}
1254
+ {...register("password")}
1071
1255
  errorMessage={errors.password?.message}
1072
1256
  isInvalid={!!errors.password}
1073
1257
  />
@@ -1089,18 +1273,20 @@ export default function LoginForm() {
1089
1273
  ### Navigation with i18n
1090
1274
 
1091
1275
  **Import Guidelines**:
1276
+
1092
1277
  ```tsx
1093
1278
  // For Link component - use Next.js Link
1094
- import Link from 'next/link';
1279
+ import Link from "next/link";
1095
1280
 
1096
1281
  // For navigation hooks - use next/navigation
1097
- import { usePathname, useRouter } from 'next/navigation';
1282
+ import { usePathname, useRouter } from "next/navigation";
1098
1283
 
1099
1284
  // For navigation URLs - use centralized constants
1100
- import { NAVIGATION_URLS } from '@/config/navigationUrls';
1285
+ import { NAVIGATION_URLS } from "@/config/navigationUrls";
1101
1286
  ```
1102
1287
 
1103
1288
  **Navigation Example**:
1289
+
1104
1290
  ```tsx
1105
1291
  import Link from 'next/link';
1106
1292
  import { NAVIGATION_URLS } from '@/config/navigationUrls';
@@ -1117,10 +1303,11 @@ import { Link } from '@heroui/react';
1117
1303
  ```
1118
1304
 
1119
1305
  **Using Navigation Hooks**:
1306
+
1120
1307
  ```tsx
1121
- 'use client';
1308
+ "use client";
1122
1309
 
1123
- import { usePathname, useRouter } from 'next/navigation';
1310
+ import { usePathname, useRouter } from "next/navigation";
1124
1311
 
1125
1312
  export function MyComponent() {
1126
1313
  const pathname = usePathname();
@@ -1139,17 +1326,17 @@ export function MyComponent() {
1139
1326
  **CRITICAL: Specify namespace to avoid TypeScript errors**
1140
1327
 
1141
1328
  ```tsx
1142
- import { useTranslations } from 'next-intl';
1329
+ import { useTranslations } from "next-intl";
1143
1330
 
1144
1331
  function MyComponent() {
1145
1332
  // ✅ CORRECT - Specify namespace for type safety
1146
- const t = useTranslations('namespace');
1333
+ const t = useTranslations("namespace");
1147
1334
 
1148
1335
  return (
1149
1336
  <div>
1150
1337
  {/* Now you can use keys directly without type errors */}
1151
- <h1>{t('welcome')}</h1>
1152
- <p>{t('description')}</p>
1338
+ <h1>{t("welcome")}</h1>
1339
+ <p>{t("description")}</p>
1153
1340
  </div>
1154
1341
  );
1155
1342
  }
@@ -1158,42 +1345,141 @@ function MyComponent() {
1158
1345
  function BadComponent() {
1159
1346
  const t = useTranslations(); // Missing namespace
1160
1347
 
1161
- const items = [
1162
- { key: 'product', labelKey: 'navbar.product' }
1163
- ];
1348
+ const items = [{ key: "product", labelKey: "navbar.product" }];
1164
1349
 
1165
1350
  return (
1166
1351
  <div>
1167
1352
  {/* TypeScript error: Argument of type 'string' is not assignable */}
1168
- {items.map(item => <p key={item.key}>{t(item.labelKey)}</p>)}
1353
+ {items.map((item) => (
1354
+ <p key={item.key}>{t(item.labelKey)}</p>
1355
+ ))}
1169
1356
  </div>
1170
1357
  );
1171
1358
  }
1172
1359
  ```
1173
1360
 
1174
1361
  **Type-Safe Translation Pattern:**
1362
+
1363
+ ⚠️ **COMMON ERROR - Dynamic Translation Keys with Wrong Namespace**:
1364
+
1365
+ When you have configuration data with translation keys from different namespaces, you'll get TypeScript errors if you try to use a single `useTranslations()` hook:
1366
+
1367
+ ```tsx
1368
+ // ❌ WRONG - This causes TypeScript errors
1369
+ const menuItems = [
1370
+ {
1371
+ key: "product",
1372
+ labelKey: "product",
1373
+ items: [
1374
+ {
1375
+ key: "chat",
1376
+ labelKey: "product.chat",
1377
+ descriptionKey: "product.chatDescription",
1378
+ },
1379
+ ],
1380
+ },
1381
+ ];
1382
+
1383
+ function Navbar() {
1384
+ const tNavbar = useTranslations("navbar"); // Only accepts navbar.* keys
1385
+ const item = menuItems[0];
1386
+
1387
+ return (
1388
+ <div>
1389
+ {/* ❌ ERROR: 'product.chat' is not assignable to navbar keys */}
1390
+ {item.items.map((subItem) => (
1391
+ <div key={subItem.key}>
1392
+ <h3>{tNavbar(subItem.labelKey)}</h3>
1393
+ <p>{tNavbar(subItem.descriptionKey)}</p>
1394
+ </div>
1395
+ ))}
1396
+ </div>
1397
+ );
1398
+ }
1399
+ ```
1400
+
1401
+ **✅ SOLUTION - Use Separate Translation Hooks for Each Namespace**:
1402
+
1175
1403
  ```tsx
1176
- // 1. Define translation key types in config
1404
+ // File: src/locales/en.json
1405
+ {
1406
+ "navbar": {
1407
+ "product": "Product",
1408
+ "useCases": "Use cases"
1409
+ },
1410
+ "product": {
1411
+ "chat": "Chat",
1412
+ "chatDescription": "Empower your team with Gen AI"
1413
+ }
1414
+ }
1415
+
1416
+ // File: src/config/menuItems.ts
1417
+ export type SubMenuItem = {
1418
+ key: string;
1419
+ labelKey: string; // String type because it's from different namespace
1420
+ descriptionKey: string;
1421
+ href: string;
1422
+ };
1423
+
1177
1424
  export type MenuItem = {
1178
1425
  key: string;
1179
- labelKey: 'product' | 'useCases' | 'resources'; // Union type of valid keys
1180
- href?: string;
1426
+ label: string; // Maps to navbar namespace keys
1427
+ items?: SubMenuItem[];
1181
1428
  };
1182
1429
 
1183
- // 2. Use with namespace
1184
- const t = useTranslations('navbar');
1430
+ export const navbarMenuItems: MenuItem[] = [
1431
+ {
1432
+ key: 'product',
1433
+ label: 'product', // navbar.product
1434
+ items: [
1435
+ {
1436
+ key: 'chat',
1437
+ labelKey: 'chat', // product.chat (different namespace!)
1438
+ descriptionKey: 'chatDescription', // product.chatDescription
1439
+ href: '/chat',
1440
+ },
1441
+ ],
1442
+ },
1443
+ ];
1444
+
1445
+ // File: Component usage
1446
+ function Navbar() {
1447
+ // ✅ CORRECT - Use separate hooks for each namespace
1448
+ const tNavbar = useTranslations('navbar');
1449
+ const tProduct = useTranslations('product');
1185
1450
 
1186
- // 3. Access keys directly (type-safe)
1187
- {menuItems.map(item => (
1188
- <Button key={item.key}>
1189
- {t(item.labelKey)} {/* No TypeScript error */}
1190
- </Button>
1191
- ))}
1451
+ return (
1452
+ <div>
1453
+ {navbarMenuItems.map(item => (
1454
+ <div key={item.key}>
1455
+ {/* Use tNavbar for navbar.* keys */}
1456
+ <button>{tNavbar(item.label)}</button>
1457
+
1458
+ {/* Use tProduct for product.* keys */}
1459
+ {item.items?.map(subItem => (
1460
+ <div key={subItem.key}>
1461
+ <h3>{tProduct(subItem.labelKey)}</h3>
1462
+ <p>{tProduct(subItem.descriptionKey)}</p>
1463
+ </div>
1464
+ ))}
1465
+ </div>
1466
+ ))}
1467
+ </div>
1468
+ );
1469
+ }
1192
1470
  ```
1193
1471
 
1472
+ **Key Points**:
1473
+
1474
+ 1. ✅ Separate translation hooks for each namespace (`tNavbar`, `tProduct`)
1475
+ 2. ✅ Use the correct hook for each translation key based on its namespace
1476
+ 3. ✅ Keep translation namespaces flat and separate (don't nest `product` inside `navbar`)
1477
+ 4. ❌ Don't try to use one translation hook for keys from multiple namespaces
1478
+
1194
1479
  ### Form labels, placeholders, errors - ALL must use i18n
1480
+
1195
1481
  ```tsx
1196
- import { useTranslations } from 'next-intl';
1482
+ import { useTranslations } from "next-intl";
1197
1483
 
1198
1484
  function LoginForm() {
1199
1485
  const t = useTranslations();
@@ -1202,9 +1488,11 @@ function LoginForm() {
1202
1488
  <form>
1203
1489
  {/* ✅ CORRECT */}
1204
1490
  <Input
1205
- label={t('email')}
1206
- placeholder={t('enterEmail')}
1207
- errorMessage={errors.email?.message ? t(errors.email.message) : undefined}
1491
+ label={t("email")}
1492
+ placeholder={t("enterEmail")}
1493
+ errorMessage={
1494
+ errors.email?.message ? t(errors.email.message) : undefined
1495
+ }
1208
1496
  />
1209
1497
 
1210
1498
  {/* ❌ WRONG - Hardcoded text */}
@@ -1219,6 +1507,7 @@ function LoginForm() {
1219
1507
  ```
1220
1508
 
1221
1509
  ### Navigation URLs Reference
1510
+
1222
1511
  ```tsx
1223
1512
  import { NAVIGATION_URLS } from '@/config/navigationUrls';
1224
1513
 
@@ -1243,19 +1532,20 @@ NAVIGATION_URLS.DASHBOARD.INDEX // '/dashboard'
1243
1532
  ## 🎯 Data Fetching
1244
1533
 
1245
1534
  ### Using React Query
1535
+
1246
1536
  ```tsx
1247
- 'use client';
1537
+ "use client";
1248
1538
 
1249
- import { useQuery } from '@tanstack/react-query';
1250
- import axios from 'axios';
1539
+ import { useQuery } from "@tanstack/react-query";
1540
+ import axios from "axios";
1251
1541
 
1252
- import { QUERY_KEYS } from '@/libs/react-query';
1542
+ import { QUERY_KEYS } from "@/libs/react-query";
1253
1543
 
1254
1544
  export default function ProductList() {
1255
1545
  const { data, isLoading, error } = useQuery({
1256
1546
  queryKey: QUERY_KEYS.PRODUCTS.LIST,
1257
1547
  queryFn: async () => {
1258
- const response = await axios.get('/api/products');
1548
+ const response = await axios.get("/api/products");
1259
1549
  return response.data;
1260
1550
  },
1261
1551
  });
@@ -1278,11 +1568,12 @@ export default function ProductList() {
1278
1568
  ## 📐 Layout Components
1279
1569
 
1280
1570
  ### Using Existing Layouts
1571
+
1281
1572
  ```tsx
1282
1573
  // Auth pages use auth layout automatically
1283
1574
  // Location: src/app/[locale]/(auth)/login/page.tsx
1284
1575
 
1285
- 'use client';
1576
+ "use client";
1286
1577
 
1287
1578
  export default function LoginPage() {
1288
1579
  return (
@@ -1295,11 +1586,14 @@ export default function LoginPage() {
1295
1586
  ```
1296
1587
 
1297
1588
  ### Navbar & Footer
1589
+
1298
1590
  Already implemented in `src/components/layout/`:
1591
+
1299
1592
  - `Navbar.tsx` - Main navigation using HeroUI Navbar
1300
1593
  - `Footer.tsx` - Footer component
1301
1594
 
1302
1595
  **CRITICAL**: Navbar uses HeroUI Navbar component:
1596
+
1303
1597
  ```tsx
1304
1598
  import { Navbar } from '@/components/layout';
1305
1599
 
@@ -1309,6 +1603,7 @@ import { Navbar } from '@/components/layout';
1309
1603
  ```
1310
1604
 
1311
1605
  **Implementation details** (see `src/components/layout/Navbar.tsx` and `docs/NAVBAR_IMPLEMENTATION.md`):
1606
+
1312
1607
  - ✅ Uses HeroUI `Navbar`, `NavbarBrand`, `NavbarContent`, `NavbarItem`, `Dropdown`
1313
1608
  - ✅ Uses `Button` from `@/components/ui` with props (`color`, `size`, `variant`)
1314
1609
  - ✅ Uses `useTranslations('navbar')` with namespace for type safety
@@ -1323,6 +1618,7 @@ import { Navbar } from '@/components/layout';
1323
1618
  ## ⚠️ CRITICAL RULES
1324
1619
 
1325
1620
  ### ❌ DO NOT
1621
+
1326
1622
  1. ❌ **Figma**: Use screenshots to implement design - MUST use Figma MCP server with `get_design_context`
1327
1623
  2. ❌ **Figma**: Call `get_screenshot` tool - Design context provides all needed information
1328
1624
  3. ❌ **Icons**: Import individual icon components (e.g., `import { ChevronDownIcon }`) - MUST use `<Icon name="ChevronDownIcon" />`
@@ -1334,28 +1630,29 @@ import { Navbar } from '@/components/layout';
1334
1630
  9. ❌ **Images**: Use direct path strings anywhere - ALL paths MUST come from `@/config/images`
1335
1631
  10. ❌ **Tailwind**: Use arbitrary values when standard classes exist (e.g., `h-[40px]` → use `h-10`)
1336
1632
  11. ❌ **Tailwind**: Use custom values like `w-[100%]` (use `w-full`)
1337
- 11. ❌ **Colors**: Use custom color values (e.g., `bg-[#19ffa3]`, `text-[#ff0000]`) - MUST use theme colors from hero.ts
1338
- 12. ❌ **Colors**: Use hex, rgb, or hsl values inline - Use semantic color classes instead
1339
- 13. ❌ **Text**: Hardcode ANY text - ALL text MUST use i18n translation keys
1340
- 14. ❌ **URLs**: Hardcode URLs - ALWAYS use `NAVIGATION_URLS` from config
1341
- 15. ❌ **Data**: Hardcode menu items, dropdown options - MUST map from constants
1342
- 16. ❌ **Components**: Create custom components when HeroUI provides them (e.g., use HeroUI `Navbar` not custom `<header>`)
1343
- 17. ❌ **Components**: Use HTML elements when HeroUI component exists (e.g., `<button>` → use HeroUI `<Button>`)
1344
- 18. ❌ **Styling**: Apply component styles via className - MUST use props (`color`, `size`, `variant`, `radius`)
1345
- 19. ❌ **Styling**: Use className for component styles (e.g., `className="h-10 px-4 bg-primary"`) - Configure in wrapper instead
1346
- 20. ❌ **Styling**: Use CSS modules or styled-components - ONLY Tailwind CSS
1347
- 21. ❌ **Imports**: Import from `@heroui/react` directly (use `@/components/ui` wrappers when available)
1348
- 22. ❌ **Navigation**: Use HeroUI `Link` for internal navigation (use Next.js `Link` from `next/link`)
1349
- 23. ❌ **Navigation**: Import `usePathname`, `useRouter` from wrong source (MUST use `next/navigation`)
1350
- 24. ❌ **TypeScript**: Use `any` type - Use union types and proper typing instead
1351
- 25. ❌ **i18n**: Use `useTranslations()` without namespace - MUST specify namespace for type safety
1352
- 26. ❌ **i18n**: Use dynamic translation keys without proper typing - Define union types for keys
1353
- 27. ❌ **Design**: Ignore responsive design (always implement mobile-first)
1354
- 28. ❌ **Forms**: Skip form validation (always use Zod schemas)
1355
- 29. ❌ **Dropdowns**: Render dropdown items without checking if items array exists/has length
1356
- 30. ❌ **Build**: Run `pnpm build` or `pnpm lint` commands - The user will run these manually
1633
+ 12. ❌ **Colors**: Use custom color values (e.g., `bg-[#19ffa3]`, `text-[#ff0000]`) - MUST use theme colors from hero.ts
1634
+ 13. ❌ **Colors**: Use hex, rgb, or hsl values inline - Use semantic color classes instead
1635
+ 14. ❌ **Text**: Hardcode ANY text - ALL text MUST use i18n translation keys
1636
+ 15. ❌ **URLs**: Hardcode URLs - ALWAYS use `NAVIGATION_URLS` from config
1637
+ 16. ❌ **Data**: Hardcode menu items, dropdown options - MUST map from constants
1638
+ 17. ❌ **Components**: Create custom components when HeroUI provides them (e.g., use HeroUI `Navbar` not custom `<header>`)
1639
+ 18. ❌ **Components**: Use HTML elements when HeroUI component exists (e.g., `<button>` → use HeroUI `<Button>`)
1640
+ 19. ❌ **Styling**: Apply component styles via className - MUST use props (`color`, `size`, `variant`, `radius`)
1641
+ 20. ❌ **Styling**: Use className for component styles (e.g., `className="h-10 px-4 bg-primary"`) - Configure in wrapper instead
1642
+ 21. ❌ **Styling**: Use CSS modules or styled-components - ONLY Tailwind CSS
1643
+ 22. ❌ **Imports**: Import from `@heroui/react` directly (use `@/components/ui` wrappers when available)
1644
+ 23. ❌ **Navigation**: Use HeroUI `Link` for internal navigation (use Next.js `Link` from `next/link`)
1645
+ 24. ❌ **Navigation**: Import `usePathname`, `useRouter` from wrong source (MUST use `next/navigation`)
1646
+ 25. ❌ **TypeScript**: Use `any` type - Use union types and proper typing instead
1647
+ 26. ❌ **i18n**: Use `useTranslations()` without namespace - MUST specify namespace for type safety
1648
+ 27. ❌ **i18n**: Use dynamic translation keys without proper typing - Define union types for keys
1649
+ 28. ❌ **Design**: Ignore responsive design (always implement mobile-first)
1650
+ 29. ❌ **Forms**: Skip form validation (always use Zod schemas)
1651
+ 30. ❌ **Dropdowns**: Render dropdown items without checking if items array exists/has length
1652
+ 31. ❌ **Build**: Run `pnpm build` or `pnpm lint` commands - The user will run these manually
1357
1653
 
1358
1654
  ### ✅ DO
1655
+
1359
1656
  1. ✅ **Figma**: Use Figma MCP server with `get_design_context` and node-id from Figma URL
1360
1657
  2. ✅ **Figma**: Extract node-id from URL (e.g., `node-id=8486-1580` → `"8486:1580"`)
1361
1658
  3. ✅ **Icons**: Export SVG from Figma → `src/assets/icons/` → Run `pnpm generate-icons`
@@ -1369,30 +1666,30 @@ import { Navbar } from '@/components/layout';
1369
1666
  11. ✅ **Images**: Prefer SVG over PNG when source is vector
1370
1667
  12. ✅ **Tailwind**: Use standard classes (`h-10`, `p-6`, `text-sm` instead of arbitrary values)
1371
1668
  13. ✅ **Tailwind**: Use size utilities (`size-4`, `size-5`) for icons
1372
- 13. ✅ **Colors**: Use theme colors from hero.ts (`bg-primary`, `text-primary-600`, `bg-success`)
1373
- 14. ✅ **Colors**: Check hero.ts and globals.css for available colors before using custom values
1374
- 15. ✅ **Navigation**: Use Next.js `Link` from `next/link` for internal navigation
1375
- 16. ✅ **Navigation**: Import `usePathname`, `useRouter` from `next/navigation`
1376
- 17. ✅ **Text**: Use i18n translation keys for ALL text (`t('key')`)
1377
- 18. ✅ **URLs**: Use `NAVIGATION_URLS` for ALL navigation links
1378
- 19. ✅ **Data**: Map menu items, dropdown options from constants (never hardcode)
1379
- 20. ✅ **Components**: Use HeroUI components first (e.g., use `Navbar` from `@heroui/react` for navigation)
1380
- 21. ✅ **Components**: Use existing wrappers from `src/components/ui/` when available (e.g., `Button`)
1381
- 22. ✅ **Components**: Configure component styles in wrappers using `extendVariants`
1382
- 23. ✅ **Components**: Set `defaultVariants` in wrapper configuration to avoid repetition
1383
- 24. ✅ **Styling**: Use component props for styles, but ONLY specify non-default values
1384
- 25. ✅ **Styling**: Omit props that match defaultVariants (e.g., don't write `size="md"` if `md` is default)
1385
- 26. ✅ **Styling**: Use className ONLY for layout utilities (`mt-4`, `hidden`, `lg:flex`)
1386
- 27. ✅ **Styling**: Use Tailwind CSS ONLY (utility classes)
1387
- 28. ✅ **TypeScript**: Implement strict typing with proper types (NO `any`)
1388
- 29. ✅ **TypeScript**: Use union types for translation keys (e.g., `labelKey: 'product' | 'useCases'`)
1389
- 30. ✅ **i18n**: Specify namespace in `useTranslations('namespace')` for type safety
1390
- 31. ✅ **i18n**: Define typed keys in config to avoid dynamic string issues
1391
- 32. ✅ **Dropdowns**: Check array exists and has length before mapping (`items && items.length > 0`)
1392
- 33. ✅ **React**: Use `'use client'` directive for interactive components
1393
- 34. ✅ **Design**: Follow mobile-first responsive design
1394
- 35. ✅ **States**: Implement proper loading and error states
1395
- 36. ✅ **Patterns**: Follow existing code patterns and naming conventions
1669
+ 14. ✅ **Colors**: Use theme colors from hero.ts (`bg-primary`, `text-primary-600`, `bg-success`)
1670
+ 15. ✅ **Colors**: Check hero.ts and globals.css for available colors before using custom values
1671
+ 16. ✅ **Navigation**: Use Next.js `Link` from `next/link` for internal navigation
1672
+ 17. ✅ **Navigation**: Import `usePathname`, `useRouter` from `next/navigation`
1673
+ 18. ✅ **Text**: Use i18n translation keys for ALL text (`t('key')`)
1674
+ 19. ✅ **URLs**: Use `NAVIGATION_URLS` for ALL navigation links
1675
+ 20. ✅ **Data**: Map menu items, dropdown options from constants (never hardcode)
1676
+ 21. ✅ **Components**: Use HeroUI components first (e.g., use `Navbar` from `@heroui/react` for navigation)
1677
+ 22. ✅ **Components**: Use existing wrappers from `src/components/ui/` when available (e.g., `Button`)
1678
+ 23. ✅ **Components**: Configure component styles in wrappers using `extendVariants`
1679
+ 24. ✅ **Components**: Set `defaultVariants` in wrapper configuration to avoid repetition
1680
+ 25. ✅ **Styling**: Use component props for styles, but ONLY specify non-default values
1681
+ 26. ✅ **Styling**: Omit props that match defaultVariants (e.g., don't write `size="md"` if `md` is default)
1682
+ 27. ✅ **Styling**: Use className ONLY for layout utilities (`mt-4`, `hidden`, `lg:flex`)
1683
+ 28. ✅ **Styling**: Use Tailwind CSS ONLY (utility classes)
1684
+ 29. ✅ **TypeScript**: Implement strict typing with proper types (NO `any`)
1685
+ 30. ✅ **TypeScript**: Use union types for translation keys (e.g., `labelKey: 'product' | 'useCases'`)
1686
+ 31. ✅ **i18n**: Specify namespace in `useTranslations('namespace')` for type safety
1687
+ 32. ✅ **i18n**: Define typed keys in config to avoid dynamic string issues
1688
+ 33. ✅ **Dropdowns**: Check array exists and has length before mapping (`items && items.length > 0`)
1689
+ 34. ✅ **React**: Use `'use client'` directive for interactive components
1690
+ 35. ✅ **Design**: Follow mobile-first responsive design
1691
+ 36. ✅ **States**: Implement proper loading and error states
1692
+ 37. ✅ **Patterns**: Follow existing code patterns and naming conventions
1396
1693
 
1397
1694
  ---
1398
1695
 
@@ -1401,6 +1698,7 @@ import { Navbar } from '@/components/layout';
1401
1698
  When converting Figma to code, ensure:
1402
1699
 
1403
1700
  ### Icons & Assets
1701
+
1404
1702
  - [ ] Exported icons as SVG from Figma
1405
1703
  - [ ] Placed SVG files in `src/assets/icons/`
1406
1704
  - [ ] Ran `pnpm generate-icons` to create React components
@@ -1415,6 +1713,7 @@ When converting Figma to code, ensure:
1415
1713
  - [ ] Referenced via `IMAGES.LOGOS.PRIMARY` (not hardcoded paths)
1416
1714
 
1417
1715
  ### Component & Styling
1716
+
1418
1717
  - [ ] Checked HeroUI library first for component availability
1419
1718
  - [ ] Used HeroUI components via `src/components/ui/` wrappers (e.g., `<Button>` not `<button>`)
1420
1719
  - [ ] Configured component styles in wrapper/theme (not inline)
@@ -1425,6 +1724,7 @@ When converting Figma to code, ensure:
1425
1724
  - [ ] Mapped all data from constants (no hardcoded menu items/dropdowns)
1426
1725
 
1427
1726
  ### Content & Navigation
1727
+
1428
1728
  - [ ] ALL text uses i18n translation keys (no hardcoded text)
1429
1729
  - [ ] ALL labels use `t('labelKey')`
1430
1730
  - [ ] ALL placeholders use `t('placeholderKey')`
@@ -1433,18 +1733,21 @@ When converting Figma to code, ensure:
1433
1733
  - [ ] ALL URLs use `NAVIGATION_URLS` from config (no hardcoded URLs)
1434
1734
 
1435
1735
  ### Structure & Types
1736
+
1436
1737
  - [ ] Page created in correct location (`src/app/[locale]/...`)
1437
1738
  - [ ] Added TypeScript types for all data structures
1438
1739
  - [ ] Used `'use client'` for interactive components
1439
1740
  - [ ] No `any` types used
1440
1741
 
1441
1742
  ### Forms & Validation
1743
+
1442
1744
  - [ ] Implemented forms with Zod validation schemas
1443
1745
  - [ ] Form labels use i18n
1444
1746
  - [ ] Form placeholders use i18n
1445
1747
  - [ ] Form errors use i18n
1446
1748
 
1447
1749
  ### Responsive & States
1750
+
1448
1751
  - [ ] Implemented responsive design (mobile-first)
1449
1752
  - [ ] Added proper loading states
1450
1753
  - [ ] Added proper error states
@@ -1457,12 +1760,14 @@ When converting Figma to code, ensure:
1457
1760
  Before finalizing code, verify:
1458
1761
 
1459
1762
  ### Icons & Assets
1763
+
1460
1764
  1. **Icons workflow** - All icons created via `pnpm generate-icons` (not manual)
1461
1765
  2. **Icons source** - SVG files exist in `src/assets/icons/`
1462
1766
  3. **Logos location** - All logos/images in `public/` directory (not `src/`)
1463
1767
  4. **Image format** - SVG used for logos when possible (not PNG)
1464
1768
 
1465
1769
  ### Components & Styling
1770
+
1466
1771
  1. **HeroUI components first** - Verify HeroUI library was checked before custom implementation
1467
1772
  2. **No direct HeroUI imports** - Only through `@/components/ui`
1468
1773
  3. **Component reuse** - Don't duplicate existing components
@@ -1472,17 +1777,20 @@ Before finalizing code, verify:
1472
1777
  7. **Map from constants** - All menu items, dropdown options mapped from config files
1473
1778
 
1474
1779
  ### i18n & Navigation
1780
+
1475
1781
  5. **Zero hardcoded text** - ALL text uses `t('key')`
1476
1782
  6. **Zero hardcoded URLs** - ALL links use `NAVIGATION_URLS`
1477
1783
  7. **Form fields i18n** - Labels, placeholders, errors all use translation keys
1478
1784
 
1479
1785
  ### Styling & Layout
1786
+
1480
1787
  8. **Tailwind only** - No CSS modules, no styled-components
1481
1788
  9. **HeroUI theme colors** - Use semantic colors, not arbitrary values
1482
1789
  10. **Consistent spacing** - Use `space-y-*` and `space-x-*` utilities
1483
1790
  11. **Mobile-first** - Base styles for mobile, then `md:`, `lg:`, etc.
1484
1791
 
1485
1792
  ### TypeScript & Validation
1793
+
1486
1794
  12. **Proper TypeScript** - No `any`, all props typed
1487
1795
  13. **Form validation** - Zod schemas for all forms
1488
1796
 
@@ -1491,6 +1799,7 @@ Before finalizing code, verify:
1491
1799
  ## 📚 Reference Files
1492
1800
 
1493
1801
  When in doubt, check these example files:
1802
+
1494
1803
  - **Form example**: `src/components/ui/form/Form.tsx`
1495
1804
  - **Page example**: `src/app/[locale]/(auth)/login/page.tsx`
1496
1805
  - **Component example**: `src/components/ui/Input.tsx`
@@ -1502,6 +1811,7 @@ When in doubt, check these example files:
1502
1811
  ## 🚀 Quick Reference Guide
1503
1812
 
1504
1813
  ### Icons Workflow
1814
+
1505
1815
  ```bash
1506
1816
  # 1. Export SVG from Figma
1507
1817
  # 2. Place in folder
@@ -1516,6 +1826,7 @@ import { IconIcon } from '@/components/icons';
1516
1826
  ```
1517
1827
 
1518
1828
  ### Logos/Images Workflow
1829
+
1519
1830
  ```bash
1520
1831
  # 1. Export SVG/PNG from Figma
1521
1832
  # 2. Place in public with organized folders
@@ -1548,6 +1859,7 @@ import { IMAGES } from '@/config/images';
1548
1859
  ```
1549
1860
 
1550
1861
  ### Tailwind Standard Classes
1862
+
1551
1863
  ```tsx
1552
1864
  // Heights/Widths
1553
1865
  h-10 = 40px w-14 = 56px size-5 = 20px
@@ -1567,6 +1879,7 @@ text-lg = 18px text-3xl = 30px
1567
1879
  ```
1568
1880
 
1569
1881
  ### Common Patterns
1882
+
1570
1883
  ```tsx
1571
1884
  // Icons (auto-generated)
1572
1885
  import { MenuIcon, CloseIcon } from '@/components/icons';