create-flexireact 1.0.1 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/index.js +1311 -233
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -74,11 +74,11 @@ ${c.green} ╰─────────────────────
74
74
  const TEMPLATES = {
75
75
  default: {
76
76
  name: 'Default',
77
- description: 'Basic FlexiReact app with TypeScript and Tailwind',
77
+ description: 'Premium template with modern UI, animations & dark mode',
78
78
  },
79
79
  'flexi-ui': {
80
- name: 'FlexiUI',
81
- description: 'FlexiReact with FlexiUI component library',
80
+ name: 'Flexi UI',
81
+ description: 'Showcase template with @flexireact/flexi-ui components',
82
82
  },
83
83
  minimal: {
84
84
  name: 'Minimal',
@@ -106,10 +106,6 @@ function info(msg) {
106
106
  console.log(` ${c.cyan}ℹ${c.reset} ${msg}`);
107
107
  }
108
108
 
109
- function step(num, total, msg) {
110
- console.log(` ${c.dim}[${num}/${total}]${c.reset} ${msg}`);
111
- }
112
-
113
109
  // Spinner
114
110
  class Spinner {
115
111
  constructor(message) {
@@ -184,26 +180,6 @@ async function select(question, options) {
184
180
  });
185
181
  }
186
182
 
187
- // Copy directory recursively
188
- function copyDir(src, dest) {
189
- if (!fs.existsSync(dest)) {
190
- fs.mkdirSync(dest, { recursive: true });
191
- }
192
-
193
- const entries = fs.readdirSync(src, { withFileTypes: true });
194
-
195
- for (const entry of entries) {
196
- const srcPath = path.join(src, entry.name);
197
- const destPath = path.join(dest, entry.name);
198
-
199
- if (entry.isDirectory()) {
200
- copyDir(srcPath, destPath);
201
- } else {
202
- fs.copyFileSync(srcPath, destPath);
203
- }
204
- }
205
- }
206
-
207
183
  // Check if directory is empty
208
184
  function isDirEmpty(dir) {
209
185
  if (!fs.existsSync(dir)) return true;
@@ -211,7 +187,7 @@ function isDirEmpty(dir) {
211
187
  }
212
188
 
213
189
  // ============================================================================
214
- // Template Files (Inline for npm package)
190
+ // Template Files
215
191
  // ============================================================================
216
192
 
217
193
  const TEMPLATE_FILES = {
@@ -224,21 +200,24 @@ const TEMPLATE_FILES = {
224
200
  dev: "npm run css && flexireact dev",
225
201
  build: "npm run css && flexireact build",
226
202
  start: "flexireact start",
227
- css: "npx tailwindcss -i ./app/styles/input.css -o ./public/styles.css --minify"
203
+ css: "npx tailwindcss -i ./app/styles/globals.css -o ./public/styles.css --minify"
228
204
  },
229
205
  dependencies: {
230
- react: "^18.2.0",
206
+ "react": "^18.2.0",
231
207
  "react-dom": "^18.2.0",
232
208
  "@flexireact/core": "^1.0.0",
233
- ...(template === 'flexi-ui' && { "@flexireact/flexi-ui": "^1.0.0" })
209
+ "framer-motion": "^11.0.0",
210
+ "lucide-react": "^0.400.0",
211
+ "clsx": "^2.1.0",
212
+ "tailwind-merge": "^2.2.0"
234
213
  },
235
214
  devDependencies: {
236
215
  "@types/react": "^18.2.0",
237
216
  "@types/react-dom": "^18.2.0",
238
- typescript: "^5.3.0",
239
- tailwindcss: "^3.4.0",
240
- postcss: "^8.4.32",
241
- autoprefixer: "^10.4.16"
217
+ "typescript": "^5.3.0",
218
+ "tailwindcss": "^3.4.0",
219
+ "postcss": "^8.4.32",
220
+ "autoprefixer": "^10.4.16"
242
221
  }
243
222
  }, null, 2),
244
223
 
@@ -265,8 +244,7 @@ const TEMPLATE_FILES = {
265
244
  exclude: ["node_modules", ".flexi"]
266
245
  }, null, 2),
267
246
 
268
- 'tailwind.config.js': (name, template) => `/** @type {import('tailwindcss').Config} */
269
- ${template === 'flexi-ui' ? "const { flexiUIPlugin } = require('@flexireact/flexi-ui/tailwind');\n" : ''}
247
+ 'tailwind.config.js': () => `/** @type {import('tailwindcss').Config} */
270
248
  module.exports = {
271
249
  darkMode: 'class',
272
250
  content: [
@@ -274,16 +252,71 @@ module.exports = {
274
252
  './pages/**/*.{js,ts,jsx,tsx}',
275
253
  './components/**/*.{js,ts,jsx,tsx}',
276
254
  './layouts/**/*.{js,ts,jsx,tsx}',
277
- ${template === 'flexi-ui' ? "'./node_modules/@flexireact/flexi-ui/dist/**/*.js'," : ''}
278
255
  ],
279
256
  theme: {
280
257
  extend: {
281
258
  fontFamily: {
282
259
  sans: ['Inter', 'system-ui', 'sans-serif'],
283
260
  },
261
+ colors: {
262
+ border: 'hsl(240 3.7% 15.9%)',
263
+ input: 'hsl(240 3.7% 15.9%)',
264
+ ring: 'hsl(142.1 76.2% 36.3%)',
265
+ background: 'hsl(240 10% 3.9%)',
266
+ foreground: 'hsl(0 0% 98%)',
267
+ primary: {
268
+ DEFAULT: 'hsl(142.1 76.2% 36.3%)',
269
+ foreground: 'hsl(144.9 80.4% 10%)',
270
+ },
271
+ secondary: {
272
+ DEFAULT: 'hsl(240 3.7% 15.9%)',
273
+ foreground: 'hsl(0 0% 98%)',
274
+ },
275
+ muted: {
276
+ DEFAULT: 'hsl(240 3.7% 15.9%)',
277
+ foreground: 'hsl(240 5% 64.9%)',
278
+ },
279
+ accent: {
280
+ DEFAULT: 'hsl(240 3.7% 15.9%)',
281
+ foreground: 'hsl(0 0% 98%)',
282
+ },
283
+ card: {
284
+ DEFAULT: 'hsl(240 10% 3.9%)',
285
+ foreground: 'hsl(0 0% 98%)',
286
+ },
287
+ },
288
+ borderRadius: {
289
+ lg: '0.75rem',
290
+ md: '0.5rem',
291
+ sm: '0.25rem',
292
+ },
293
+ animation: {
294
+ 'fade-in': 'fadeIn 0.5s ease-out',
295
+ 'fade-up': 'fadeUp 0.5s ease-out',
296
+ 'scale-in': 'scaleIn 0.3s ease-out',
297
+ 'glow': 'glow 2s ease-in-out infinite alternate',
298
+ },
299
+ keyframes: {
300
+ fadeIn: {
301
+ '0%': { opacity: '0' },
302
+ '100%': { opacity: '1' },
303
+ },
304
+ fadeUp: {
305
+ '0%': { opacity: '0', transform: 'translateY(20px)' },
306
+ '100%': { opacity: '1', transform: 'translateY(0)' },
307
+ },
308
+ scaleIn: {
309
+ '0%': { opacity: '0', transform: 'scale(0.95)' },
310
+ '100%': { opacity: '1', transform: 'scale(1)' },
311
+ },
312
+ glow: {
313
+ '0%': { boxShadow: '0 0 20px rgba(16, 185, 129, 0.2)' },
314
+ '100%': { boxShadow: '0 0 40px rgba(16, 185, 129, 0.4)' },
315
+ },
316
+ },
284
317
  },
285
318
  },
286
- plugins: [${template === 'flexi-ui' ? 'flexiUIPlugin' : ''}],
319
+ plugins: [],
287
320
  };
288
321
  `,
289
322
 
@@ -295,126 +328,398 @@ module.exports = {
295
328
  };
296
329
  `,
297
330
 
298
- 'flexireact.config.js': (name, template) => `/** @type {import('@flexireact/core').Config} */
331
+ 'flexireact.config.js': () => `/** @type {import('@flexireact/core').Config} */
299
332
  export default {
300
- // Styles to include
301
333
  styles: [
302
334
  '/styles.css',
303
- 'https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap'
335
+ 'https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800;900&display=swap'
304
336
  ],
305
-
306
- // Favicon
307
337
  favicon: '/favicon.svg',
308
-
309
- // Server options
310
338
  server: {
311
339
  port: 3000
312
340
  },
313
-
314
- // Islands (partial hydration)
315
341
  islands: {
316
342
  enabled: true
317
343
  }
318
344
  };
319
345
  `,
320
346
 
321
- 'pages/index.tsx': (name, template) => template === 'flexi-ui' ? `import React from 'react';
347
+ // ============================================================================
348
+ // Components
349
+ // ============================================================================
322
350
 
323
- export default function HomePage() {
351
+ 'components/ui/button.tsx': () => `import React from 'react';
352
+ import { cn } from '../../lib/utils';
353
+
354
+ interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
355
+ variant?: 'default' | 'outline' | 'ghost';
356
+ size?: 'default' | 'sm' | 'lg';
357
+ children: React.ReactNode;
358
+ }
359
+
360
+ export function Button({
361
+ className,
362
+ variant = 'default',
363
+ size = 'default',
364
+ children,
365
+ ...props
366
+ }: ButtonProps) {
324
367
  return (
325
- <div className="py-20">
326
- <div className="container mx-auto px-4 text-center">
327
- <span className="inline-block px-4 py-1.5 text-sm font-medium rounded-full mb-6" style={{ backgroundColor: 'rgba(0,255,156,0.1)', color: '#00FF9C', border: '1px solid rgba(0,255,156,0.3)' }}>
328
- ✨ Welcome to FlexiReact
329
- </span>
330
-
331
- <h1 className="text-4xl md:text-6xl font-bold mb-6">
332
- Build amazing apps with{' '}
333
- <span style={{ color: '#00FF9C' }}>FlexiReact</span>
334
- </h1>
335
-
336
- <p className="text-lg opacity-70 mb-8 max-w-2xl mx-auto">
337
- The modern React framework with TypeScript, Tailwind CSS, SSR, and Islands architecture.
338
- </p>
368
+ <button
369
+ className={cn(
370
+ 'inline-flex items-center justify-center rounded-lg font-medium transition-all duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50',
371
+ {
372
+ 'bg-primary text-primary-foreground hover:bg-primary/90 shadow-lg shadow-primary/25': variant === 'default',
373
+ 'border border-border bg-transparent hover:bg-secondary hover:text-foreground': variant === 'outline',
374
+ 'hover:bg-secondary hover:text-foreground': variant === 'ghost',
375
+ },
376
+ {
377
+ 'h-10 px-4 py-2 text-sm': size === 'default',
378
+ 'h-9 px-3 text-sm': size === 'sm',
379
+ 'h-12 px-8 text-base': size === 'lg',
380
+ },
381
+ className
382
+ )}
383
+ {...props}
384
+ >
385
+ {children}
386
+ </button>
387
+ );
388
+ }
389
+ `,
339
390
 
340
- <div className="flex gap-4 justify-center">
341
- <a href="/docs" className="px-6 py-3 font-medium rounded-xl text-black" style={{ backgroundColor: '#00FF9C' }}>
342
- Get Started →
343
- </a>
344
- <a href="https://github.com/flexireact/flexireact" className="px-6 py-3 font-medium rounded-xl border border-[var(--flexi-border)] hover:bg-[var(--flexi-bg-muted)] transition-colors">
345
- GitHub
346
- </a>
347
- </div>
348
- </div>
391
+ 'components/ui/card.tsx': () => `import React from 'react';
392
+ import { cn } from '../../lib/utils';
393
+
394
+ interface CardProps extends React.HTMLAttributes<HTMLDivElement> {
395
+ children: React.ReactNode;
396
+ }
397
+
398
+ export function Card({ className, children, ...props }: CardProps) {
399
+ return (
400
+ <div
401
+ className={cn(
402
+ 'rounded-xl border border-border bg-card text-card-foreground shadow-sm transition-all duration-300 hover:border-primary/50 hover:shadow-lg hover:shadow-primary/5',
403
+ className
404
+ )}
405
+ {...props}
406
+ >
407
+ {children}
349
408
  </div>
350
409
  );
351
410
  }
352
- ` : `import React from 'react';
353
411
 
354
- export default function HomePage() {
412
+ export function CardHeader({ className, children, ...props }: CardProps) {
355
413
  return (
356
- <div className="py-20 px-4">
357
- <div className="max-w-4xl mx-auto text-center">
358
- {/* Badge */}
359
- <span className="inline-block px-4 py-2 text-sm font-medium rounded-full mb-8 bg-emerald-500/10 text-emerald-400 border border-emerald-500/30">
360
- ⚡ The Modern React Framework
361
- </span>
362
-
363
- {/* Title */}
364
- <h1 className="text-5xl md:text-7xl font-extrabold mb-6 text-white">
365
- Build amazing apps with{' '}
366
- <span className="text-transparent bg-clip-text bg-gradient-to-r from-emerald-400 to-cyan-400">
367
- FlexiReact
368
- </span>
369
- </h1>
414
+ <div className={cn('flex flex-col space-y-1.5 p-6', className)} {...props}>
415
+ {children}
416
+ </div>
417
+ );
418
+ }
419
+
420
+ export function CardTitle({ className, children, ...props }: CardProps) {
421
+ return (
422
+ <h3 className={cn('text-lg font-semibold leading-none tracking-tight', className)} {...props}>
423
+ {children}
424
+ </h3>
425
+ );
426
+ }
427
+
428
+ export function CardDescription({ className, children, ...props }: CardProps) {
429
+ return (
430
+ <p className={cn('text-sm text-muted-foreground', className)} {...props}>
431
+ {children}
432
+ </p>
433
+ );
434
+ }
435
+
436
+ export function CardContent({ className, children, ...props }: CardProps) {
437
+ return (
438
+ <div className={cn('p-6 pt-0', className)} {...props}>
439
+ {children}
440
+ </div>
441
+ );
442
+ }
443
+ `,
444
+
445
+ 'components/ui/badge.tsx': () => `import React from 'react';
446
+ import { cn } from '../../lib/utils';
447
+
448
+ interface BadgeProps extends React.HTMLAttributes<HTMLDivElement> {
449
+ variant?: 'default' | 'secondary' | 'outline';
450
+ children: React.ReactNode;
451
+ }
452
+
453
+ export function Badge({ className, variant = 'default', children, ...props }: BadgeProps) {
454
+ return (
455
+ <div
456
+ className={cn(
457
+ 'inline-flex items-center rounded-full px-3 py-1 text-xs font-medium transition-colors',
458
+ {
459
+ 'bg-primary/10 text-primary border border-primary/20': variant === 'default',
460
+ 'bg-secondary text-secondary-foreground': variant === 'secondary',
461
+ 'border border-border text-foreground': variant === 'outline',
462
+ },
463
+ className
464
+ )}
465
+ {...props}
466
+ >
467
+ {children}
468
+ </div>
469
+ );
470
+ }
471
+ `,
472
+
473
+ 'components/Navbar.tsx': () => `import React from 'react';
474
+ import { Button } from './ui/button';
475
+
476
+ export function Navbar() {
477
+ return (
478
+ <header className="sticky top-0 z-50 w-full border-b border-border/40 bg-background/80 backdrop-blur-xl">
479
+ <nav className="container mx-auto flex h-16 max-w-6xl items-center justify-between px-4">
480
+ <a href="/" className="flex items-center gap-2 transition-opacity hover:opacity-80">
481
+ <div className="flex h-8 w-8 items-center justify-center rounded-lg bg-gradient-to-br from-primary to-emerald-400">
482
+ <svg className="h-4 w-4 text-primary-foreground" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2.5}>
483
+ <path strokeLinecap="round" strokeLinejoin="round" d="M13 10V3L4 14h7v7l9-11h-7z" />
484
+ </svg>
485
+ </div>
486
+ <span className="text-lg font-bold">FlexiReact</span>
487
+ </a>
370
488
 
371
- {/* Subtitle */}
372
- <p className="text-xl text-slate-400 mb-10 max-w-2xl mx-auto leading-relaxed">
373
- A blazing-fast React framework with TypeScript, Tailwind CSS, SSR, SSG,
374
- Islands architecture, and file-based routing.
375
- </p>
489
+ <div className="flex items-center gap-2">
490
+ <Button variant="ghost" size="sm" asChild>
491
+ <a href="https://github.com/flexireact/flexireact">Docs</a>
492
+ </Button>
493
+ <Button variant="ghost" size="sm" asChild>
494
+ <a href="https://github.com/flexireact/flexireact" className="flex items-center gap-2">
495
+ <svg className="h-4 w-4" fill="currentColor" viewBox="0 0 24 24">
496
+ <path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/>
497
+ </svg>
498
+ GitHub
499
+ </a>
500
+ </Button>
501
+ </div>
502
+ </nav>
503
+ </header>
504
+ );
505
+ }
506
+ `,
507
+
508
+ 'components/Hero.tsx': () => `import React from 'react';
509
+ import { Button } from './ui/button';
510
+ import { Badge } from './ui/badge';
376
511
 
377
- {/* Buttons */}
378
- <div className="flex flex-wrap gap-4 justify-center mb-16">
379
- <a
380
- href="https://github.com/flexireact/flexireact"
381
- className="px-8 py-4 bg-emerald-500 text-black font-semibold rounded-xl hover:bg-emerald-400 transition-all shadow-lg shadow-emerald-500/25"
382
- >
383
- Get Started
384
- </a>
385
- <a
386
- href="https://github.com/flexireact/flexireact"
387
- className="px-8 py-4 bg-slate-800 text-white font-semibold rounded-xl border border-slate-700 hover:bg-slate-700 transition-all"
388
- >
389
- GitHub
390
- </a>
512
+ export function Hero() {
513
+ return (
514
+ <section className="relative overflow-hidden">
515
+ {/* Gradient Background */}
516
+ <div className="absolute inset-0 -z-10">
517
+ <div className="absolute left-1/2 top-0 -translate-x-1/2 -translate-y-1/2">
518
+ <div className="h-[600px] w-[600px] rounded-full bg-gradient-to-r from-primary/20 via-emerald-500/10 to-cyan-500/20 blur-3xl" />
519
+ </div>
520
+ <div className="absolute right-0 top-1/2 -translate-y-1/2">
521
+ <div className="h-[400px] w-[400px] rounded-full bg-gradient-to-l from-primary/10 to-transparent blur-3xl" />
391
522
  </div>
523
+ </div>
392
524
 
393
- {/* Features */}
394
- <div className="grid md:grid-cols-3 gap-6 text-left">
395
- <div className="p-6 rounded-2xl bg-slate-800/50 border border-slate-700">
396
- <div className="text-3xl mb-3">⚡</div>
397
- <h3 className="text-lg font-semibold text-white mb-2">Lightning Fast</h3>
398
- <p className="text-slate-400 text-sm">Powered by esbuild for instant builds and sub-second HMR.</p>
525
+ <div className="container mx-auto max-w-6xl px-4 py-24 sm:py-32 lg:py-40">
526
+ <div className="flex flex-col items-center text-center">
527
+ {/* Badge */}
528
+ <Badge className="mb-6 animate-fade-in">
529
+ <span className="mr-1">⚡</span> The Modern React Framework
530
+ </Badge>
531
+
532
+ {/* Title */}
533
+ <h1 className="mb-6 max-w-4xl animate-fade-up text-4xl font-extrabold tracking-tight sm:text-5xl md:text-6xl lg:text-7xl">
534
+ Build{' '}
535
+ <span className="bg-gradient-to-r from-primary via-emerald-400 to-cyan-400 bg-clip-text text-transparent">
536
+ blazing fast
537
+ </span>{' '}
538
+ web apps
539
+ </h1>
540
+
541
+ {/* Subtitle */}
542
+ <p className="mb-10 max-w-2xl animate-fade-up text-lg text-muted-foreground sm:text-xl" style={{ animationDelay: '0.1s' }}>
543
+ A modern React framework with TypeScript, Tailwind CSS, SSR, SSG,
544
+ Islands architecture, and file-based routing. Ship faster.
545
+ </p>
546
+
547
+ {/* CTA Buttons */}
548
+ <div className="flex flex-wrap items-center justify-center gap-4 animate-fade-up" style={{ animationDelay: '0.2s' }}>
549
+ <Button size="lg" className="gap-2">
550
+ Start Building
551
+ <svg className="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
552
+ <path strokeLinecap="round" strokeLinejoin="round" d="M13 7l5 5m0 0l-5 5m5-5H6" />
553
+ </svg>
554
+ </Button>
555
+ <Button variant="outline" size="lg" asChild>
556
+ <a href="https://github.com/flexireact/flexireact" className="gap-2">
557
+ <svg className="h-4 w-4" fill="currentColor" viewBox="0 0 24 24">
558
+ <path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/>
559
+ </svg>
560
+ GitHub
561
+ </a>
562
+ </Button>
399
563
  </div>
400
- <div className="p-6 rounded-2xl bg-slate-800/50 border border-slate-700">
401
- <div className="text-3xl mb-3">🏝️</div>
402
- <h3 className="text-lg font-semibold text-white mb-2">Islands Architecture</h3>
403
- <p className="text-slate-400 text-sm">Partial hydration for minimal JavaScript and maximum performance.</p>
564
+
565
+ {/* Code Preview */}
566
+ <div className="mt-16 w-full max-w-2xl animate-fade-up rounded-xl border border-border bg-card/50 p-4 backdrop-blur-sm" style={{ animationDelay: '0.3s' }}>
567
+ <div className="flex items-center gap-2 border-b border-border pb-3">
568
+ <div className="h-3 w-3 rounded-full bg-red-500/80" />
569
+ <div className="h-3 w-3 rounded-full bg-yellow-500/80" />
570
+ <div className="h-3 w-3 rounded-full bg-green-500/80" />
571
+ <span className="ml-2 text-xs text-muted-foreground">terminal</span>
572
+ </div>
573
+ <pre className="mt-4 overflow-x-auto text-left text-sm">
574
+ <code className="text-muted-foreground">
575
+ <span className="text-muted-foreground/60">$</span>{' '}
576
+ <span className="text-primary">npx</span> create-flexireact@latest my-app{'\n'}
577
+ <span className="text-muted-foreground/60">$</span>{' '}
578
+ <span className="text-primary">cd</span> my-app{'\n'}
579
+ <span className="text-muted-foreground/60">$</span>{' '}
580
+ <span className="text-primary">npm</span> run dev{'\n'}
581
+ {'\n'}
582
+ <span className="text-emerald-400">✓</span> Ready in <span className="text-primary">38ms</span>
583
+ </code>
584
+ </pre>
404
585
  </div>
405
- <div className="p-6 rounded-2xl bg-slate-800/50 border border-slate-700">
406
- <div className="text-3xl mb-3">📁</div>
407
- <h3 className="text-lg font-semibold text-white mb-2">File-based Routing</h3>
408
- <p className="text-slate-400 text-sm">Create a file in pages/, get a route automatically.</p>
586
+ </div>
587
+ </div>
588
+ </section>
589
+ );
590
+ }
591
+ `,
592
+
593
+ 'components/Features.tsx': () => `import React from 'react';
594
+ import { Card, CardHeader, CardTitle, CardDescription } from './ui/card';
595
+
596
+ const features = [
597
+ {
598
+ icon: (
599
+ <svg className="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
600
+ <path strokeLinecap="round" strokeLinejoin="round" d="M13 10V3L4 14h7v7l9-11h-7z" />
601
+ </svg>
602
+ ),
603
+ title: 'Lightning Fast',
604
+ description: 'Powered by esbuild for instant builds and sub-second hot module replacement.',
605
+ },
606
+ {
607
+ icon: (
608
+ <svg className="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
609
+ <path strokeLinecap="round" strokeLinejoin="round" d="M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-6l-2-2H5a2 2 0 00-2 2z" />
610
+ </svg>
611
+ ),
612
+ title: 'File-based Routing',
613
+ description: 'Create a file in pages/, get a route automatically. Simple and intuitive.',
614
+ },
615
+ {
616
+ icon: (
617
+ <svg className="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
618
+ <path strokeLinecap="round" strokeLinejoin="round" d="M5 3v4M3 5h4M6 17v4m-2-2h4m5-16l2.286 6.857L21 12l-5.714 2.143L13 21l-2.286-6.857L5 12l5.714-2.143L13 3z" />
619
+ </svg>
620
+ ),
621
+ title: 'Islands Architecture',
622
+ description: 'Partial hydration for minimal JavaScript. Only hydrate what needs interactivity.',
623
+ },
624
+ {
625
+ icon: (
626
+ <svg className="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
627
+ <path strokeLinecap="round" strokeLinejoin="round" d="M5 12h14M5 12a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v4a2 2 0 01-2 2M5 12a2 2 0 00-2 2v4a2 2 0 002 2h14a2 2 0 002-2v-4a2 2 0 00-2-2m-2-4h.01M17 16h.01" />
628
+ </svg>
629
+ ),
630
+ title: 'SSR & SSG',
631
+ description: 'Server-side rendering and static generation out of the box. SEO friendly.',
632
+ },
633
+ ];
634
+
635
+ export function Features() {
636
+ return (
637
+ <section className="container mx-auto max-w-6xl px-4 py-24">
638
+ <div className="mb-12 text-center">
639
+ <h2 className="mb-4 text-3xl font-bold tracking-tight sm:text-4xl">
640
+ Everything you need
641
+ </h2>
642
+ <p className="mx-auto max-w-2xl text-muted-foreground">
643
+ A complete toolkit for building modern web applications with React.
644
+ </p>
645
+ </div>
646
+
647
+ <div className="grid gap-6 sm:grid-cols-2 lg:grid-cols-4">
648
+ {features.map((feature, index) => (
649
+ <Card key={index} className="group cursor-default">
650
+ <CardHeader>
651
+ <div className="mb-3 inline-flex h-12 w-12 items-center justify-center rounded-lg bg-primary/10 text-primary transition-colors group-hover:bg-primary group-hover:text-primary-foreground">
652
+ {feature.icon}
653
+ </div>
654
+ <CardTitle>{feature.title}</CardTitle>
655
+ <CardDescription>{feature.description}</CardDescription>
656
+ </CardHeader>
657
+ </Card>
658
+ ))}
659
+ </div>
660
+ </section>
661
+ );
662
+ }
663
+ `,
664
+
665
+ 'components/Footer.tsx': () => `import React from 'react';
666
+
667
+ export function Footer() {
668
+ return (
669
+ <footer className="border-t border-border">
670
+ <div className="container mx-auto max-w-6xl px-4 py-8">
671
+ <div className="flex flex-col items-center justify-between gap-4 sm:flex-row">
672
+ <div className="flex items-center gap-2 text-sm text-muted-foreground">
673
+ <span>Built with</span>
674
+ <span className="text-red-500">❤️</span>
675
+ <span>using</span>
676
+ <a href="https://github.com/flexireact/flexireact" className="font-medium text-foreground hover:text-primary transition-colors">
677
+ FlexiReact
678
+ </a>
679
+ </div>
680
+ <div className="flex items-center gap-4 text-sm text-muted-foreground">
681
+ <a href="https://github.com/flexireact/flexireact" className="hover:text-foreground transition-colors">
682
+ GitHub
683
+ </a>
684
+ <a href="https://github.com/flexireact/flexireact" className="hover:text-foreground transition-colors">
685
+ Documentation
686
+ </a>
409
687
  </div>
410
688
  </div>
411
689
  </div>
412
- </div>
690
+ </footer>
413
691
  );
414
692
  }
415
693
  `,
416
694
 
417
- 'layouts/root.tsx': (name, template) => template === 'flexi-ui' ? `import React from 'react';
695
+ 'components/index.ts': () => `export { Navbar } from './Navbar';
696
+ export { Hero } from './Hero';
697
+ export { Features } from './Features';
698
+ export { Footer } from './Footer';
699
+ export { Button } from './ui/button';
700
+ export { Card, CardHeader, CardTitle, CardDescription, CardContent } from './ui/card';
701
+ export { Badge } from './ui/badge';
702
+ `,
703
+
704
+ // ============================================================================
705
+ // Lib
706
+ // ============================================================================
707
+
708
+ 'lib/utils.ts': () => `import { clsx, type ClassValue } from 'clsx';
709
+ import { twMerge } from 'tailwind-merge';
710
+
711
+ export function cn(...inputs: ClassValue[]) {
712
+ return twMerge(clsx(inputs));
713
+ }
714
+ `,
715
+
716
+ // ============================================================================
717
+ // Pages & Layouts
718
+ // ============================================================================
719
+
720
+ 'layouts/root.tsx': () => `import React from 'react';
721
+ import { Navbar } from '../components/Navbar';
722
+ import { Footer } from '../components/Footer';
418
723
 
419
724
  interface LayoutProps {
420
725
  children: React.ReactNode;
@@ -422,31 +727,722 @@ interface LayoutProps {
422
727
 
423
728
  export default function RootLayout({ children }: LayoutProps) {
424
729
  return (
425
- <div className="min-h-screen flex flex-col" style={{ backgroundColor: 'var(--flexi-bg)', color: 'var(--flexi-fg)' }}>
426
- <header className="sticky top-0 z-50 w-full border-b border-[var(--flexi-border)] backdrop-blur-sm" style={{ backgroundColor: 'rgba(2, 6, 23, 0.8)' }}>
427
- <nav className="container mx-auto px-4 h-16 flex items-center justify-between">
428
- <a href="/" className="flex items-center gap-2">
429
- <div className="w-8 h-8 rounded-xl flex items-center justify-center" style={{ background: 'linear-gradient(135deg, #00FF9C, #00CC7D)' }}>
730
+ <div className="relative min-h-screen bg-background text-foreground antialiased">
731
+ <Navbar />
732
+ <main>{children}</main>
733
+ <Footer />
734
+ </div>
735
+ );
736
+ }
737
+ `,
738
+
739
+ 'pages/index.tsx': () => `import React from 'react';
740
+ import { Hero } from '../components/Hero';
741
+ import { Features } from '../components/Features';
742
+
743
+ export default function HomePage() {
744
+ return (
745
+ <>
746
+ <Hero />
747
+ <Features />
748
+ </>
749
+ );
750
+ }
751
+ `,
752
+
753
+ // ============================================================================
754
+ // Styles
755
+ // ============================================================================
756
+
757
+ 'app/styles/globals.css': () => `@tailwind base;
758
+ @tailwind components;
759
+ @tailwind utilities;
760
+
761
+ @layer base {
762
+ :root {
763
+ --background: 240 10% 3.9%;
764
+ --foreground: 0 0% 98%;
765
+ --card: 240 10% 3.9%;
766
+ --card-foreground: 0 0% 98%;
767
+ --popover: 240 10% 3.9%;
768
+ --popover-foreground: 0 0% 98%;
769
+ --primary: 142.1 76.2% 36.3%;
770
+ --primary-foreground: 144.9 80.4% 10%;
771
+ --secondary: 240 3.7% 15.9%;
772
+ --secondary-foreground: 0 0% 98%;
773
+ --muted: 240 3.7% 15.9%;
774
+ --muted-foreground: 240 5% 64.9%;
775
+ --accent: 240 3.7% 15.9%;
776
+ --accent-foreground: 0 0% 98%;
777
+ --destructive: 0 62.8% 30.6%;
778
+ --destructive-foreground: 0 0% 98%;
779
+ --border: 240 3.7% 15.9%;
780
+ --input: 240 3.7% 15.9%;
781
+ --ring: 142.1 76.2% 36.3%;
782
+ --radius: 0.75rem;
783
+ }
784
+
785
+ * {
786
+ border-color: hsl(var(--border));
787
+ }
788
+
789
+ html {
790
+ scroll-behavior: smooth;
791
+ }
792
+
793
+ body {
794
+ font-family: 'Inter', system-ui, -apple-system, sans-serif;
795
+ background-color: hsl(var(--background));
796
+ color: hsl(var(--foreground));
797
+ min-height: 100vh;
798
+ -webkit-font-smoothing: antialiased;
799
+ -moz-osx-font-smoothing: grayscale;
800
+ }
801
+ }
802
+
803
+ @layer utilities {
804
+ .text-balance {
805
+ text-wrap: balance;
806
+ }
807
+ }
808
+ `,
809
+
810
+ // ============================================================================
811
+ // Public Assets
812
+ // ============================================================================
813
+
814
+ 'public/.gitkeep': () => '',
815
+
816
+ 'public/favicon.svg': () => `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
817
+ <defs>
818
+ <linearGradient id="grad" x1="0%" y1="0%" x2="100%" y2="100%">
819
+ <stop offset="0%" style="stop-color:#10b981"/>
820
+ <stop offset="100%" style="stop-color:#06b6d4"/>
821
+ </linearGradient>
822
+ </defs>
823
+ <rect width="100" height="100" rx="20" fill="#0a0a0a"/>
824
+ <path d="M50 20L30 55h15v25l20-35H50V20z" fill="url(#grad)"/>
825
+ </svg>`,
826
+ };
827
+
828
+ // Minimal template files
829
+ const MINIMAL_FILES = {
830
+ 'package.json': (name) => JSON.stringify({
831
+ name: name,
832
+ version: "1.0.0",
833
+ private: true,
834
+ type: "module",
835
+ scripts: {
836
+ dev: "flexireact dev",
837
+ build: "flexireact build",
838
+ start: "flexireact start"
839
+ },
840
+ dependencies: {
841
+ "react": "^18.2.0",
842
+ "react-dom": "^18.2.0",
843
+ "@flexireact/core": "^1.0.0"
844
+ },
845
+ devDependencies: {
846
+ "@types/react": "^18.2.0",
847
+ "@types/react-dom": "^18.2.0",
848
+ "typescript": "^5.3.0"
849
+ }
850
+ }, null, 2),
851
+
852
+ 'tsconfig.json': TEMPLATE_FILES['tsconfig.json'],
853
+
854
+ 'flexireact.config.js': () => `export default {
855
+ server: { port: 3000 }
856
+ };
857
+ `,
858
+
859
+ 'pages/index.tsx': () => `import React from 'react';
860
+
861
+ export default function HomePage() {
862
+ return (
863
+ <div style={{ padding: '2rem', fontFamily: 'system-ui' }}>
864
+ <h1>Welcome to FlexiReact</h1>
865
+ <p>Edit pages/index.tsx to get started.</p>
866
+ </div>
867
+ );
868
+ }
869
+ `,
870
+
871
+ 'public/.gitkeep': () => '',
872
+ };
873
+
874
+ // ============================================================================
875
+ // Flexi UI Template Files
876
+ // ============================================================================
877
+
878
+ const FLEXI_UI_FILES = {
879
+ 'package.json': (name) => JSON.stringify({
880
+ name: name,
881
+ version: "1.0.0",
882
+ private: true,
883
+ type: "module",
884
+ scripts: {
885
+ dev: "npm run css && flexireact dev",
886
+ build: "npm run css && flexireact build",
887
+ start: "flexireact start",
888
+ css: "npx tailwindcss -i ./app/styles/globals.css -o ./public/styles.css --minify"
889
+ },
890
+ dependencies: {
891
+ "react": "^18.2.0",
892
+ "react-dom": "^18.2.0",
893
+ "@flexireact/core": "^1.0.0",
894
+ "@flexireact/flexi-ui": "^1.0.0",
895
+ "lucide-react": "^0.400.0"
896
+ },
897
+ devDependencies: {
898
+ "@types/react": "^18.2.0",
899
+ "@types/react-dom": "^18.2.0",
900
+ "typescript": "^5.3.0",
901
+ "tailwindcss": "^3.4.0",
902
+ "postcss": "^8.4.32",
903
+ "autoprefixer": "^10.4.16"
904
+ }
905
+ }, null, 2),
906
+
907
+ 'tsconfig.json': TEMPLATE_FILES['tsconfig.json'],
908
+
909
+ 'tailwind.config.js': () => `/** @type {import('tailwindcss').Config} */
910
+ const { flexiUIPlugin } = require('@flexireact/flexi-ui/tailwind');
911
+
912
+ module.exports = {
913
+ darkMode: 'class',
914
+ content: [
915
+ './app/**/*.{js,ts,jsx,tsx}',
916
+ './pages/**/*.{js,ts,jsx,tsx}',
917
+ './components/**/*.{js,ts,jsx,tsx}',
918
+ './layouts/**/*.{js,ts,jsx,tsx}',
919
+ './node_modules/@flexireact/flexi-ui/dist/**/*.js',
920
+ ],
921
+ theme: {
922
+ extend: {
923
+ fontFamily: {
924
+ sans: ['Inter', 'system-ui', 'sans-serif'],
925
+ },
926
+ animation: {
927
+ 'fade-in': 'fadeIn 0.6s ease-out forwards',
928
+ 'fade-up': 'fadeUp 0.6s ease-out forwards',
929
+ 'scale-in': 'scaleIn 0.4s ease-out forwards',
930
+ 'glow-pulse': 'glowPulse 3s ease-in-out infinite',
931
+ },
932
+ keyframes: {
933
+ fadeIn: {
934
+ '0%': { opacity: '0' },
935
+ '100%': { opacity: '1' },
936
+ },
937
+ fadeUp: {
938
+ '0%': { opacity: '0', transform: 'translateY(30px)' },
939
+ '100%': { opacity: '1', transform: 'translateY(0)' },
940
+ },
941
+ scaleIn: {
942
+ '0%': { opacity: '0', transform: 'scale(0.9)' },
943
+ '100%': { opacity: '1', transform: 'scale(1)' },
944
+ },
945
+ glowPulse: {
946
+ '0%, 100%': { boxShadow: '0 0 20px rgba(0, 255, 156, 0.15)' },
947
+ '50%': { boxShadow: '0 0 40px rgba(0, 255, 156, 0.3)' },
948
+ },
949
+ },
950
+ },
951
+ },
952
+ plugins: [flexiUIPlugin],
953
+ };
954
+ `,
955
+
956
+ 'postcss.config.js': () => `module.exports = {
957
+ plugins: {
958
+ tailwindcss: {},
959
+ autoprefixer: {},
960
+ },
961
+ };
962
+ `,
963
+
964
+ 'flexireact.config.js': () => `/** @type {import('@flexireact/core').Config} */
965
+ export default {
966
+ styles: [
967
+ '/styles.css',
968
+ 'https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800;900&display=swap'
969
+ ],
970
+ favicon: '/favicon.svg',
971
+ server: {
972
+ port: 3000
973
+ },
974
+ islands: {
975
+ enabled: true
976
+ }
977
+ };
978
+ `,
979
+
980
+ // ============================================================================
981
+ // Components
982
+ // ============================================================================
983
+
984
+ 'components/Hero.tsx': () => `import React from 'react';
985
+ import { Button, Badge, Card } from '@flexireact/flexi-ui';
986
+ import { Zap, Github, ArrowRight, Sparkles } from 'lucide-react';
987
+
988
+ export function Hero() {
989
+ return (
990
+ <section className="relative min-h-screen flex items-center justify-center overflow-hidden">
991
+ {/* Radial Gradient Background */}
992
+ <div className="absolute inset-0 -z-10">
993
+ <div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[800px] h-[800px] rounded-full bg-gradient-radial from-[#00FF9C]/20 via-[#00FF9C]/5 to-transparent blur-3xl" />
994
+ <div className="absolute top-0 right-0 w-[600px] h-[600px] rounded-full bg-gradient-radial from-cyan-500/10 to-transparent blur-3xl" />
995
+ <div className="absolute bottom-0 left-0 w-[400px] h-[400px] rounded-full bg-gradient-radial from-emerald-500/10 to-transparent blur-3xl" />
996
+ </div>
997
+
998
+ {/* Grid Pattern Overlay */}
999
+ <div className="absolute inset-0 -z-10 bg-[linear-gradient(rgba(255,255,255,0.02)_1px,transparent_1px),linear-gradient(90deg,rgba(255,255,255,0.02)_1px,transparent_1px)] bg-[size:64px_64px]" />
1000
+
1001
+ <div className="container mx-auto px-6 py-32 max-w-6xl">
1002
+ <div className="flex flex-col items-center text-center">
1003
+ {/* Badge */}
1004
+ <div className="animate-fade-in" style={{ animationDelay: '0.1s' }}>
1005
+ <Badge variant="success" className="mb-8 px-4 py-2 text-sm">
1006
+ <Sparkles className="w-4 h-4 mr-2" />
1007
+ The Modern React Framework
1008
+ </Badge>
1009
+ </div>
1010
+
1011
+ {/* Title */}
1012
+ <h1 className="text-5xl sm:text-6xl md:text-7xl lg:text-8xl font-black tracking-tight mb-8 animate-fade-up" style={{ animationDelay: '0.2s' }}>
1013
+ Build{' '}
1014
+ <span className="text-transparent bg-clip-text bg-gradient-to-r from-[#00FF9C] via-emerald-400 to-cyan-400">
1015
+ beautiful
1016
+ </span>
1017
+ <br />
1018
+ apps faster
1019
+ </h1>
1020
+
1021
+ {/* Subtitle */}
1022
+ <p className="text-xl md:text-2xl text-[#94a3b8] max-w-2xl mb-12 leading-relaxed animate-fade-up" style={{ animationDelay: '0.3s' }}>
1023
+ Flexi UI is a stunning component library with neon emerald accents,
1024
+ dark-first design, and seamless React integration.
1025
+ </p>
1026
+
1027
+ {/* CTA Buttons */}
1028
+ <div className="flex flex-wrap items-center justify-center gap-4 mb-20 animate-fade-up" style={{ animationDelay: '0.4s' }}>
1029
+ <Button size="lg" className="gap-2 text-base px-8 py-4 h-auto">
1030
+ Get Started
1031
+ <ArrowRight className="w-5 h-5" />
1032
+ </Button>
1033
+ <Button variant="outline" size="lg" className="gap-2 text-base px-8 py-4 h-auto">
1034
+ <Github className="w-5 h-5" />
1035
+ GitHub
1036
+ </Button>
1037
+ </div>
1038
+
1039
+ {/* Terminal Preview */}
1040
+ <Card className="w-full max-w-2xl animate-scale-in animate-glow-pulse" style={{ animationDelay: '0.5s' }}>
1041
+ <div className="p-6">
1042
+ <div className="flex items-center gap-2 mb-4">
1043
+ <div className="w-3 h-3 rounded-full bg-red-500/80" />
1044
+ <div className="w-3 h-3 rounded-full bg-yellow-500/80" />
1045
+ <div className="w-3 h-3 rounded-full bg-green-500/80" />
1046
+ <span className="ml-3 text-xs text-[#64748b]">terminal</span>
1047
+ </div>
1048
+ <pre className="text-left text-sm md:text-base font-mono">
1049
+ <code>
1050
+ <span className="text-[#64748b]">$</span>{' '}
1051
+ <span className="text-[#00FF9C]">npm</span> install @flexireact/flexi-ui{'\n'}
1052
+ <span className="text-[#64748b]">$</span>{' '}
1053
+ <span className="text-[#00FF9C]">npx</span> create-flexireact my-app{'\n'}
1054
+ {'\n'}
1055
+ <span className="text-[#00FF9C]">✓</span> <span className="text-[#f8fafc]">Ready in</span> <span className="text-[#00FF9C]">38ms</span>
1056
+ </code>
1057
+ </pre>
1058
+ </div>
1059
+ </Card>
1060
+ </div>
1061
+ </div>
1062
+ </section>
1063
+ );
1064
+ }
1065
+ `,
1066
+
1067
+ 'components/Features.tsx': () => `import React from 'react';
1068
+ import { Card, Badge } from '@flexireact/flexi-ui';
1069
+ import { Zap, Folder, Sparkles, Server, Palette, Shield } from 'lucide-react';
1070
+
1071
+ const features = [
1072
+ {
1073
+ icon: Zap,
1074
+ title: 'Lightning Fast',
1075
+ description: 'Powered by esbuild for instant builds and sub-second hot module replacement.',
1076
+ badge: 'Performance',
1077
+ },
1078
+ {
1079
+ icon: Folder,
1080
+ title: 'File-based Routing',
1081
+ description: 'Create a file in pages/, get a route automatically. Simple and intuitive.',
1082
+ badge: 'DX',
1083
+ },
1084
+ {
1085
+ icon: Sparkles,
1086
+ title: 'Islands Architecture',
1087
+ description: 'Partial hydration for minimal JavaScript. Only hydrate what needs interactivity.',
1088
+ badge: 'Modern',
1089
+ },
1090
+ {
1091
+ icon: Server,
1092
+ title: 'SSR & SSG',
1093
+ description: 'Server-side rendering and static generation out of the box. SEO friendly.',
1094
+ badge: 'SEO',
1095
+ },
1096
+ {
1097
+ icon: Palette,
1098
+ title: 'Beautiful Design',
1099
+ description: 'Neon emerald accents with dark-first design. Stunning out of the box.',
1100
+ badge: 'UI',
1101
+ },
1102
+ {
1103
+ icon: Shield,
1104
+ title: 'Type Safe',
1105
+ description: 'Full TypeScript support with strict type checking and excellent DX.',
1106
+ badge: 'TypeScript',
1107
+ },
1108
+ ];
1109
+
1110
+ export function Features() {
1111
+ return (
1112
+ <section className="py-32 px-6">
1113
+ <div className="container mx-auto max-w-6xl">
1114
+ {/* Section Header */}
1115
+ <div className="text-center mb-20">
1116
+ <Badge variant="outline" className="mb-6">Features</Badge>
1117
+ <h2 className="text-4xl md:text-5xl font-bold tracking-tight mb-6">
1118
+ Everything you need
1119
+ </h2>
1120
+ <p className="text-xl text-[#94a3b8] max-w-2xl mx-auto">
1121
+ A complete toolkit for building modern web applications with React and Flexi UI.
1122
+ </p>
1123
+ </div>
1124
+
1125
+ {/* Feature Grid */}
1126
+ <div className="grid md:grid-cols-2 lg:grid-cols-3 gap-6">
1127
+ {features.map((feature, index) => (
1128
+ <Card
1129
+ key={index}
1130
+ className="group p-8 transition-all duration-300 hover:border-[#00FF9C]/50 hover:shadow-[0_0_30px_rgba(0,255,156,0.1)] cursor-default animate-fade-up"
1131
+ style={{ animationDelay: \`\${index * 0.1}s\` }}
1132
+ >
1133
+ <div className="flex items-start gap-4">
1134
+ <div className="p-3 rounded-xl bg-[#00FF9C]/10 text-[#00FF9C] group-hover:bg-[#00FF9C] group-hover:text-black transition-all duration-300">
1135
+ <feature.icon className="w-6 h-6" />
1136
+ </div>
1137
+ <div className="flex-1">
1138
+ <div className="flex items-center gap-2 mb-2">
1139
+ <h3 className="text-lg font-semibold">{feature.title}</h3>
1140
+ </div>
1141
+ <p className="text-[#94a3b8] text-sm leading-relaxed">
1142
+ {feature.description}
1143
+ </p>
1144
+ </div>
1145
+ </div>
1146
+ </Card>
1147
+ ))}
1148
+ </div>
1149
+ </div>
1150
+ </section>
1151
+ );
1152
+ }
1153
+ `,
1154
+
1155
+ 'components/Showcase.tsx': () => `import React from 'react';
1156
+ import {
1157
+ Button,
1158
+ Card,
1159
+ Badge,
1160
+ Input,
1161
+ Checkbox,
1162
+ Switch,
1163
+ Progress,
1164
+ Spinner,
1165
+ Avatar,
1166
+ Separator
1167
+ } from '@flexireact/flexi-ui';
1168
+ import { Mail, Lock, User, Search, Heart, Star, Check } from 'lucide-react';
1169
+
1170
+ export function Showcase() {
1171
+ return (
1172
+ <section className="py-32 px-6 relative">
1173
+ {/* Background Gradient */}
1174
+ <div className="absolute inset-0 -z-10">
1175
+ <div className="absolute top-1/2 left-1/4 w-[500px] h-[500px] rounded-full bg-gradient-radial from-[#00FF9C]/10 to-transparent blur-3xl" />
1176
+ </div>
1177
+
1178
+ <div className="container mx-auto max-w-6xl">
1179
+ {/* Section Header */}
1180
+ <div className="text-center mb-20">
1181
+ <Badge variant="success" className="mb-6">Components</Badge>
1182
+ <h2 className="text-4xl md:text-5xl font-bold tracking-tight mb-6">
1183
+ Beautiful by default
1184
+ </h2>
1185
+ <p className="text-xl text-[#94a3b8] max-w-2xl mx-auto">
1186
+ 23+ components designed with attention to detail. Dark mode first, accessible, and customizable.
1187
+ </p>
1188
+ </div>
1189
+
1190
+ {/* Component Showcase Grid */}
1191
+ <div className="grid lg:grid-cols-2 gap-8">
1192
+ {/* Buttons Card */}
1193
+ <Card className="p-8">
1194
+ <h3 className="text-lg font-semibold mb-6 flex items-center gap-2">
1195
+ <span className="w-2 h-2 rounded-full bg-[#00FF9C]" />
1196
+ Buttons
1197
+ </h3>
1198
+ <div className="flex flex-wrap gap-3">
1199
+ <Button>Primary</Button>
1200
+ <Button variant="secondary">Secondary</Button>
1201
+ <Button variant="outline">Outline</Button>
1202
+ <Button variant="ghost">Ghost</Button>
1203
+ <Button variant="danger">Danger</Button>
1204
+ <Button variant="link">Link</Button>
1205
+ </div>
1206
+ <Separator className="my-6" />
1207
+ <div className="flex flex-wrap gap-3">
1208
+ <Button size="sm">Small</Button>
1209
+ <Button size="md">Medium</Button>
1210
+ <Button size="lg">Large</Button>
1211
+ </div>
1212
+ <Separator className="my-6" />
1213
+ <div className="flex flex-wrap gap-3">
1214
+ <Button loading>Loading</Button>
1215
+ <Button disabled>Disabled</Button>
1216
+ <Button className="gap-2">
1217
+ <Heart className="w-4 h-4" /> With Icon
1218
+ </Button>
1219
+ </div>
1220
+ </Card>
1221
+
1222
+ {/* Inputs Card */}
1223
+ <Card className="p-8">
1224
+ <h3 className="text-lg font-semibold mb-6 flex items-center gap-2">
1225
+ <span className="w-2 h-2 rounded-full bg-[#00FF9C]" />
1226
+ Inputs
1227
+ </h3>
1228
+ <div className="space-y-4">
1229
+ <Input
1230
+ label="Email"
1231
+ placeholder="you@example.com"
1232
+ type="email"
1233
+ />
1234
+ <Input
1235
+ label="Password"
1236
+ placeholder="Enter password"
1237
+ type="password"
1238
+ />
1239
+ <Input
1240
+ label="Search"
1241
+ placeholder="Search..."
1242
+ />
1243
+ <Input
1244
+ label="With Error"
1245
+ placeholder="Invalid input"
1246
+ error
1247
+ helperText="This field is required"
1248
+ />
1249
+ </div>
1250
+ </Card>
1251
+
1252
+ {/* Badges Card */}
1253
+ <Card className="p-8">
1254
+ <h3 className="text-lg font-semibold mb-6 flex items-center gap-2">
1255
+ <span className="w-2 h-2 rounded-full bg-[#00FF9C]" />
1256
+ Badges & Status
1257
+ </h3>
1258
+ <div className="flex flex-wrap gap-3 mb-6">
1259
+ <Badge>Default</Badge>
1260
+ <Badge variant="success">Success</Badge>
1261
+ <Badge variant="warning">Warning</Badge>
1262
+ <Badge variant="danger">Danger</Badge>
1263
+ <Badge variant="outline">Outline</Badge>
1264
+ </div>
1265
+ <Separator className="my-6" />
1266
+ <h4 className="text-sm font-medium mb-4 text-[#94a3b8]">Progress</h4>
1267
+ <div className="space-y-4">
1268
+ <Progress value={25} />
1269
+ <Progress value={50} />
1270
+ <Progress value={75} />
1271
+ <Progress value={100} />
1272
+ </div>
1273
+ </Card>
1274
+
1275
+ {/* Form Controls Card */}
1276
+ <Card className="p-8">
1277
+ <h3 className="text-lg font-semibold mb-6 flex items-center gap-2">
1278
+ <span className="w-2 h-2 rounded-full bg-[#00FF9C]" />
1279
+ Form Controls
1280
+ </h3>
1281
+ <div className="space-y-6">
1282
+ <div className="flex items-center gap-4">
1283
+ <Checkbox id="terms" />
1284
+ <label htmlFor="terms" className="text-sm">Accept terms and conditions</label>
1285
+ </div>
1286
+ <div className="flex items-center gap-4">
1287
+ <Checkbox id="newsletter" defaultChecked />
1288
+ <label htmlFor="newsletter" className="text-sm">Subscribe to newsletter</label>
1289
+ </div>
1290
+ <Separator />
1291
+ <div className="flex items-center justify-between">
1292
+ <span className="text-sm">Dark Mode</span>
1293
+ <Switch defaultChecked />
1294
+ </div>
1295
+ <div className="flex items-center justify-between">
1296
+ <span className="text-sm">Notifications</span>
1297
+ <Switch />
1298
+ </div>
1299
+ <Separator />
1300
+ <div className="flex items-center gap-4">
1301
+ <Spinner size="sm" />
1302
+ <Spinner />
1303
+ <Spinner size="lg" />
1304
+ </div>
1305
+ </div>
1306
+ </Card>
1307
+ </div>
1308
+
1309
+ {/* Avatars Row */}
1310
+ <Card className="p-8 mt-8">
1311
+ <h3 className="text-lg font-semibold mb-6 flex items-center gap-2">
1312
+ <span className="w-2 h-2 rounded-full bg-[#00FF9C]" />
1313
+ Avatars
1314
+ </h3>
1315
+ <div className="flex items-center gap-4 flex-wrap">
1316
+ <Avatar size="sm" fallback="JD" />
1317
+ <Avatar fallback="AB" />
1318
+ <Avatar size="lg" fallback="CD" />
1319
+ <Avatar size="xl" fallback="EF" />
1320
+ <Separator orientation="vertical" className="h-12 mx-4" />
1321
+ <div className="flex -space-x-3">
1322
+ <Avatar fallback="A" className="ring-2 ring-[#0a0a0a]" />
1323
+ <Avatar fallback="B" className="ring-2 ring-[#0a0a0a]" />
1324
+ <Avatar fallback="C" className="ring-2 ring-[#0a0a0a]" />
1325
+ <Avatar fallback="+5" className="ring-2 ring-[#0a0a0a]" />
1326
+ </div>
1327
+ </div>
1328
+ </Card>
1329
+ </div>
1330
+ </section>
1331
+ );
1332
+ }
1333
+ `,
1334
+
1335
+ 'components/Footer.tsx': () => `import React from 'react';
1336
+ import { Separator } from '@flexireact/flexi-ui';
1337
+ import { Github, Twitter, Heart } from 'lucide-react';
1338
+
1339
+ export function Footer() {
1340
+ return (
1341
+ <footer className="border-t border-[#1e293b]">
1342
+ <div className="container mx-auto max-w-6xl px-6 py-12">
1343
+ <div className="flex flex-col md:flex-row items-center justify-between gap-6">
1344
+ {/* Logo & Copyright */}
1345
+ <div className="flex items-center gap-3">
1346
+ <div className="w-8 h-8 rounded-lg bg-gradient-to-br from-[#00FF9C] to-emerald-400 flex items-center justify-center">
430
1347
  <span className="text-black font-bold text-sm">F</span>
431
1348
  </div>
432
- <span className="font-bold text-xl">FlexiReact</span>
433
- </a>
434
- <div className="flex items-center gap-4">
435
- <a href="/" className="text-sm opacity-70 hover:opacity-100">Home</a>
436
- <a href="/about" className="text-sm opacity-70 hover:opacity-100">About</a>
1349
+ <span className="text-[#94a3b8] text-sm">
1350
+ Built with <Heart className="w-4 h-4 inline text-red-500 mx-1" /> using{' '}
1351
+ <a href="https://github.com/flexireact/flexi-ui" className="text-[#00FF9C] hover:underline">
1352
+ Flexi UI
1353
+ </a>
1354
+ </span>
437
1355
  </div>
438
- </nav>
439
- </header>
440
- <main className="flex-1">
441
- {children}
442
- </main>
443
- <footer className="border-t border-[var(--flexi-border)] py-8 text-center text-sm opacity-70">
444
- Built with FlexiReact
445
- </footer>
446
- </div>
1356
+
1357
+ {/* Links */}
1358
+ <div className="flex items-center gap-6">
1359
+ <a
1360
+ href="https://github.com/flexireact/flexi-ui"
1361
+ className="text-[#94a3b8] hover:text-white transition-colors flex items-center gap-2 text-sm"
1362
+ >
1363
+ <Github className="w-4 h-4" />
1364
+ GitHub
1365
+ </a>
1366
+ <a
1367
+ href="https://github.com/flexireact/flexireact"
1368
+ className="text-[#94a3b8] hover:text-white transition-colors text-sm"
1369
+ >
1370
+ Documentation
1371
+ </a>
1372
+ <a
1373
+ href="https://github.com/flexireact/flexi-ui"
1374
+ className="text-[#94a3b8] hover:text-white transition-colors text-sm"
1375
+ >
1376
+ Components
1377
+ </a>
1378
+ </div>
1379
+ </div>
1380
+ </div>
1381
+ </footer>
447
1382
  );
448
1383
  }
449
- ` : `import React from 'react';
1384
+ `,
1385
+
1386
+ 'components/Navbar.tsx': () => `import React from 'react';
1387
+ import { Button, Badge } from '@flexireact/flexi-ui';
1388
+ import { Github, Menu } from 'lucide-react';
1389
+
1390
+ export function Navbar() {
1391
+ return (
1392
+ <header className="fixed top-0 left-0 right-0 z-50 border-b border-[#1e293b]/50 bg-[#0a0a0a]/80 backdrop-blur-xl">
1393
+ <nav className="container mx-auto max-w-6xl px-6 h-16 flex items-center justify-between">
1394
+ {/* Logo */}
1395
+ <a href="/" className="flex items-center gap-3 group">
1396
+ <div className="w-9 h-9 rounded-xl bg-gradient-to-br from-[#00FF9C] to-emerald-400 flex items-center justify-center shadow-lg shadow-[#00FF9C]/20 group-hover:shadow-[#00FF9C]/40 transition-shadow">
1397
+ <span className="text-black font-black text-lg">F</span>
1398
+ </div>
1399
+ <span className="text-lg font-bold">Flexi UI</span>
1400
+ <Badge variant="outline" className="hidden sm:flex text-xs">v1.0</Badge>
1401
+ </a>
1402
+
1403
+ {/* Desktop Nav */}
1404
+ <div className="hidden md:flex items-center gap-2">
1405
+ <Button variant="ghost" size="sm">
1406
+ <a href="https://github.com/flexireact/flexi-ui">Docs</a>
1407
+ </Button>
1408
+ <Button variant="ghost" size="sm">
1409
+ <a href="https://github.com/flexireact/flexi-ui">Components</a>
1410
+ </Button>
1411
+ <Button variant="ghost" size="sm">
1412
+ <a href="https://github.com/flexireact/flexireact">FlexiReact</a>
1413
+ </Button>
1414
+ <div className="w-px h-6 bg-[#1e293b] mx-2" />
1415
+ <Button variant="outline" size="sm" className="gap-2">
1416
+ <Github className="w-4 h-4" />
1417
+ <a href="https://github.com/flexireact/flexi-ui">GitHub</a>
1418
+ </Button>
1419
+ </div>
1420
+
1421
+ {/* Mobile Menu Button */}
1422
+ <Button variant="ghost" size="sm" className="md:hidden">
1423
+ <Menu className="w-5 h-5" />
1424
+ </Button>
1425
+ </nav>
1426
+ </header>
1427
+ );
1428
+ }
1429
+ `,
1430
+
1431
+ 'components/index.ts': () => `export { Hero } from './Hero';
1432
+ export { Features } from './Features';
1433
+ export { Showcase } from './Showcase';
1434
+ export { Footer } from './Footer';
1435
+ export { Navbar } from './Navbar';
1436
+ `,
1437
+
1438
+ // ============================================================================
1439
+ // Pages & Layouts
1440
+ // ============================================================================
1441
+
1442
+ 'layouts/root.tsx': () => `import React from 'react';
1443
+ import { ThemeProvider } from '@flexireact/flexi-ui';
1444
+ import { Navbar } from '../components/Navbar';
1445
+ import { Footer } from '../components/Footer';
450
1446
 
451
1447
  interface LayoutProps {
452
1448
  children: React.ReactNode;
@@ -454,72 +1450,163 @@ interface LayoutProps {
454
1450
 
455
1451
  export default function RootLayout({ children }: LayoutProps) {
456
1452
  return (
457
- <div className="min-h-screen bg-slate-900 text-white">
458
- <header className="sticky top-0 z-50 border-b border-slate-700 bg-slate-900/80 backdrop-blur-sm">
459
- <nav className="container mx-auto px-4 h-16 flex items-center justify-between">
460
- <a href="/" className="flex items-center gap-2 font-bold text-xl">
461
- <span className="text-emerald-400">⚡</span> FlexiReact
462
- </a>
463
- <div className="flex items-center gap-6">
464
- <a href="/" className="text-sm text-slate-400 hover:text-white">Home</a>
465
- <a href="/about" className="text-sm text-slate-400 hover:text-white">About</a>
466
- <a href="https://github.com/flexireact/flexireact" className="text-sm px-4 py-2 bg-emerald-500 text-black rounded-lg font-medium hover:bg-emerald-400">
467
- GitHub
468
- </a>
469
- </div>
470
- </nav>
471
- </header>
472
- <main className="flex-1">
473
- {children}
474
- </main>
475
- <footer className="border-t border-slate-700 py-8 text-center text-sm text-slate-500">
476
- Built with ❤️ using FlexiReact
477
- </footer>
478
- </div>
1453
+ <ThemeProvider defaultTheme="dark">
1454
+ <div className="min-h-screen bg-[#0a0a0a] text-white antialiased">
1455
+ <Navbar />
1456
+ <main className="pt-16">{children}</main>
1457
+ <Footer />
1458
+ </div>
1459
+ </ThemeProvider>
1460
+ );
1461
+ }
1462
+ `,
1463
+
1464
+ 'pages/index.tsx': () => `import React from 'react';
1465
+ import { Hero } from '../components/Hero';
1466
+ import { Features } from '../components/Features';
1467
+ import { Showcase } from '../components/Showcase';
1468
+
1469
+ export default function HomePage() {
1470
+ return (
1471
+ <>
1472
+ <Hero />
1473
+ <Features />
1474
+ <Showcase />
1475
+ </>
479
1476
  );
480
1477
  }
481
1478
  `,
482
1479
 
483
- 'app/styles/input.css': () => `@tailwind base;
1480
+ // ============================================================================
1481
+ // Styles
1482
+ // ============================================================================
1483
+
1484
+ 'app/styles/globals.css': () => `@tailwind base;
484
1485
  @tailwind components;
485
1486
  @tailwind utilities;
486
1487
 
487
1488
  @layer base {
488
1489
  :root {
489
- --flexi-bg: #0f172a;
490
- --flexi-fg: #f8fafc;
491
- --flexi-bg-subtle: #1e293b;
492
- --flexi-bg-muted: #334155;
493
- --flexi-border: #475569;
494
- --flexi-fg-muted: #94a3b8;
495
- --flexi-primary: #10b981;
1490
+ --flexi-bg: #0a0a0a;
1491
+ --flexi-fg: #fafafa;
1492
+ --flexi-primary: #00FF9C;
1493
+ --flexi-primary-fg: #000000;
1494
+ --flexi-muted: #94a3b8;
1495
+ --flexi-border: #1e293b;
1496
+ --flexi-card: #0f0f0f;
496
1497
  }
497
-
1498
+
1499
+ * {
1500
+ border-color: var(--flexi-border);
1501
+ }
1502
+
498
1503
  html {
499
1504
  scroll-behavior: smooth;
500
1505
  }
501
-
1506
+
502
1507
  body {
503
- font-family: 'Inter', system-ui, sans-serif;
504
- background-color: #0f172a;
505
- color: #f8fafc;
1508
+ font-family: 'Inter', system-ui, -apple-system, sans-serif;
1509
+ background-color: var(--flexi-bg);
1510
+ color: var(--flexi-fg);
506
1511
  min-height: 100vh;
1512
+ -webkit-font-smoothing: antialiased;
1513
+ -moz-osx-font-smoothing: grayscale;
1514
+ }
1515
+
1516
+ ::selection {
1517
+ background-color: rgba(0, 255, 156, 0.3);
1518
+ color: white;
1519
+ }
1520
+ }
1521
+
1522
+ @layer utilities {
1523
+ .bg-gradient-radial {
1524
+ background: radial-gradient(circle, var(--tw-gradient-stops));
1525
+ }
1526
+
1527
+ .text-balance {
1528
+ text-wrap: balance;
1529
+ }
1530
+
1531
+ /* Custom scrollbar */
1532
+ ::-webkit-scrollbar {
1533
+ width: 8px;
1534
+ height: 8px;
1535
+ }
1536
+
1537
+ ::-webkit-scrollbar-track {
1538
+ background: #0a0a0a;
1539
+ }
1540
+
1541
+ ::-webkit-scrollbar-thumb {
1542
+ background: #1e293b;
1543
+ border-radius: 4px;
1544
+ }
1545
+
1546
+ ::-webkit-scrollbar-thumb:hover {
1547
+ background: #334155;
1548
+ }
1549
+ }
1550
+
1551
+ /* Animation utilities */
1552
+ .animate-fade-in {
1553
+ animation: fadeIn 0.6s ease-out forwards;
1554
+ opacity: 0;
1555
+ }
1556
+
1557
+ .animate-fade-up {
1558
+ animation: fadeUp 0.6s ease-out forwards;
1559
+ opacity: 0;
1560
+ }
1561
+
1562
+ .animate-scale-in {
1563
+ animation: scaleIn 0.4s ease-out forwards;
1564
+ opacity: 0;
1565
+ }
1566
+
1567
+ @keyframes fadeIn {
1568
+ from { opacity: 0; }
1569
+ to { opacity: 1; }
1570
+ }
1571
+
1572
+ @keyframes fadeUp {
1573
+ from {
1574
+ opacity: 0;
1575
+ transform: translateY(30px);
1576
+ }
1577
+ to {
1578
+ opacity: 1;
1579
+ transform: translateY(0);
1580
+ }
1581
+ }
1582
+
1583
+ @keyframes scaleIn {
1584
+ from {
1585
+ opacity: 0;
1586
+ transform: scale(0.9);
1587
+ }
1588
+ to {
1589
+ opacity: 1;
1590
+ transform: scale(1);
507
1591
  }
508
1592
  }
509
1593
  `,
510
1594
 
1595
+ // ============================================================================
1596
+ // Public Assets
1597
+ // ============================================================================
1598
+
511
1599
  'public/.gitkeep': () => '',
512
1600
 
513
1601
  'public/favicon.svg': () => `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
514
1602
  <defs>
515
1603
  <linearGradient id="grad" x1="0%" y1="0%" x2="100%" y2="100%">
516
- <stop offset="0%" style="stop-color:#10b981"/>
517
- <stop offset="100%" style="stop-color:#06b6d4"/>
1604
+ <stop offset="0%" style="stop-color:#00FF9C"/>
1605
+ <stop offset="100%" style="stop-color:#10b981"/>
518
1606
  </linearGradient>
519
1607
  </defs>
520
- <rect width="100" height="100" rx="20" fill="#0f172a"/>
521
- <path d="M25 70V30h30v10H37v8h15v10H37v12H25z" fill="url(#grad)"/>
522
- <circle cx="65" cy="65" r="8" fill="url(#grad)"/>
1608
+ <rect width="100" height="100" rx="20" fill="#0a0a0a"/>
1609
+ <text x="50" y="68" font-family="system-ui" font-size="50" font-weight="900" fill="url(#grad)" text-anchor="middle">F</text>
523
1610
  </svg>`,
524
1611
  };
525
1612
 
@@ -548,50 +1635,67 @@ async function main() {
548
1635
 
549
1636
  // Check if directory exists
550
1637
  if (fs.existsSync(projectPath) && !isDirEmpty(projectPath)) {
551
- error(`Directory "${projectName}" already exists and is not empty`);
1638
+ error(`Directory ${projectName} already exists and is not empty`);
552
1639
  process.exit(1);
553
1640
  }
554
1641
 
555
- console.log('');
556
-
557
1642
  // Select template
1643
+ console.log('');
558
1644
  const templateOptions = Object.entries(TEMPLATES).map(([key, value]) => ({
559
1645
  key,
560
1646
  ...value,
561
1647
  }));
562
1648
 
563
1649
  const selectedTemplate = await select('Select a template:', templateOptions);
564
- const template = selectedTemplate.key;
1650
+ const templateKey = selectedTemplate.key;
565
1651
 
566
1652
  console.log('');
567
- console.log(` ${c.dim}Creating project in${c.reset} ${c.cyan}${projectPath}${c.reset}`);
1653
+ log(`Creating project in ${c.cyan}${projectPath}${c.reset}`);
568
1654
  console.log('');
569
1655
 
570
1656
  // Create project directory
571
1657
  const spinner1 = new Spinner('Creating project structure...');
572
1658
  spinner1.start();
573
-
1659
+
574
1660
  try {
575
1661
  fs.mkdirSync(projectPath, { recursive: true });
576
- fs.mkdirSync(path.join(projectPath, 'pages'), { recursive: true });
577
- fs.mkdirSync(path.join(projectPath, 'layouts'), { recursive: true });
578
- fs.mkdirSync(path.join(projectPath, 'app', 'styles'), { recursive: true });
579
- fs.mkdirSync(path.join(projectPath, 'public'), { recursive: true });
580
- fs.mkdirSync(path.join(projectPath, 'components'), { recursive: true });
1662
+
1663
+ // Create subdirectories
1664
+ let dirs;
1665
+ if (templateKey === 'minimal') {
1666
+ dirs = ['pages', 'public'];
1667
+ } else if (templateKey === 'flexi-ui') {
1668
+ dirs = ['pages', 'public', 'components', 'layouts', 'app/styles'];
1669
+ } else {
1670
+ dirs = ['pages', 'public', 'components', 'components/ui', 'layouts', 'app/styles', 'lib'];
1671
+ }
1672
+
1673
+ for (const dir of dirs) {
1674
+ fs.mkdirSync(path.join(projectPath, dir), { recursive: true });
1675
+ }
581
1676
 
582
1677
  spinner1.stop(true);
583
1678
  } catch (err) {
584
1679
  spinner1.stop(false);
585
- error(`Failed to create directory: ${err.message}`);
1680
+ error(`Failed to create project structure: ${err.message}`);
586
1681
  process.exit(1);
587
1682
  }
588
1683
 
589
1684
  // Write template files
590
1685
  const spinner2 = new Spinner('Writing template files...');
591
1686
  spinner2.start();
592
-
1687
+
593
1688
  try {
594
- for (const [filePath, generator] of Object.entries(TEMPLATE_FILES)) {
1689
+ let files;
1690
+ if (templateKey === 'minimal') {
1691
+ files = MINIMAL_FILES;
1692
+ } else if (templateKey === 'flexi-ui') {
1693
+ files = FLEXI_UI_FILES;
1694
+ } else {
1695
+ files = TEMPLATE_FILES;
1696
+ }
1697
+
1698
+ for (const [filePath, contentFn] of Object.entries(files)) {
595
1699
  const fullPath = path.join(projectPath, filePath);
596
1700
  const dir = path.dirname(fullPath);
597
1701
 
@@ -599,51 +1703,25 @@ async function main() {
599
1703
  fs.mkdirSync(dir, { recursive: true });
600
1704
  }
601
1705
 
602
- const content = generator(projectName, template);
1706
+ const content = contentFn(projectName, templateKey);
603
1707
  fs.writeFileSync(fullPath, content);
604
1708
  }
605
1709
 
606
1710
  spinner2.stop(true);
607
1711
  } catch (err) {
608
1712
  spinner2.stop(false);
609
- error(`Failed to write files: ${err.message}`);
1713
+ error(`Failed to write template files: ${err.message}`);
610
1714
  process.exit(1);
611
1715
  }
612
1716
 
613
- // Create .gitignore
1717
+ // Create README
614
1718
  const spinner3 = new Spinner('Creating configuration files...');
615
1719
  spinner3.start();
616
-
1720
+
617
1721
  try {
618
- fs.writeFileSync(path.join(projectPath, '.gitignore'), `# Dependencies
619
- node_modules/
620
-
621
- # Build
622
- .flexi/
623
- dist/
624
- build/
1722
+ const readmeContent = `# ${projectName}
625
1723
 
626
- # Environment
627
- .env
628
- .env.local
629
- .env.*.local
630
-
631
- # IDE
632
- .vscode/
633
- .idea/
634
-
635
- # OS
636
- .DS_Store
637
- Thumbs.db
638
-
639
- # Logs
640
- *.log
641
- npm-debug.log*
642
- `);
643
-
644
- fs.writeFileSync(path.join(projectPath, 'README.md'), `# ${projectName}
645
-
646
- A FlexiReact application.
1724
+ A modern web application built with [FlexiReact](https://github.com/flexireact/flexireact).
647
1725
 
648
1726
  ## Getting Started
649
1727
 
@@ -657,9 +1735,9 @@ Open [http://localhost:3000](http://localhost:3000) in your browser.
657
1735
  ## Learn More
658
1736
 
659
1737
  - [FlexiReact Documentation](https://github.com/flexireact/flexireact)
660
- - [FlexiUI Components](https://github.com/flexireact/flexi-ui)
661
- `);
1738
+ `;
662
1739
 
1740
+ fs.writeFileSync(path.join(projectPath, 'README.md'), readmeContent);
663
1741
  spinner3.stop(true);
664
1742
  } catch (err) {
665
1743
  spinner3.stop(false);
@@ -667,7 +1745,7 @@ Open [http://localhost:3000](http://localhost:3000) in your browser.
667
1745
  process.exit(1);
668
1746
  }
669
1747
 
670
- // Done!
1748
+ // Success message
671
1749
  console.log(SUCCESS_BANNER(projectName));
672
1750
  }
673
1751