@adlas/create-app 1.0.50 → 1.0.52

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adlas/create-app",
3
- "version": "1.0.50",
3
+ "version": "1.0.52",
4
4
  "description": "Adlas project initializer with Figma and Swagger integration",
5
5
  "type": "module",
6
6
  "main": "./dist/cli.js",
@@ -11,25 +11,19 @@ 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
-
15
14
  ```typescript
16
15
  // Use get_design_context tool with node-id from Figma URL
17
16
  // Example URL: https://figma.com/design/:fileKey/:fileName?node-id=8486-1580
18
17
  // Extract node-id: 8486-1580 → use as: "8486:1580"
19
18
 
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
- });
19
+ mcp__figma-dev-mode-mcp-server__get_design_context({
20
+ nodeId: "8486:1580",
21
+ clientLanguages: "typescript",
22
+ clientFrameworks: "react,nextjs"
23
+ })
29
24
  ```
30
25
 
31
26
  **Benefits of using Figma MCP**:
32
-
33
27
  - ✅ Get exact measurements, colors, and spacing
34
28
  - ✅ Access design tokens and styles
35
29
  - ✅ See component structure and hierarchy
@@ -51,6 +45,7 @@ mcp__figma -
51
45
  9. **Follow project structure** - Place files in correct locations as defined below
52
46
  10. **Match coding patterns** - Use the same patterns found in existing code
53
47
  11. **Type safety first** - Use TypeScript strictly, no `any` types
48
+ 12. **❌ NEVER run build** - Do NOT run `pnpm build` or `pnpm lint` commands. The user will run these manually
54
49
 
55
50
  ---
56
51
 
@@ -59,7 +54,6 @@ mcp__figma -
59
54
  ### CRITICAL: Component Styles Must Be Configured, Not Inline
60
55
 
61
56
  **❌ WRONG - Inline component styles**:
62
-
63
57
  ```tsx
64
58
  // DON'T: Apply component-specific styles inline via className
65
59
  <Button className="h-10 rounded-full bg-[#19ffa3] px-4 text-sm text-black">
@@ -76,7 +70,6 @@ mcp__figma -
76
70
  ```
77
71
 
78
72
  **✅ CORRECT - Use props and configured variants**:
79
-
80
73
  ```tsx
81
74
  // Step 1: Configure variants in component wrapper
82
75
  // File: src/components/ui/Button.tsx
@@ -86,13 +79,16 @@ export const Button = extendVariants(HeroUIButton, {
86
79
  variants: {
87
80
  color: {
88
81
  // ✅ Use theme colors from hero.ts, NOT custom colors
89
- primary: 'bg-primary text-black',
82
+ primary: 'bg-primary-500 text-black',
90
83
  },
91
84
  size: {
92
- sm: 'h-8 px-3 text-xs',
85
+ sm: 'h-10 px-4 text-sm',
93
86
  md: 'h-10 px-4 text-sm',
94
87
  lg: 'h-12 px-6 text-base',
95
88
  },
89
+ radius: {
90
+ full: 'rounded-full',
91
+ },
96
92
  },
97
93
  defaultVariants: {
98
94
  size: 'md',
@@ -121,7 +117,6 @@ import { Button } from '@/components/ui';
121
117
  ```
122
118
 
123
119
  **Component Style Rules**:
124
-
125
120
  - ✅ **Configure in wrapper**: All component-specific styles (height, padding, colors, text size)
126
121
  - ✅ **Set defaultVariants**: Define defaults in wrapper so you don't repeat them in usage
127
122
  - ✅ **Use theme colors**: `bg-primary`, `bg-secondary`, `bg-success`, `bg-danger`, `bg-warning` from hero.ts
@@ -134,7 +129,6 @@ import { Button } from '@/components/ui';
134
129
  - ❌ **NEVER repeat defaultVariants**: Don't specify `size="md"` if `md` is already the default
135
130
 
136
131
  **Color Usage Rules**:
137
-
138
132
  ```tsx
139
133
  // ✅ CORRECT - Use theme colors from hero.ts or globals.css
140
134
  color: {
@@ -156,7 +150,6 @@ secondary, success, danger, warning, default, foreground, background
156
150
  ```
157
151
 
158
152
  **What goes where**:
159
-
160
153
  ```tsx
161
154
  // In Button.tsx configuration:
162
155
  const Button = extendVariants(HerouiButton, {
@@ -177,16 +170,17 @@ const Button = extendVariants(HerouiButton, {
177
170
 
178
171
  // In component usage:
179
172
  <Button
180
- color="primary" // ✅ Specify only when different from default
181
- radius="full" // ✅ HeroUI built-in prop (don't configure in wrapper)
173
+ color="primary" // ✅ Configured variant
174
+ size="sm" // ✅ Configured variant (can omit if md is default)
175
+ radius="full" // ✅ Configured radius variant
182
176
  className="mt-4 hidden lg:block" // ✅ Layout utilities only
183
177
  >
184
178
  {t('navbar.bookDemo')} // ✅ i18n text
185
179
  </Button>
186
- // Note: size="md" NOT needed because it's the defaultVariant
180
+ // Note: Omit props that match defaultVariants to keep code clean
187
181
 
188
182
  // Using size prop when you need different size:
189
- <Button color="primary" size="lg"> // ✅ Override default size
183
+ <Button color="primary" size="lg" radius="full"> // ✅ Override default size
190
184
  Large Button
191
185
  </Button>
192
186
 
@@ -200,7 +194,6 @@ import { Icon } from '@/components/ui';
200
194
  ### Data Must Be Mapped from Constants
201
195
 
202
196
  **❌ WRONG - Hardcoded data**:
203
-
204
197
  ```tsx
205
198
  <DropdownMenu>
206
199
  <DropdownItem key="option1">Option 1</DropdownItem>
@@ -210,17 +203,16 @@ import { Icon } from '@/components/ui';
210
203
  ```
211
204
 
212
205
  **✅ CORRECT - Map from constants**:
213
-
214
206
  ```tsx
215
207
  // File: src/config/menuOptions.ts
216
208
  export const productMenuItems = [
217
- { key: "analytics", labelKey: "product.analytics", href: "/analytics" },
218
- { key: "insights", labelKey: "product.insights", href: "/insights" },
219
- { key: "reports", labelKey: "product.reports", href: "/reports" },
209
+ { key: 'analytics', labelKey: 'product.analytics', href: '/analytics' },
210
+ { key: 'insights', labelKey: 'product.insights', href: '/insights' },
211
+ { key: 'reports', labelKey: 'product.reports', href: '/reports' },
220
212
  ];
221
213
 
222
214
  // Usage:
223
- import { productMenuItems } from "@/config/menuOptions";
215
+ import { productMenuItems } from '@/config/menuOptions';
224
216
 
225
217
  <DropdownMenu>
226
218
  {productMenuItems.map((item) => (
@@ -228,7 +220,7 @@ import { productMenuItems } from "@/config/menuOptions";
228
220
  {t(item.labelKey)}
229
221
  </DropdownItem>
230
222
  ))}
