@adlas/create-app 1.0.51 → 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.51",
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",
@@ -45,6 +45,7 @@ mcp__figma-dev-mode-mcp-server__get_design_context({
45
45
  9. **Follow project structure** - Place files in correct locations as defined below
46
46
  10. **Match coding patterns** - Use the same patterns found in existing code
47
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
48
49
 
49
50
  ---
50
51
 
@@ -78,13 +79,16 @@ export const Button = extendVariants(HeroUIButton, {
78
79
  variants: {
79
80
  color: {
80
81
  // ✅ Use theme colors from hero.ts, NOT custom colors
81
- primary: 'bg-primary text-black',
82
+ primary: 'bg-primary-500 text-black',
82
83
  },
83
84
  size: {
84
- sm: 'h-8 px-3 text-xs',
85
+ sm: 'h-10 px-4 text-sm',
85
86
  md: 'h-10 px-4 text-sm',
86
87
  lg: 'h-12 px-6 text-base',
87
88
  },
89
+ radius: {
90
+ full: 'rounded-full',
91
+ },
88
92
  },
89
93
  defaultVariants: {
90
94
  size: 'md',
@@ -166,16 +170,17 @@ const Button = extendVariants(HerouiButton, {
166
170
 
167
171
  // In component usage:
168
172
  <Button
169
- color="primary" // ✅ Specify only when different from default
170
- 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
171
176
  className="mt-4 hidden lg:block" // ✅ Layout utilities only
172
177
  >
173
178
  {t('navbar.bookDemo')} // ✅ i18n text
174
179
  </Button>
175
- // Note: size="md" NOT needed because it's the defaultVariant
180
+ // Note: Omit props that match defaultVariants to keep code clean
176
181
 
177
182
  // Using size prop when you need different size:
178
- <Button color="primary" size="lg"> // ✅ Override default size
183
+ <Button color="primary" size="lg" radius="full"> // ✅ Override default size
179
184
  Large Button
180
185
  </Button>
181
186
 
@@ -339,6 +344,86 @@ import { Button } from '@/components/ui';
339
344
  - ✅ className ONLY for layout (`hidden`, `lg:flex`, `bg-black`)
340
345
  - ❌ DON'T use custom `<header>` or `<nav>` tags
341
346
 
347
+ #### Dropdown Menus in Navbar
348
+ **CRITICAL**: Always use HeroUI Dropdown components for dropdown menus:
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
+
342
427
  ### Form Components
343
428
  All located in `src/components/ui/`:
344
429
 
@@ -495,9 +580,15 @@ pnpm generate-icons
495
580
  This command will:
496
581
  - Convert all SVG files in `src/assets/icons/` to React components
497
582
  - Place them in `src/components/icons/`
583
+ - **Automatically add "Icon" suffix** to all component names (configured in `svgr.config.mjs`)
498
584
  - Auto-format and lint the generated code
499
585
  - Update `src/components/icons/index.ts` with exports
500
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
+
501
592
  #### Step 4: Use in Code
502
593
 
503
594
  **CORRECT USAGE**: Use the `Icon` component with `name` prop (PascalCase):
@@ -643,18 +734,28 @@ export const IMAGES = {
643
734
 
644
735
  #### Step 5: Reference in Code
645
736
 
737
+ **CRITICAL: ALWAYS import and use IMAGES constant - NEVER hardcode paths**
738
+
646
739
  ```tsx
647
- // Import from centralized constants
740
+ // ✅ CORRECT - Import from centralized constants
648
741
  import { IMAGES } from '@/config/images';
649
742
  import Image from 'next/image';
650
743
 
651
744
  // Using Next.js Image component (recommended)
652
745
  <Image
653
- src={IMAGES.LOGOS.FULL}
654
- alt="Company Logo"
655
- width={120}
656
- height={40}
657
- 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}
658
759
  />
659
760
 
660
761
  // Using standard img tag (for SVGs with CSS control)
@@ -683,7 +784,8 @@ import Image from 'next/image';
683
784
  - Import images as modules unless necessary
684
785
  - Use base64 encoded images inline
685
786
  - Forget to optimize images before adding
686
- - 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
687
789
 
688
790
  **✅ DO**:
689
791
  - Always place in `public/` directory
@@ -1033,25 +1135,62 @@ export function MyComponent() {
1033
1135
  ```
1034
1136
 
1035
1137
  ### Translations for ALL text
1138
+
1139
+ **CRITICAL: Specify namespace to avoid TypeScript errors**
1140
+
1036
1141
  ```tsx
1037
1142
  import { useTranslations } from 'next-intl';
1038
1143
 
1039
1144
  function MyComponent() {
1040
- const t = useTranslations();
1145
+ // CORRECT - Specify namespace for type safety
1146
+ const t = useTranslations('namespace');
1041
1147
 
1042
1148
  return (
1043
1149
  <div>
1044
- {/* CORRECT - Using translation key */}
1150
+ {/* Now you can use keys directly without type errors */}
1045
1151
  <h1>{t('welcome')}</h1>
1046
1152
  <p>{t('description')}</p>
1153
+ </div>
1154
+ );
1155
+ }
1047
1156
 
1048
- {/* ❌ WRONG - Hardcoded text */}
1049
- <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>)}
1050
1169
  </div>
1051
1170
  );
1052
1171
  }
1053
1172
  ```
1054
1173
 
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
+ ```
1193
+
1055
1194
  ### Form labels, placeholders, errors - ALL must use i18n
1056
1195
  ```tsx
1057
1196
  import { useTranslations } from 'next-intl';
@@ -1169,11 +1308,15 @@ import { Navbar } from '@/components/layout';
1169
1308
  <main>{children}</main>
1170
1309
  ```
1171
1310
 
1172
- **Implementation details** (see `src/components/layout/Navbar.tsx`):
1173
- - ✅ 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`
1174
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`
1175
1317
  - ✅ All styles via props, NO className for component styles
1176
1318
  - ✅ className ONLY for layout utilities
1319
+ - ✅ NO `any` types - uses union types for translation keys
1177
1320
 
1178
1321
  ---
1179
1322
 
@@ -1185,11 +1328,12 @@ import { Navbar } from '@/components/layout';
1185
1328
  3. ❌ **Icons**: Import individual icon components (e.g., `import { ChevronDownIcon }`) - MUST use `<Icon name="ChevronDownIcon" />`
1186
1329
  4. ❌ **Icons**: Create manual icon components - MUST use `pnpm generate-icons` workflow
1187
1330
  5. ❌ **Icons**: Use non-project icons (Lucide, Font Awesome, etc.)
1188
- 6. ❌ **Logos**: Put logos/images in `src/` folder - MUST go in `public/`
1189
- 7. ❌ **Logos**: Import images as modules unless necessary
1190
- 8. ❌ **Logos**: Hardcode image paths in components - MUST use centralized constants from `@/config/images`
1191
- 9. ❌ **Tailwind**: Use arbitrary values when standard classes exist (e.g., `h-[40px]` use `h-10`)
1192
- 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`)
1193
1337
  11. ❌ **Colors**: Use custom color values (e.g., `bg-[#19ffa3]`, `text-[#ff0000]`) - MUST use theme colors from hero.ts
1194
1338
  12. ❌ **Colors**: Use hex, rgb, or hsl values inline - Use semantic color classes instead
1195
1339
  13. ❌ **Text**: Hardcode ANY text - ALL text MUST use i18n translation keys
@@ -1203,23 +1347,28 @@ import { Navbar } from '@/components/layout';
1203
1347
  21. ❌ **Imports**: Import from `@heroui/react` directly (use `@/components/ui` wrappers when available)
1204
1348
  22. ❌ **Navigation**: Use HeroUI `Link` for internal navigation (use Next.js `Link` from `next/link`)
1205
1349
  23. ❌ **Navigation**: Import `usePathname`, `useRouter` from wrong source (MUST use `next/navigation`)
1206
- 24. ❌ **TypeScript**: Use `any` type
1207
- 25. ❌ **Design**: Ignore responsive design (always implement mobile-first)
1208
- 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
1209
1357
 
1210
1358
  ### ✅ DO
1211
1359
  1. ✅ **Figma**: Use Figma MCP server with `get_design_context` and node-id from Figma URL
1212
1360
  2. ✅ **Figma**: Extract node-id from URL (e.g., `node-id=8486-1580` → `"8486:1580"`)
1213
1361
  3. ✅ **Icons**: Export SVG from Figma → `src/assets/icons/` → Run `pnpm generate-icons`
1214
1362
  4. ✅ **Icons**: Use `<Icon name="IconName" />` pattern with PascalCase - NEVER import individual icon components
1215
- 5. ✅ **Logos**: Check `public/images/index.ts` BEFORE exporting from Figma
1216
- 6. ✅ **Logos**: Check `public/images/logos/` directory for existing assets
1217
- 7. ✅ **Logos**: Export SVG/PNG from Figma ONLY if not existing → Place in `public/images/` with organized folders
1218
- 8. ✅ **Logos**: Create centralized constants file `src/config/images.ts` with LOGOS, AUTH, WEBSITE, etc.
1219
- 9. ✅ **Logos**: Import from `@/config/images` and use `IMAGES.LOGOS.PRIMARY`
1220
- 10. ✅ **Logos**: Prefer SVG over PNG when source is vector
1221
- 11. ✅ **Tailwind**: Use standard classes (`h-10`, `p-6`, `text-sm` instead of arbitrary values)
1222
- 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
1223
1372
  13. ✅ **Colors**: Use theme colors from hero.ts (`bg-primary`, `text-primary-600`, `bg-success`)
1224
1373
  14. ✅ **Colors**: Check hero.ts and globals.css for available colors before using custom values
1225
1374
  15. ✅ **Navigation**: Use Next.js `Link` from `next/link` for internal navigation
@@ -1235,11 +1384,15 @@ import { Navbar } from '@/components/layout';
1235
1384
  25. ✅ **Styling**: Omit props that match defaultVariants (e.g., don't write `size="md"` if `md` is default)
1236
1385
  26. ✅ **Styling**: Use className ONLY for layout utilities (`mt-4`, `hidden`, `lg:flex`)
1237
1386
  27. ✅ **Styling**: Use Tailwind CSS ONLY (utility classes)
1238
- 28. ✅ **TypeScript**: Implement strict typing with proper types
1239
- 29. ✅ **React**: Use `'use client'` directive for interactive components
1240
- 30. ✅ **Design**: Follow mobile-first responsive design
1241
- 31. ✅ **States**: Implement proper loading and error states
1242
- 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
1243
1396
 
1244
1397
  ---
1245
1398
 
@@ -1384,11 +1537,14 @@ export const IMAGES = {
1384
1537
  WEBSITE,
1385
1538
  } as const;
1386
1539
 
1387
- # 4. Use in code
1540
+ # 4. Use in code - ALWAYS use IMAGES constant
1388
1541
  import { IMAGES } from '@/config/images';
1389
- <img src={IMAGES.LOGOS.PRIMARY} alt="Logo" className="h-10 w-auto" />
1390
- # OR
1391
- <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} />
1392
1548
  ```
1393
1549
 
1394
1550
  ### Tailwind Standard Classes
@@ -1416,9 +1572,14 @@ text-lg = 18px text-3xl = 30px
1416
1572
  import { MenuIcon, CloseIcon } from '@/components/icons';
1417
1573
  <MenuIcon className="size-6 text-white" />
1418
1574
 
1419
- // Logos (centralized constants)
1575
+ // Images & Logos (ALWAYS use IMAGES constant - NEVER hardcode)
1420
1576
  import { IMAGES } from '@/config/images';
1421
- <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" />
1422
1583
 
1423
1584
  // Navigation (Next.js Link + constants)
1424
1585
  import Link from 'next/link';