231
- </DropdownMenu>;
223
+ </DropdownMenu>
232
224
  ```
233
225
 
234
226
  ---
@@ -236,14 +228,11 @@ import { productMenuItems } from "@/config/menuOptions";
236
228
  ## 🎨 Component Priority & Usage Strategy
237
229
 
238
230
  ### 1. Check HeroUI First
239
-
240
231
  Before creating ANY component, check if HeroUI provides it:
241
-
242
232
  - **HeroUI Documentation**: https://heroui.com/docs/components
243
233
  - **HeroUI Figma Kit**: https://www.figma.com/design/kFGcjHsNKZx7zh2NxEJXYt/HeroUI-Figma-Kit--Community---Community-
244
234
 
245
235
  ### 2. Component Selection Flow
246
-
247
236
  ```
248
237
  1. Does HeroUI have this component?
249
238
  → YES: Use HeroUI component (via @/components/ui wrapper if exists)
@@ -259,7 +248,6 @@ Before creating ANY component, check if HeroUI provides it:
259
248
  ```
260
249
 
261
250
  ### 3. Example Decision Tree
262
-
263
251
  ```tsx
264
252
  // Need a Button?
265
253
  import { Button } from '@/components/ui'; // ✅ Use HeroUI Button wrapper
@@ -278,12 +266,10 @@ import { Input } from '@/components/ui'; // ✅ Use HeroUI Input wrapper
278
266
  ## 📁 Project Structure
279
267
 
280
268
  ### Pages Location
281
-
282
269
  - **With i18n**: `src/app/[locale]/(route-group)/page.tsx`
283
270
  - **Without i18n**: `src/app/(route-group)/page.tsx`
284
271
 
285
272
  ### Components Location
286
-
287
273
  ```
288
274
  src/components/
289
275
  ├── ui/ # Reusable UI components (HeroUI wrappers)
@@ -293,7 +279,6 @@ src/components/
293
279
  ```
294
280
 
295
281
  ### Styling
296
-
297
282
  - **Global styles**: `src/styles/globals.css`
298
283
  - **Theme config**: `src/styles/hero.ts`
299
284
  - **Approach**: Tailwind CSS utility classes ONLY
@@ -306,7 +291,6 @@ src/components/
306
291
  ### Navigation Components
307
292
 
308
293
  #### Navbar (HeroUI)
309
-
310
294
  **CRITICAL**: Always use HeroUI Navbar component for navigation bars:
311
295
 
312
296
  ```tsx
@@ -318,8 +302,8 @@ import {
318
302
  NavbarMenu,
319
303
  NavbarMenuItem,
320
304
  NavbarMenuToggle,
321
- } from "@heroui/react";
322
- import { Button } from "@/components/ui";
305
+ } from '@heroui/react';
306
+ import { Button } from '@/components/ui';
323
307
 
324
308
  <Navbar maxWidth="full" className="bg-black border-b-2">
325
309
  {/* Logo */}
@@ -330,16 +314,14 @@ import { Button } from "@/components/ui";
330
314
  {/* Desktop Menu */}
331
315
  <NavbarContent className="hidden lg:flex" justify="center">
332
316
  <NavbarItem>
333
- <Button variant="light">Menu Item</Button>{" "}
334
- {/* size="md" omitted - it's default */}
317
+ <Button variant="light">Menu Item</Button> {/* size="md" omitted - it's default */}
335
318
  </NavbarItem>
336
319
  </NavbarContent>
337
320
 
338
321
  {/* CTA */}
339
322
  <NavbarContent className="hidden lg:flex" justify="end">
340
323
  <NavbarItem>
341
- <Button color="primary">CTA</Button>{" "}
342
- {/* size="md" omitted - it's default */}
324
+ <Button color="primary">CTA</Button> {/* size="md" omitted - it's default */}
343
325
  </NavbarItem>
344
326
  </NavbarContent>
345
327
 
@@ -349,28 +331,103 @@ import { Button } from "@/components/ui";
349
331
  {/* Mobile Menu */}
350
332
  <NavbarMenu>
351
333
  <NavbarMenuItem>
352
- <Button variant="light" fullWidth>
353
- Menu Item
354
- </Button>
334
+ <Button variant="light" fullWidth>Menu Item</Button>
355
335
  </NavbarMenuItem>
356
336
  </NavbarMenu>
357
- </Navbar>;
337
+ </Navbar>
358
338
  ```
359
339
 
360
340
  **Key Points**:
361
-
362
341
  - ✅ Use `Navbar` from `@heroui/react`
363
342
  - ✅ Use `Button` from `@/components/ui` for menu items
364
343
  - ✅ Use props (`color`, `size`, `variant`) NOT className for styles
365
344
  - ✅ className ONLY for layout (`hidden`, `lg:flex`, `bg-black`)
366
345
  - ❌ DON'T use custom `<header>` or `<nav>` tags
367
346
 
368
- ### Form Components
347
+ #### Dropdown Menus in Navbar
348
+ **CRITICAL**: Always use HeroUI Dropdown components for dropdown menus:
369
349
 
350
+ ```tsx
351
+ import {
352
+ Dropdown,
353
+ DropdownTrigger,
354
+ DropdownMenu,
355
+ DropdownItem,
356
+ } from '@heroui/react';
357
+ import { Button, Icon } from '@/components/ui';
358
+
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}>
373
+ {t(subItem.labelKey)}
374
+ </DropdownItem>
375
+ ))}
376
+ </DropdownMenu>
377
+ </Dropdown>
378
+ ) : (
379
+ <Button variant="light">
380
+ {t(item.labelKey)}
381
+ </Button>
382
+ )}
383
+ ```
384
+
385
+ **Example Menu Configuration** (`src/config/menuItems.ts`):
386
+ ```tsx
387
+ export type MenuItem = {
388
+ key: string;
389
+ labelKey: 'product' | 'useCases' | 'resources' | 'company' | 'pricing';
390
+ href?: string;
391
+ hasDropdown?: boolean;
392
+ items?: Array<{
393
+ key: string;
394
+ labelKey: string;
395
+ href: string;
396
+ }>;
397
+ };
398
+
399
+ export const navbarMenuItems: MenuItem[] = [
400
+ {
401
+ key: 'product',
402
+ labelKey: 'product',
403
+ hasDropdown: true,
404
+ 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 },
408
+ ],
409
+ },
410
+ {
411
+ key: 'pricing',
412
+ labelKey: 'pricing',
413
+ href: NAVIGATION_URLS.ROOT,
414
+ },
415
+ ];
416
+ ```
417
+
418
+ **Key Points**:
419
+ - ✅ Always check `items && items.length > 0` before rendering dropdown
420
+ - ✅ Use `Icon` component with proper name (e.g., `ChevronDownIcon`)
421
+ - ✅ Use `endContent` prop for icons in buttons
422
+ - ✅ Add `aria-label` to DropdownMenu for accessibility
423
+ - ✅ Map menu items from config constants, never hardcode
424
+ - ✅ Use union types for `labelKey` to ensure type safety
425
+ - ❌ DON'T render dropdown without checking array exists
426
+
427
+ ### Form Components
370
428
  All located in `src/components/ui/`:
371
429
 
372
430
  #### Input Fields
373
-
374
431
  ```tsx
375
432
  import { Input, PasswordInput, NumberInput, Textarea } from '@/components/ui';
376
433
 
@@ -406,7 +463,6 @@ import { Input, PasswordInput, NumberInput, Textarea } from '@/components/ui';
406
463
  ```
407
464
 
408
465
  #### Selection Components
409
-
410
466
  ```tsx
411
467
  import { Select, RadioGroup, Checkbox, Autocomplete } from '@/components/ui';
412
468
 
@@ -439,18 +495,16 @@ import { Select, RadioGroup, Checkbox, Autocomplete } from '@/components/ui';
439
495
  ```
440
496
 
441
497
  #### Date & Time
442
-
443
498
  ```tsx
444
- import { DatePicker } from "@/components/ui";
499
+ import { DatePicker } from '@/components/ui';
445
500
 
446
501
  <DatePicker
447
502
  label="Select Date"
448
503
  placeholderValue={new CalendarDate(2024, 1, 1)}
449
- />;
504
+ />
450
505
  ```
451
506
 
452
507
  #### Buttons
453
-
454
508
  ```tsx
455
509
  import { Button } from '@/components/ui';
456
510
 
@@ -468,7 +522,6 @@ import { Button } from '@/components/ui';
468
522
  ```
469
523
 
470
524
  #### Other Components
471
-
472
525
  ```tsx
473
526
  import { Modal, Chip, Breadcrumbs, Tabs, Icon } from '@/components/ui';
474
527
 
@@ -508,32 +561,34 @@ import { Modal, Chip, Breadcrumbs, Tabs, Icon } from '@/components/ui';
508
561
  **CRITICAL WORKFLOW**: Icons must follow this exact process:
509
562
 
510
563
  #### Step 1: Export SVG from Figma
511
-
512
564
  1. Select the icon in Figma design
513
565
  2. Export as SVG (not PNG/JPG)
514
566
  3. Download the SVG file
515
567
 
516
568
  #### Step 2: Place in Icons Folder
517
-
518
569
  ```bash
519
570
  # Place SVG file in src/assets/icons/
520
571
  mv downloaded-icon.svg src/assets/icons/icon-name.svg
521
572
  ```
522
573
 
523
574
  #### Step 3: Generate React Components
524
-
525
575
  ```bash
526
576
  # Run the icon generation script
527
577
  pnpm generate-icons
528
578
  ```
529
579
 
530
580
  This command will:
531
-
532
581
  - Convert all SVG files in `src/assets/icons/` to React components
533
582
  - Place them in `src/components/icons/`
583
+ - **Automatically add "Icon" suffix** to all component names (configured in `svgr.config.mjs`)
534
584
  - Auto-format and lint the generated code
535
585
  - Update `src/components/icons/index.ts` with exports
536
586
 
587
+ **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
591
+
537
592
  #### Step 4: Use in Code
538
593
 
539
594
  **CORRECT USAGE**: Use the `Icon` component with `name` prop (PascalCase):
@@ -548,7 +603,6 @@ import { Icon } from '@/components/ui';
548
603
  ```
549
604
 
550
605
  **❌ WRONG USAGE - DO NOT import individual icon components**:
551
-
552
606
  ```tsx
553
607
  // ❌ WRONG - Don't import and use individual icon components
554
608
  import { ChevronDownIcon, CloseIcon } from '@/components/icons';
@@ -557,7 +611,6 @@ import { ChevronDownIcon, CloseIcon } from '@/components/icons';
557
611
  ```
558
612
 
559
613
  **Available Icons** (auto-generated):
560
-
561
614
  - ChevronDownIcon, ChevronRightIcon
562
615
  - CloseIcon, MenuIcon
563
616
  - EyeIcon, EyeSlashIcon
@@ -567,13 +620,11 @@ import { ChevronDownIcon, CloseIcon } from '@/components/icons';
567
620
  - And more...
568
621
 
569
622
  **Icon Names**:
570
-
571
623
  - Icon names are PascalCase with "Icon" suffix (e.g., `ChevronDownIcon`)
572
624
  - Generated from SVG filename: `chevron-down.svg` → component `ChevronDownIcon`
573
625
  - The Icon component uses the exact component name from `@/components/icons`
574
626
 
575
627
  **❌ DO NOT**:
576
-
577
628
  - Import individual icon components directly
578
629
  - Use kebab-case names (use `ChevronDownIcon` not `chevron-down`)
579
630
  - Use Lucide, Font Awesome, or other icon libraries
@@ -582,7 +633,6 @@ import { ChevronDownIcon, CloseIcon } from '@/components/icons';
582
633
  - Hardcode SVG paths directly in components
583
634
 
584
635
  **✅ DO**:
585
-
586
636
  - Always use `<Icon name="IconName" />` pattern with PascalCase
587
637
  - Always export from Figma as SVG
588
638
  - Use `pnpm generate-icons` to create components
@@ -595,7 +645,6 @@ import { ChevronDownIcon, CloseIcon } from '@/components/icons';
595
645
  #### Step 1: Check Existing Images First
596
646
 
597
647
  **BEFORE implementing or exporting from Figma**:
598
-
599
648
  1. Check `public/images/index.ts` to see if the image/logo already exists
600
649
  2. Check `public/images/logos/` directory for available logo files
601
650
  3. Only export from Figma if the asset doesn't exist
@@ -607,19 +656,16 @@ ls public/images/logos/
607
656
  ```
608
657
 
609
658
  **Why this matters**:
610
-
611
659
  - Avoid duplicate assets
612
660
  - User may have already exported the assets
613
661
  - Maintain consistency with existing naming conventions
614
662
 
615
663
  #### Step 2: Export from Figma (if needed)
616
-
617
664
  1. **For logos**: Export as SVG (preferred) or PNG if source is raster
618
665
  2. **For images**: Export as PNG, JPG, or WebP based on image type
619
666
  3. Use appropriate resolution (2x or 3x for retina displays)
620
667
 
621
668
  #### Step 3: Place in Public Folder
622
-
623
669
  ```bash
624
670
  # Place logo/image files in public/
625
671
  public/
@@ -645,36 +691,36 @@ public/
645
691
  */
646
692
 
647
693
  const LOGOS = {
648
- PRIMARY_CIRCLE: "/images/logos/logo-circle-primary.svg",
649
- SECONDARY_CIRCLE: "/images/logos/logo-circle-secondary.svg",
650
- FULL: "/images/logos/logo-full.svg",
651
- FULL_BLACK: "/images/logos/logo-full-black.svg",
652
- FULL_WHITE: "/images/logos/logo-full-white.svg",
653
- ICON: "/images/logos/logo-icon.svg",
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',
654
700
  } as const;
655
701
 
656
702
  const AUTH = {
657
- LOGIN_BG: "/images/auth/login-background.jpg",
658
- SIGNUP_BG: "/images/auth/signup-background.jpg",
659
- RESET_PASSWORD: "/images/auth/reset-password.jpg",
703
+ LOGIN_BG: '/images/auth/login-background.jpg',
704
+ SIGNUP_BG: '/images/auth/signup-background.jpg',
705
+ RESET_PASSWORD: '/images/auth/reset-password.jpg',
660
706
  } as const;
661
707
 
662
708
  const WEBSITE = {
663
- HOME_HERO: "/images/website/home-hero.webp",
664
- HOME_NEWSLETTER: "/images/website/home-newsletter.webp",
665
- ABOUT_HEADER: "/images/website/about-header.jpg",
666
- CONTACT_MAP: "/images/website/contact-map.png",
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',
667
713
  } as const;
668
714
 
669
715
  const SERVICES = {
670
- HEADER: "/images/services/services-header.webp",
671
- FEATURE_1: "/images/services/feature-1.jpg",
672
- FEATURE_2: "/images/services/feature-2.jpg",
716
+ HEADER: '/images/services/services-header.webp',
717
+ FEATURE_1: '/images/services/feature-1.jpg',
718
+ FEATURE_2: '/images/services/feature-2.jpg',
673
719
  } as const;
674
720
 
675
721
  const PRODUCTS = {
676
- THUMBNAIL_DEFAULT: "/images/products/thumbnail-default.png",
677
- HERO: "/images/products/hero-banner.jpg",
722
+ THUMBNAIL_DEFAULT: '/images/products/thumbnail-default.png',
723
+ HERO: '/images/products/hero-banner.jpg',
678
724
  } as const;
679
725
 
680
726
  export const IMAGES = {
@@ -688,18 +734,28 @@ export const IMAGES = {
688
734
 
689
735
  #### Step 5: Reference in Code
690
736
 
737
+ **CRITICAL: ALWAYS import and use IMAGES constant - NEVER hardcode paths**
738
+
691
739
  ```tsx
692
- // Import from centralized constants
740
+ // ✅ CORRECT - Import from centralized constants
693
741
  import { IMAGES } from '@/config/images';
694
742
  import Image from 'next/image';
695
743
 
696
744
  // Using Next.js Image component (recommended)
697
745
  <Image
698
- src={IMAGES.LOGOS.FULL}
699
- alt="Company Logo"
700
- width={120}
701
- height={40}
702
- priority
746
+ src={IMAGES.LOGOS.BINA} // ✅ Use constant
747
+ alt="BINA"
748
+ width={54}
749
+ height={41}
750
+ className="h-10 w-auto"
751
+ />
752
+
753
+ // ❌ WRONG - Hardcoded path
754
+ <Image
755
+ src="/images/logos/bina.png" // ❌ Don't hardcode
756
+ alt="BINA"
757
+ width={54}
758
+ height={41}
703
759
  />
704
760
 
705
761
  // Using standard img tag (for SVGs with CSS control)
@@ -718,22 +774,20 @@ import Image from 'next/image';
718
774
  ```
719
775
 
720
776
  **Preference Order**:
721
-
722
777
  1. ✅ **SVG** - Best for logos, icons, and vector graphics (scalable, small file size)
723
778
  2. ✅ **WebP** - Modern format for photos (smaller than PNG/JPG)
724
779
  3. ✅ **PNG** - For images requiring transparency
725
780
  4. ✅ **JPG** - For photos without transparency
726
781
 
727
782
  **❌ DO NOT**:
728
-
729
783
  - Put images in `src/` folder
730
784
  - Import images as modules unless necessary
731
785
  - Use base64 encoded images inline
732
786
  - Forget to optimize images before adding
733
- - Hardcode image paths directly in components (use centralized constants)
787
+ - **CRITICAL**: Hardcode image paths directly in components - MUST use `IMAGES` constant from `@/config/images`
788
+ - Use hardcoded strings like `src="/images/logos/bina.png"` - Use `src={IMAGES.LOGOS.BINA}` instead
734
789
 
735
790
  **✅ DO**:
736
-
737
791
  - Always place in `public/` directory
738
792
  - Create centralized image constants file (src/config/images.ts)
739
793
  - Organize image paths by category (LOGOS, AUTH, WEBSITE, SERVICES)
@@ -750,30 +804,27 @@ import Image from 'next/image';
750
804
  ### CRITICAL: Use Theme Colors, NOT Custom Values
751
805
 
752
806
  **Colors are defined in two places**:
753
-
754
807
  1. **`src/styles/hero.ts`** - HeroUI theme colors (primary, secondary, etc.)
755
808
  2. **`src/styles/globals.css`** - Additional custom theme colors
756
809
 
757
810
  ### Available Theme Colors
758
811
 
759
812
  #### From hero.ts (Primary Color Palette):
760
-
761
813
  ```typescript
762
814
  // Primary green shades (defined in hero.ts)
763
- primary - 50; // #E6FFF0 (lightest)
764
- primary - 100; // #CBFFE0
765
- primary - 200; // #AEFFD1
766
- primary - 300; // #8EFFC2
767
- primary - 400; // #66FFB2
768
- primary - 500; // #19FFA3 (default primary)
769
- primary - 600; // #25C780
770
- primary - 700; // #26915F
771
- primary - 800; // #215F40
772
- primary - 900; // #173123 (darkest)
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)
773
825
  ```
774
826
 
775
827
  #### HeroUI Default Colors:
776
-
777
828
  ```tsx
778
829
  // Semantic colors (built into HeroUI)
779
830
  bg-primary text-primary border-primary
@@ -789,7 +840,6 @@ bg-background text-background border-background
789
840
  ### Color Usage Examples
790
841
 
791
842
  **✅ CORRECT - Use theme colors**:
792
-
793
843
  ```tsx
794
844
  // In component configuration (NO hover states)
795
845
  color: {
@@ -803,7 +853,6 @@ className="bg-primary-50 text-primary-900"
803
853
  ```
804
854
 
805
855
  **❌ WRONG - Custom color values or hover states**:
806
-
807
856
  ```tsx
808
857
  // DON'T use hex values or hover states in config
809
858
  color: {
@@ -823,13 +872,11 @@ color: {
823
872
  ### When to Add Custom Colors
824
873
 
825
874
  **Only add custom colors to hero.ts if**:
826
-
827
875
  1. Color is NOT in the existing palette
828
876
  2. Color is used in multiple places (reusable)
829
877
  3. Color is part of the design system
830
878
 
831
879
  **Steps to add custom color**:
832
-
833
880
  ```typescript
834
881
  // 1. Add to hero.ts theme
835
882
  export default heroui({
@@ -838,9 +885,9 @@ export default heroui({
838
885
  colors: {
839
886
  // Add new color palette
840
887
  accent: {
841
- 50: "#...",
842
- 500: "#...",
843
- 900: "#...",
888
+ 50: '#...',
889
+ 500: '#...',
890
+ 900: '#...',
844
891
  },
845
892
  },
846
893
  },
@@ -848,7 +895,7 @@ export default heroui({
848
895
  });
849
896
 
850
897
  // 2. Use in components
851
- className = "bg-accent text-accent-900";
898
+ className="bg-accent text-accent-900"
852
899
  ```
853
900
 
854
901
  ---
@@ -860,23 +907,21 @@ className = "bg-accent text-accent-900";
860
907
  **CRITICAL**: Always use closest standard Tailwind class instead of custom arbitrary values
861
908
 
862
909
  **Common Conversions**:
863
-
864
910
  ```tsx
865
911
  // ❌ WRONG - Custom arbitrary values
866
- className = "h-[41px] w-[54.6px]";
867
- className = "p-[24px]";
868
- className = "text-[14px]";
869
- className = "gap-[11px]";
912
+ className="h-[41px] w-[54.6px]"
913
+ className="p-[24px]"
914
+ className="text-[14px]"
915
+ className="gap-[11px]"
870
916
 
871
917
  // ✅ CORRECT - Standard Tailwind classes
872
- className = "h-10 w-14"; // h-10 = 40px, w-14 = 56px (closest to 54.6px)
873
- className = "p-6"; // p-6 = 24px
874
- className = "text-sm"; // text-sm = 14px
875
- className = "gap-3"; // gap-3 = 12px (closest to 11px)
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)
876
922
  ```
877
923
 
878
924
  **Tailwind Size Reference**:
879
-
880
925
  ```css
881
926
  /* Spacing Scale (padding, margin, gap, etc.) */
882
927
  0.5 = 2px 4 = 16px 12 = 48px
@@ -900,13 +945,11 @@ auto, full, screen, fit, min, max
900
945
  ```
901
946
 
902
947
  **Only use arbitrary values when**:
903
-
904
948
  - Exact pixel value is required by design system
905
949
  - No standard Tailwind class is close enough
906
950
  - Using design tokens/CSS variables: `bg-[var(--custom-color)]`
907
951
 
908
952
  **Examples**:
909
-
910
953
  ```tsx
911
954
  // ✅ Good - Using standard classes
912
955
  <div className="h-10 w-full p-6 text-sm">
@@ -916,7 +959,6 @@ auto, full, screen, fit, min, max
916
959
  ```
917
960
 
918
961
  ### Responsive Breakpoints (Mobile-First)
919
-
920
962
  ```css
921
963
  /* Mobile */
922
964
  4xs: 320px /* iPhone SE */
@@ -937,7 +979,6 @@ xl: 1280px /* MacBook Air */
937
979
  ```
938
980
 
939
981
  ### Usage Example
940
-
941
982
  ```tsx
942
983
  <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
943
984
  {/* Mobile: 1 column, Tablet: 2 columns, Desktop: 3 columns */}
@@ -945,9 +986,7 @@ xl: 1280px /* MacBook Air */
945
986
  ```
946
987
 
947
988
  ### HeroUI Color System
948
-
949
989
  Use these semantic colors from HeroUI theme:
950
-
951
990
  - `bg-background` - Main background
952
991
  - `bg-foreground` - Text color background
953
992
  - `bg-default` / `bg-default-50` to `bg-default-900` - Gray scale
@@ -958,7 +997,6 @@ Use these semantic colors from HeroUI theme:
958
997
  - `bg-danger` - Error/danger states
959
998
 
960
999
  ### Common Patterns
961
-
962
1000
  ```tsx
963
1001
  // Card
964
1002
  <div className="rounded-lg bg-white p-6 shadow-md">
@@ -982,20 +1020,19 @@ Use these semantic colors from HeroUI theme:
982
1020
  ## 📝 Form Implementation with Zod
983
1021
 
984
1022
  ### Pattern to Follow
985
-
986
1023
  ```tsx
987
- "use client";
1024
+ 'use client';
988
1025
 
989
- import { zodResolver } from "@hookform/resolvers/zod";
990
- import { useForm } from "react-hook-form";
991
- import { z } from "zod";
1026
+ import { zodResolver } from '@hookform/resolvers/zod';
1027
+ import { useForm } from 'react-hook-form';
1028
+ import { z } from 'zod';
992
1029
 
993
- import { Button, Input } from "@/components/ui";
1030
+ import { Button, Input } from '@/components/ui';
994
1031
 
995
1032
  // 1. Define schema
996
1033
  const schema = z.object({
997
- email: z.string().email("Invalid email"),
998
- password: z.string().min(8, "Password must be at least 8 characters"),
1034
+ email: z.string().email('Invalid email'),
1035
+ password: z.string().min(8, 'Password must be at least 8 characters'),
999
1036
  });
1000
1037
 
1001
1038
  type FormData = z.infer<typeof schema>;
@@ -1022,7 +1059,7 @@ export default function LoginForm() {
1022
1059
  <Input
1023
1060
  label="Email"
1024
1061
  type="email"
1025
- {...register("email")}
1062
+ {...register('email')}
1026
1063
  errorMessage={errors.email?.message}
1027
1064
  isInvalid={!!errors.email}
1028
1065
  />
@@ -1030,7 +1067,7 @@ export default function LoginForm() {
1030
1067
  <Input
1031
1068
  label="Password"
1032
1069
  type="password"
1033
- {...register("password")}
1070
+ {...register('password')}
1034
1071
  errorMessage={errors.password?.message}
1035
1072
  isInvalid={!!errors.password}
1036
1073
  />
@@ -1052,20 +1089,18 @@ export default function LoginForm() {
1052
1089
  ### Navigation with i18n
1053
1090
 
1054
1091
  **Import Guidelines**:
1055
-
1056
1092
  ```tsx
1057
1093
  // For Link component - use Next.js Link
1058
- import Link from "next/link";
1094
+ import Link from 'next/link';
1059
1095
 
1060
1096
  // For navigation hooks - use next/navigation
1061
- import { usePathname, useRouter } from "next/navigation";
1097
+ import { usePathname, useRouter } from 'next/navigation';
1062
1098
 
1063
1099
  // For navigation URLs - use centralized constants
1064
- import { NAVIGATION_URLS } from "@/config/navigationUrls";
1100
+ import { NAVIGATION_URLS } from '@/config/navigationUrls';
1065
1101
  ```
1066
1102
 
1067
1103
  **Navigation Example**:
1068
-
1069
1104
  ```tsx
1070
1105
  import Link from 'next/link';
1071
1106
  import { NAVIGATION_URLS } from '@/config/navigationUrls';
@@ -1082,11 +1117,10 @@ import { Link } from '@heroui/react';
1082
1117
  ```
1083
1118
 
1084
1119
  **Using Navigation Hooks**:
1085
-
1086
1120
  ```tsx
1087
- "use client";
1121
+ 'use client';
1088
1122
 
1089
- import { usePathname, useRouter } from "next/navigation";
1123
+ import { usePathname, useRouter } from 'next/navigation';
1090
1124
 
1091
1125
  export function MyComponent() {
1092
1126
  const pathname = usePathname();
@@ -1102,29 +1136,64 @@ export function MyComponent() {
1102
1136
 
1103
1137
  ### Translations for ALL text
1104
1138
 
1139
+ **CRITICAL: Specify namespace to avoid TypeScript errors**
1140
+
1105
1141
  ```tsx
1106
- import { useTranslations } from "next-intl";
1142
+ import { useTranslations } from 'next-intl';
1107
1143
 
1108
1144
  function MyComponent() {
1109
- const t = useTranslations();
1145
+ // CORRECT - Specify namespace for type safety
1146
+ const t = useTranslations('namespace');
1110
1147
 
1111
1148
  return (
1112
1149
  <div>
1113
- {/* CORRECT - Using translation key */}
1114
- <h1>{t("welcome")}</h1>
1115
- <p>{t("description")}</p>
1150
+ {/* Now you can use keys directly without type errors */}
1151
+ <h1>{t('welcome')}</h1>
1152
+ <p>{t('description')}</p>
1153
+ </div>
1154
+ );
1155
+ }
1116
1156
 
1117
- {/* ❌ WRONG - Hardcoded text */}
1118
- <h1>Welcome</h1>
1157
+ // ❌ WRONG - No namespace causes TypeScript errors with dynamic keys
1158
+ function BadComponent() {
1159
+ const t = useTranslations(); // Missing namespace
1160
+
1161
+ const items = [
1162
+ { key: 'product', labelKey: 'navbar.product' }
1163
+ ];
1164
+
1165
+ return (
1166
+ <div>
1167
+ {/* TypeScript error: Argument of type 'string' is not assignable */}
1168
+ {items.map(item => <p key={item.key}>{t(item.labelKey)}</p>)}
1119
1169
  </div>
1120
1170
  );
1121
1171
  }
1122
1172
  ```
1123
1173
 
1124
- ### Form labels, placeholders, errors - ALL must use i18n
1174
+ **Type-Safe Translation Pattern:**
1175
+ ```tsx
1176
+ // 1. Define translation key types in config
1177
+ export type MenuItem = {
1178
+ key: string;
1179
+ labelKey: 'product' | 'useCases' | 'resources'; // Union type of valid keys
1180
+ href?: string;
1181
+ };
1182
+
1183
+ // 2. Use with namespace
1184
+ const t = useTranslations('navbar');
1185
+
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
+ ))}
1192
+ ```
1125
1193
 
1194
+ ### Form labels, placeholders, errors - ALL must use i18n
1126
1195
  ```tsx
1127
- import { useTranslations } from "next-intl";
1196
+ import { useTranslations } from 'next-intl';
1128
1197
 
1129
1198
  function LoginForm() {
1130
1199
  const t = useTranslations();
@@ -1133,11 +1202,9 @@ function LoginForm() {
1133
1202
  <form>
1134
1203
  {/* ✅ CORRECT */}
1135
1204
  <Input
1136
- label={t("email")}
1137
- placeholder={t("enterEmail")}
1138
- errorMessage={
1139
- errors.email?.message ? t(errors.email.message) : undefined
1140
- }
1205
+ label={t('email')}
1206
+ placeholder={t('enterEmail')}
1207
+ errorMessage={errors.email?.message ? t(errors.email.message) : undefined}
1141
1208
  />
1142
1209
 
1143
1210
  {/* ❌ WRONG - Hardcoded text */}
@@ -1152,7 +1219,6 @@ function LoginForm() {
1152
1219
  ```
1153
1220
 
1154
1221
  ### Navigation URLs Reference
1155
-
1156
1222
  ```tsx
1157
1223
  import { NAVIGATION_URLS } from '@/config/navigationUrls';
1158
1224
 
@@ -1177,20 +1243,19 @@ NAVIGATION_URLS.DASHBOARD.INDEX // '/dashboard'
1177
1243
  ## 🎯 Data Fetching
1178
1244
 
1179
1245
  ### Using React Query
1180
-
1181
1246
  ```tsx
1182
- "use client";
1247
+ 'use client';
1183
1248
 
1184
- import { useQuery } from "@tanstack/react-query";
1185
- import axios from "axios";
1249
+ import { useQuery } from '@tanstack/react-query';
1250
+ import axios from 'axios';
1186
1251
 
1187
- import { QUERY_KEYS } from "@/libs/react-query";
1252
+ import { QUERY_KEYS } from '@/libs/react-query';
1188
1253
 
1189
1254
  export default function ProductList() {
1190
1255
  const { data, isLoading, error } = useQuery({
1191
1256
  queryKey: QUERY_KEYS.PRODUCTS.LIST,
1192
1257
  queryFn: async () => {
1193
- const response = await axios.get("/api/products");
1258
+ const response = await axios.get('/api/products');
1194
1259
  return response.data;
1195
1260
  },
1196
1261
  });
@@ -1213,12 +1278,11 @@ export default function ProductList() {
1213
1278
  ## 📐 Layout Components
1214
1279
 
1215
1280
  ### Using Existing Layouts
1216
-
1217
1281
  ```tsx
1218
1282
  // Auth pages use auth layout automatically
1219
1283
  // Location: src/app/[locale]/(auth)/login/page.tsx
1220
1284
 
1221
- "use client";
1285
+ 'use client';
1222
1286
 
1223
1287
  export default function LoginPage() {
1224
1288
  return (
@@ -1231,14 +1295,11 @@ export default function LoginPage() {
1231
1295
  ```
1232
1296
 
1233
1297
  ### Navbar & Footer
1234
-
1235
1298
  Already implemented in `src/components/layout/`:
1236
-
1237
1299
  - `Navbar.tsx` - Main navigation using HeroUI Navbar
1238
1300
  - `Footer.tsx` - Footer component
1239
1301
 
1240
1302
  **CRITICAL**: Navbar uses HeroUI Navbar component:
1241
-
1242
1303
  ```tsx
1243
1304
  import { Navbar } from '@/components/layout';
1244
1305
 
@@ -1247,29 +1308,32 @@ import { Navbar } from '@/components/layout';
1247
1308
  <main>{children}</main>
1248
1309
  ```
1249
1310
 
1250
- **Implementation details** (see `src/components/layout/Navbar.tsx`):
1251
-
1252
- - ✅ Uses HeroUI `Navbar`, `NavbarBrand`, `NavbarContent`, `NavbarItem`
1311
+ **Implementation details** (see `src/components/layout/Navbar.tsx` and `docs/NAVBAR_IMPLEMENTATION.md`):
1312
+ - ✅ Uses HeroUI `Navbar`, `NavbarBrand`, `NavbarContent`, `NavbarItem`, `Dropdown`
1253
1313
  - ✅ Uses `Button` from `@/components/ui` with props (`color`, `size`, `variant`)
1314
+ - ✅ Uses `useTranslations('navbar')` with namespace for type safety
1315
+ - ✅ Menu items mapped from `src/config/menuItems.ts` with typed `labelKey`
1316
+ - ✅ Dropdown menus with HeroUI `Dropdown`, `DropdownTrigger`, `DropdownMenu`
1254
1317
  - ✅ All styles via props, NO className for component styles
1255
1318
  - ✅ className ONLY for layout utilities
1319
+ - ✅ NO `any` types - uses union types for translation keys
1256
1320
 
1257
1321
  ---
1258
1322
 
1259
1323
  ## ⚠️ CRITICAL RULES
1260
1324
 
1261
1325
  ### ❌ DO NOT
1262
-
1263
1326
  1. ❌ **Figma**: Use screenshots to implement design - MUST use Figma MCP server with `get_design_context`
1264
1327
  2. ❌ **Figma**: Call `get_screenshot` tool - Design context provides all needed information
1265
1328
  3. ❌ **Icons**: Import individual icon components (e.g., `import { ChevronDownIcon }`) - MUST use `<Icon name="ChevronDownIcon" />`
1266
1329
  4. ❌ **Icons**: Create manual icon components - MUST use `pnpm generate-icons` workflow
1267
1330
  5. ❌ **Icons**: Use non-project icons (Lucide, Font Awesome, etc.)
1268
- 6. ❌ **Logos**: Put logos/images in `src/` folder - MUST go in `public/`
1269
- 7. ❌ **Logos**: Import images as modules unless necessary
1270
- 8. ❌ **Logos**: Hardcode image paths in components - MUST use centralized constants from `@/config/images`
1271
- 9. ❌ **Tailwind**: Use arbitrary values when standard classes exist (e.g., `h-[40px]` use `h-10`)
1272
- 10. ❌ **Tailwind**: Use custom values like `w-[100%]` (use `w-full`)
1331
+ 6. ❌ **Images**: Put logos/images in `src/` folder - MUST go in `public/`
1332
+ 7. ❌ **Images**: Import images as modules unless necessary
1333
+ 8. ❌ **Images**: **CRITICAL** - Hardcode image/video paths (e.g., `src="/images/logos/bina.png"`) - MUST use `IMAGES` constant
1334
+ 9. ❌ **Images**: Use direct path strings anywhere - ALL paths MUST come from `@/config/images`
1335
+ 10. ❌ **Tailwind**: Use arbitrary values when standard classes exist (e.g., `h-[40px]` use `h-10`)
1336
+ 11. ❌ **Tailwind**: Use custom values like `w-[100%]` (use `w-full`)
1273
1337
  11. ❌ **Colors**: Use custom color values (e.g., `bg-[#19ffa3]`, `text-[#ff0000]`) - MUST use theme colors from hero.ts
1274
1338
  12. ❌ **Colors**: Use hex, rgb, or hsl values inline - Use semantic color classes instead
1275
1339
  13. ❌ **Text**: Hardcode ANY text - ALL text MUST use i18n translation keys
@@ -1283,24 +1347,28 @@ import { Navbar } from '@/components/layout';
1283
1347
  21. ❌ **Imports**: Import from `@heroui/react` directly (use `@/components/ui` wrappers when available)
1284
1348
  22. ❌ **Navigation**: Use HeroUI `Link` for internal navigation (use Next.js `Link` from `next/link`)
1285
1349
  23. ❌ **Navigation**: Import `usePathname`, `useRouter` from wrong source (MUST use `next/navigation`)
1286
- 24. ❌ **TypeScript**: Use `any` type
1287
- 25. ❌ **Design**: Ignore responsive design (always implement mobile-first)
1288
- 26. ❌ **Forms**: Skip form validation (always use Zod schemas)
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
1289
1357
 
1290
1358
  ### ✅ DO
1291
-
1292
1359
  1. ✅ **Figma**: Use Figma MCP server with `get_design_context` and node-id from Figma URL
1293
1360
  2. ✅ **Figma**: Extract node-id from URL (e.g., `node-id=8486-1580` → `"8486:1580"`)
1294
1361
  3. ✅ **Icons**: Export SVG from Figma → `src/assets/icons/` → Run `pnpm generate-icons`
1295
1362
  4. ✅ **Icons**: Use `<Icon name="IconName" />` pattern with PascalCase - NEVER import individual icon components
1296
- 5. ✅ **Logos**: Check `public/images/index.ts` BEFORE exporting from Figma
1297
- 6. ✅ **Logos**: Check `public/images/logos/` directory for existing assets
1298
- 7. ✅ **Logos**: Export SVG/PNG from Figma ONLY if not existing → Place in `public/images/` with organized folders
1299
- 8. ✅ **Logos**: Create centralized constants file `src/config/images.ts` with LOGOS, AUTH, WEBSITE, etc.
1300
- 9. ✅ **Logos**: Import from `@/config/images` and use `IMAGES.LOGOS.PRIMARY`
1301
- 10. ✅ **Logos**: Prefer SVG over PNG when source is vector
1302
- 11. ✅ **Tailwind**: Use standard classes (`h-10`, `p-6`, `text-sm` instead of arbitrary values)
1303
- 12. ✅ **Tailwind**: Use size utilities (`size-4`, `size-5`) for icons
1363
+ 5. ✅ **Images**: Check `public/images/index.ts` BEFORE exporting from Figma
1364
+ 6. ✅ **Images**: Check `public/images/logos/` directory for existing assets
1365
+ 7. ✅ **Images**: Export SVG/PNG from Figma ONLY if not existing → Place in `public/images/` with organized folders
1366
+ 8. ✅ **Images**: **CRITICAL** - Create/update `src/config/images.ts` with ALL image paths
1367
+ 9. ✅ **Images**: **ALWAYS** import from `@/config/images` and use `IMAGES.LOGOS.BINA` (NEVER hardcode)
1368
+ 10. ✅ **Images**: Add new images to centralized config immediately
1369
+ 11. ✅ **Images**: Prefer SVG over PNG when source is vector
1370
+ 12. ✅ **Tailwind**: Use standard classes (`h-10`, `p-6`, `text-sm` instead of arbitrary values)
1371
+ 13. ✅ **Tailwind**: Use size utilities (`size-4`, `size-5`) for icons
1304
1372
  13. ✅ **Colors**: Use theme colors from hero.ts (`bg-primary`, `text-primary-600`, `bg-success`)
1305
1373
  14. ✅ **Colors**: Check hero.ts and globals.css for available colors before using custom values
1306
1374
  15. ✅ **Navigation**: Use Next.js `Link` from `next/link` for internal navigation
@@ -1316,11 +1384,15 @@ import { Navbar } from '@/components/layout';
1316
1384
  25. ✅ **Styling**: Omit props that match defaultVariants (e.g., don't write `size="md"` if `md` is default)
1317
1385
  26. ✅ **Styling**: Use className ONLY for layout utilities (`mt-4`, `hidden`, `lg:flex`)
1318
1386
  27. ✅ **Styling**: Use Tailwind CSS ONLY (utility classes)
1319
- 28. ✅ **TypeScript**: Implement strict typing with proper types
1320
- 29. ✅ **React**: Use `'use client'` directive for interactive components
1321
- 30. ✅ **Design**: Follow mobile-first responsive design
1322
- 31. ✅ **States**: Implement proper loading and error states
1323
- 32. ✅ **Patterns**: Follow existing code patterns and naming conventions
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
1324
1396
 
1325
1397
  ---
1326
1398
 
@@ -1329,7 +1401,6 @@ import { Navbar } from '@/components/layout';
1329
1401
  When converting Figma to code, ensure:
1330
1402
 
1331
1403
  ### Icons & Assets
1332
-
1333
1404
  - [ ] Exported icons as SVG from Figma
1334
1405
  - [ ] Placed SVG files in `src/assets/icons/`
1335
1406
  - [ ] Ran `pnpm generate-icons` to create React components
@@ -1344,7 +1415,6 @@ When converting Figma to code, ensure:
1344
1415
  - [ ] Referenced via `IMAGES.LOGOS.PRIMARY` (not hardcoded paths)
1345
1416
 
1346
1417
  ### Component & Styling
1347
-
1348
1418
  - [ ] Checked HeroUI library first for component availability
1349
1419
  - [ ] Used HeroUI components via `src/components/ui/` wrappers (e.g., `<Button>` not `<button>`)
1350
1420
  - [ ] Configured component styles in wrapper/theme (not inline)
@@ -1355,7 +1425,6 @@ When converting Figma to code, ensure:
1355
1425
  - [ ] Mapped all data from constants (no hardcoded menu items/dropdowns)
1356
1426
 
1357
1427
  ### Content & Navigation
1358
-
1359
1428
  - [ ] ALL text uses i18n translation keys (no hardcoded text)
1360
1429
  - [ ] ALL labels use `t('labelKey')`
1361
1430
  - [ ] ALL placeholders use `t('placeholderKey')`
@@ -1364,21 +1433,18 @@ When converting Figma to code, ensure:
1364
1433
  - [ ] ALL URLs use `NAVIGATION_URLS` from config (no hardcoded URLs)
1365
1434
 
1366
1435
  ### Structure & Types
1367
-
1368
1436
  - [ ] Page created in correct location (`src/app/[locale]/...`)
1369
1437
  - [ ] Added TypeScript types for all data structures
1370
1438
  - [ ] Used `'use client'` for interactive components
1371
1439
  - [ ] No `any` types used
1372
1440
 
1373
1441
  ### Forms & Validation
1374
-
1375
1442
  - [ ] Implemented forms with Zod validation schemas
1376
1443
  - [ ] Form labels use i18n
1377
1444
  - [ ] Form placeholders use i18n
1378
1445
  - [ ] Form errors use i18n
1379
1446
 
1380
1447
  ### Responsive & States
1381
-
1382
1448
  - [ ] Implemented responsive design (mobile-first)
1383
1449
  - [ ] Added proper loading states
1384
1450
  - [ ] Added proper error states
@@ -1391,14 +1457,12 @@ When converting Figma to code, ensure:
1391
1457
  Before finalizing code, verify:
1392
1458
 
1393
1459
  ### Icons & Assets
1394
-
1395
1460
  1. **Icons workflow** - All icons created via `pnpm generate-icons` (not manual)
1396
1461
  2. **Icons source** - SVG files exist in `src/assets/icons/`
1397
1462
  3. **Logos location** - All logos/images in `public/` directory (not `src/`)
1398
1463
  4. **Image format** - SVG used for logos when possible (not PNG)
1399
1464
 
1400
1465
  ### Components & Styling
1401
-
1402
1466
  1. **HeroUI components first** - Verify HeroUI library was checked before custom implementation
1403
1467
  2. **No direct HeroUI imports** - Only through `@/components/ui`
1404
1468
  3. **Component reuse** - Don't duplicate existing components
@@ -1408,20 +1472,17 @@ Before finalizing code, verify:
1408
1472
  7. **Map from constants** - All menu items, dropdown options mapped from config files
1409
1473
 
1410
1474
  ### i18n & Navigation
1411
-
1412
1475
  5. **Zero hardcoded text** - ALL text uses `t('key')`
1413
1476
  6. **Zero hardcoded URLs** - ALL links use `NAVIGATION_URLS`
1414
1477
  7. **Form fields i18n** - Labels, placeholders, errors all use translation keys
1415
1478
 
1416
1479
  ### Styling & Layout
1417
-
1418
1480
  8. **Tailwind only** - No CSS modules, no styled-components
1419
1481
  9. **HeroUI theme colors** - Use semantic colors, not arbitrary values
1420
1482
  10. **Consistent spacing** - Use `space-y-*` and `space-x-*` utilities
1421
1483
  11. **Mobile-first** - Base styles for mobile, then `md:`, `lg:`, etc.
1422
1484
 
1423
1485
  ### TypeScript & Validation
1424
-
1425
1486
  12. **Proper TypeScript** - No `any`, all props typed
1426
1487
  13. **Form validation** - Zod schemas for all forms
1427
1488
 
@@ -1430,7 +1491,6 @@ Before finalizing code, verify:
1430
1491
  ## 📚 Reference Files
1431
1492
 
1432
1493
  When in doubt, check these example files:
1433
-
1434
1494
  - **Form example**: `src/components/ui/form/Form.tsx`
1435
1495
  - **Page example**: `src/app/[locale]/(auth)/login/page.tsx`
1436
1496
  - **Component example**: `src/components/ui/Input.tsx`
@@ -1442,7 +1502,6 @@ When in doubt, check these example files:
1442
1502
  ## 🚀 Quick Reference Guide
1443
1503
 
1444
1504
  ### Icons Workflow
1445
-
1446
1505
  ```bash
1447
1506
  # 1. Export SVG from Figma
1448
1507
  # 2. Place in folder
@@ -1457,7 +1516,6 @@ import { IconIcon } from '@/components/icons';
1457
1516
  ```
1458
1517
 
1459
1518
  ### Logos/Images Workflow
1460
-
1461
1519
  ```bash
1462
1520
  # 1. Export SVG/PNG from Figma
1463
1521
  # 2. Place in public with organized folders
@@ -1479,15 +1537,17 @@ export const IMAGES = {
1479
1537
  WEBSITE,
1480
1538
  } as const;
1481
1539
 
1482
- # 4. Use in code
1540
+ # 4. Use in code - ALWAYS use IMAGES constant
1483
1541
  import { IMAGES } from '@/config/images';
1484
- <img src={IMAGES.LOGOS.PRIMARY} alt="Logo" className="h-10 w-auto" />
1485
- # OR
1486
- <Image src={IMAGES.LOGOS.PRIMARY} alt="Logo" width={120} height={40} />
1542
+
1543
+ # ✅ CORRECT
1544
+ <Image src={IMAGES.LOGOS.BINA} alt="Logo" width={54} height={41} />
1545
+
1546
+ # ❌ WRONG - Hardcoded path
1547
+ <Image src="/images/logos/bina.png" alt="Logo" width={54} height={41} />
1487
1548
  ```
1488
1549
 
1489
1550
  ### Tailwind Standard Classes
1490
-
1491
1551
  ```tsx
1492
1552
  // Heights/Widths
1493
1553
  h-10 = 40px w-14 = 56px size-5 = 20px
@@ -1507,15 +1567,19 @@ text-lg = 18px text-3xl = 30px
1507
1567
  ```
1508
1568
 
1509
1569
  ### Common Patterns
1510
-
1511
1570
  ```tsx
1512
1571
  // Icons (auto-generated)
1513
1572
  import { MenuIcon, CloseIcon } from '@/components/icons';
1514
1573
  <MenuIcon className="size-6 text-white" />
1515
1574
 
1516
- // Logos (centralized constants)
1575
+ // Images & Logos (ALWAYS use IMAGES constant - NEVER hardcode)
1517
1576
  import { IMAGES } from '@/config/images';
1518
- <img src={IMAGES.LOGOS.PRIMARY} alt="Logo" className="h-10 w-auto" />
1577
+
1578
+ // ✅ CORRECT
1579
+ <Image src={IMAGES.LOGOS.BINA} alt="Logo" width={54} height={41} />
1580
+
1581
+ // ❌ WRONG
1582
+ <Image src="/images/logos/bina.png" alt="Logo" />
1519
1583
 
1520
1584
  // Navigation (Next.js Link + constants)
1521
1585
  import Link from 'next/link';