create-flexireact 3.0.7 → 4.1.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.
@@ -0,0 +1,606 @@
1
+ export function fullstackTemplate(projectName, options = {}) {
2
+ const isTailwind = options.styling !== 'css'; // Default to Tailwind
3
+ return {
4
+ // ========================================================================
5
+ // Config Files
6
+ // ========================================================================
7
+ 'package.json': JSON.stringify({
8
+ name: projectName,
9
+ version: '1.0.0',
10
+ private: true,
11
+ type: 'module',
12
+ scripts: {
13
+ dev: isTailwind ? 'npm run css && flexireact dev' : 'flexireact dev',
14
+ build: isTailwind ? 'npm run css && flexireact build' : 'flexireact build',
15
+ start: 'flexireact start',
16
+ ...(isTailwind ? { css: 'tailwindcss -i ./app/styles/globals.css -o ./public/styles.css --minify' } : {}),
17
+ 'db:generate': 'drizzle-kit generate',
18
+ 'db:migrate': 'drizzle-kit migrate',
19
+ 'db:studio': 'drizzle-kit studio',
20
+ },
21
+ dependencies: {
22
+ react: '^19.0.0',
23
+ 'react-dom': '^19.0.0',
24
+ '@flexireact/core': '^4.1.0',
25
+ '@flexireact/flexiguard': '^1.0.0',
26
+ 'drizzle-orm': '^0.30.0',
27
+ 'better-sqlite3': '^9.4.0',
28
+ 'lucide-react': '^0.344.0',
29
+ clsx: '^2.1.0',
30
+ 'tailwind-merge': '^2.2.0',
31
+ },
32
+ devDependencies: {
33
+ '@types/react': '^19.0.0',
34
+ '@types/react-dom': '^19.0.0',
35
+ '@types/better-sqlite3': '^7.6.9',
36
+ typescript: '^5.3.0',
37
+ 'drizzle-kit': '^0.20.14',
38
+ ...(isTailwind ? {
39
+ tailwindcss: '^4.0.0',
40
+ '@tailwindcss/cli': '^4.0.0',
41
+ '@tailwindcss/postcss': '^4.0.0',
42
+ } : {}),
43
+ },
44
+ }, null, 2),
45
+ 'tsconfig.json': JSON.stringify({
46
+ compilerOptions: {
47
+ target: 'ES2022',
48
+ lib: ['DOM', 'DOM.Iterable', 'ES2022'],
49
+ module: 'ESNext',
50
+ moduleResolution: 'bundler',
51
+ jsx: 'react-jsx',
52
+ strict: true,
53
+ skipLibCheck: true,
54
+ esModuleInterop: true,
55
+ resolveJsonModule: true,
56
+ isolatedModules: true,
57
+ noEmit: true,
58
+ baseUrl: '.',
59
+ paths: {
60
+ '@/*': ['./*'],
61
+ },
62
+ },
63
+ include: ['**/*.ts', '**/*.tsx'],
64
+ exclude: ['node_modules', '.flexi', 'public'],
65
+ }, null, 2),
66
+ 'drizzle.config.ts': `import type { Config } from 'drizzle-kit';
67
+
68
+ export default {
69
+ schema: './schema.ts',
70
+ out: './drizzle',
71
+ driver: 'better-sqlite',
72
+ dbCredentials: {
73
+ url: 'sqlite.db',
74
+ },
75
+ } satisfies Config;
76
+ `,
77
+ ...(isTailwind ? {
78
+ 'postcss.config.js': `export default {
79
+ plugins: {
80
+ "@tailwindcss/postcss": {},
81
+ },
82
+ };
83
+ `,
84
+ } : {}),
85
+ 'flexireact.config.js': `/** @type {import('@flexireact/core').FlexiConfig} */
86
+ const config = {
87
+ styles: [
88
+ '/styles.css',
89
+ 'https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap'
90
+ ],
91
+ server: {
92
+ port: 3000,
93
+ },
94
+ islands: { enabled: true },
95
+ };
96
+
97
+ export default config;
98
+ `,
99
+ // ========================================================================
100
+ // Database & Auth
101
+ // ========================================================================
102
+ 'schema.ts': `import { sqliteTable, text, integer } from 'drizzle-orm/sqlite-core';
103
+
104
+ export const users = sqliteTable('users', {
105
+ id: text('id').primaryKey(),
106
+ email: text('email').notNull().unique(),
107
+ passwordHash: text('password_hash').notNull(),
108
+ name: text('name'),
109
+ avatar: text('avatar'),
110
+ role: text('role').default('user'),
111
+ createdAt: integer('created_at', { mode: 'timestamp' }).notNull().default(new Date()),
112
+ });
113
+
114
+ export const sessions = sqliteTable('sessions', {
115
+ id: text('id').primaryKey(),
116
+ userId: text('user_id').notNull().references(() => users.id),
117
+ token: text('token').notNull().unique(),
118
+ expiresAt: integer('expires_at', { mode: 'timestamp' }).notNull(),
119
+ });
120
+
121
+ export const items = sqliteTable('items', {
122
+ id: text('id').primaryKey(), // We'll manage IDs in app or use default random
123
+ userId: text('user_id').notNull().references(() => users.id),
124
+ content: text('content').notNull(),
125
+ completed: integer('completed', { mode: 'boolean' }).default(false),
126
+ createdAt: integer('created_at', { mode: 'timestamp' }).notNull().default(new Date()),
127
+ });
128
+ `,
129
+ 'lib/db.ts': `import { drizzle } from 'drizzle-orm/better-sqlite3';
130
+ import Database from 'better-sqlite3';
131
+ import * as schema from '../schema';
132
+
133
+ const sqlite = new Database('sqlite.db');
134
+ export const db = drizzle(sqlite, { schema });
135
+ `,
136
+ 'lib/auth.ts': `import { createAuth } from '@flexireact/flexiguard';
137
+ import { DrizzleAdapter } from '@flexireact/flexiguard/adapters/drizzle';
138
+ import { db } from './db';
139
+ import * as schema from '../schema';
140
+
141
+ export const auth = createAuth({
142
+ adapter: DrizzleAdapter({ db, schema }),
143
+ session: {
144
+ strategy: 'database',
145
+ maxAge: 30 * 24 * 60 * 60, // 30 days
146
+ },
147
+ password: {
148
+ minLength: 8,
149
+ },
150
+ });
151
+ `,
152
+ // ========================================================================
153
+ // App Structure
154
+ // ========================================================================
155
+ 'app/layout.tsx': `import React from 'react';
156
+ import { Navbar } from './components/layout/Navbar';
157
+ import { Footer } from './components/layout/Footer';
158
+
159
+ interface RootLayoutProps {
160
+ children: React.ReactNode;
161
+ }
162
+
163
+ export default function RootLayout({ children }: RootLayoutProps) {
164
+ return (
165
+ <html lang="en" className="dark">
166
+ <head>
167
+ <meta charSet="UTF-8" />
168
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
169
+ <link rel="stylesheet" href="/styles.css" />
170
+ </head>
171
+ <body className="${isTailwind ? 'bg-background text-foreground min-h-screen antialiased flex flex-col' : 'app-body'}">
172
+ <Navbar />
173
+ <main className="${isTailwind ? 'flex-1' : 'main-content'}">{children}</main>
174
+ <Footer />
175
+ </body>
176
+ </html>
177
+ );
178
+ }
179
+ `,
180
+ // ========================================================================
181
+ // Routes
182
+ // ========================================================================
183
+ 'routes/(public)/home.tsx': `import React from 'react';
184
+ import { Button } from '@/app/components/ui/Button';
185
+ import { Shield, Database, Zap } from 'lucide-react';
186
+
187
+ export const metadata = {
188
+ title: 'FlexiStack - Production Ready Starter',
189
+ description: 'Fullstack React framework with Auth, Database, and API routes.',
190
+ };
191
+
192
+ export default function HomePage() {
193
+ return (
194
+ <div className="${isTailwind ? 'flex flex-col items-center justify-center min-h-[calc(100vh-8rem)] px-4 py-16' : 'home-page'}">
195
+ <div className="${isTailwind ? 'max-w-4xl mx-auto text-center space-y-8' : 'container'}">
196
+ <div className="${isTailwind ? 'inline-flex items-center gap-2 px-3 py-1 rounded-full bg-primary/10 border border-primary/20 text-primary text-sm font-medium' : 'badge'}">
197
+ <span>🚀 Production Ready</span>
198
+ </div>
199
+
200
+ <h1 className="${isTailwind ? 'text-5xl md:text-7xl font-bold tracking-tight' : 'page-title'}">
201
+ Build faster with
202
+ <br />
203
+ <span className="${isTailwind ? 'text-primary' : 'highlight'}">FlexiStack</span>
204
+ </h1>
205
+
206
+ <p className="${isTailwind ? 'text-xl text-muted-foreground max-w-2xl mx-auto' : 'subtitle'}">
207
+ The ultimate starter with FlexiReact v4, FlexiGuard Auth, Drizzle ORM, and CRUD API examples.
208
+ </p>
209
+
210
+ <div className="${isTailwind ? 'flex gap-4 justify-center pt-4' : 'actions'}">
211
+ <Button size="lg" href="/login">Get Started</Button>
212
+ <Button variant="outline" size="lg" href="/dashboard">View Dashboard</Button>
213
+ </div>
214
+
215
+ <div className="${isTailwind ? 'grid grid-cols-1 md:grid-cols-3 gap-8 pt-16 text-left' : 'features-grid'}">
216
+ <Feature
217
+ icon={<Shield className="w-6 h-6 text-primary" />}
218
+ title="Authentication"
219
+ desc="Secure auth powered by FlexiGuard. Login, register, and session management ready to go."
220
+ />
221
+ <Feature
222
+ icon={<Database className="w-6 h-6 text-primary" />}
223
+ title="Database"
224
+ desc="Drizzle ORM with SQLite. Type-safe database queries, schemas, and migrations."
225
+ />
226
+ <Feature
227
+ icon={<Zap className="w-6 h-6 text-primary" />}
228
+ title="API Routes"
229
+ desc="Integrated API routes with CRUD operations. Build your backend alongside your UI."
230
+ />
231
+ </div>
232
+ </div>
233
+ </div>
234
+ );
235
+ }
236
+
237
+ function Feature({ icon, title, desc }: any) {
238
+ return (
239
+ <div className="${isTailwind ? 'p-6 rounded-xl border border-border bg-card' : 'feature-card'}">
240
+ <div className="${isTailwind ? 'mb-4' : 'feature-icon'}">{icon}</div>
241
+ <h3 className="${isTailwind ? 'text-lg font-semibold mb-2' : 'feature-title'}">{title}</h3>
242
+ <p className="${isTailwind ? 'text-muted-foreground' : 'feature-desc'}">{desc}</p>
243
+ </div>
244
+ );
245
+ }
246
+ `,
247
+ 'routes/(auth)/login.tsx': `import React from 'react';
248
+ import { Button } from '@/app/components/ui/Button';
249
+
250
+ export const metadata = {
251
+ title: 'Login - FlexiStack',
252
+ };
253
+
254
+ export default function LoginPage() {
255
+ return (
256
+ <div className="${isTailwind ? 'flex items-center justify-center min-h-[calc(100vh-16rem)]' : 'auth-page'}">
257
+ <div className="${isTailwind ? 'w-full max-w-md p-8 rounded-xl border border-border bg-card' : 'auth-card'}">
258
+ <h1 className="${isTailwind ? 'text-2xl font-bold mb-6 text-center' : 'auth-title'}">Welcome Back</h1>
259
+ <form className="space-y-4" action="/api/auth/login" method="POST">
260
+ <div>
261
+ <label className="${isTailwind ? 'block text-sm font-medium mb-1' : 'label'}">Email</label>
262
+ <input
263
+ type="email"
264
+ name="email"
265
+ className="${isTailwind ? 'w-full px-3 py-2 rounded-lg bg-background border border-border focus:ring-2 focus:ring-primary/50 outline-none' : 'input'}"
266
+ placeholder="john@example.com"
267
+ required
268
+ />
269
+ </div>
270
+ <div>
271
+ <label className="${isTailwind ? 'block text-sm font-medium mb-1' : 'label'}">Password</label>
272
+ <input
273
+ type="password"
274
+ name="password"
275
+ className="${isTailwind ? 'w-full px-3 py-2 rounded-lg bg-background border border-border focus:ring-2 focus:ring-primary/50 outline-none' : 'input'}"
276
+ placeholder="••••••••"
277
+ required
278
+ />
279
+ </div>
280
+ <Button type="submit" className="w-full">Sign In</Button>
281
+ </form>
282
+ <p className="${isTailwind ? 'mt-4 text-center text-sm text-muted-foreground' : 'auth-footer'}">
283
+ Don't have an account? <a href="/register" className="text-primary hover:underline">Sign up</a>
284
+ </p>
285
+ </div>
286
+ </div>
287
+ );
288
+ }
289
+ `,
290
+ 'routes/(app)/dashboard.tsx': `import React from 'react';
291
+ import { Button } from '@/app/components/ui/Button';
292
+
293
+ // Mock data fetch - in real implementation this uses internal API or DB call
294
+ async function getItems() {
295
+ // In a real SSR environment, you would call your DB here directly
296
+ // const items = await db.select().from(schema.items).where(...)
297
+ return [
298
+ { id: '1', content: 'Review pull requests', completed: true },
299
+ { id: '2', content: 'Update documentation', completed: false },
300
+ { id: '3', content: 'Launch v4.0', completed: false },
301
+ ];
302
+ }
303
+
304
+ export const metadata = {
305
+ title: 'Dashboard - FlexiStack',
306
+ };
307
+
308
+ export default async function DashboardPage() {
309
+ // const session = await auth.getSession();
310
+ // if (!session) return redirect('/login');
311
+
312
+ const user = { name: 'Demo User', email: 'demo@example.com' };
313
+ const items = await getItems();
314
+
315
+ return (
316
+ <div className="${isTailwind ? 'container mx-auto px-4 py-8' : 'dashboard-page'}">
317
+ <div className="${isTailwind ? 'flex items-center justify-between mb-8' : 'dashboard-header'}">
318
+ <div>
319
+ <h1 className="text-3xl font-bold">Dashboard</h1>
320
+ <p className="text-muted-foreground">Welcome back, {user.name}</p>
321
+ </div>
322
+ <form action="/api/auth/logout" method="POST">
323
+ <Button variant="outline">Sign Out</Button>
324
+ </form>
325
+ </div>
326
+
327
+ <div className="${isTailwind ? 'grid grid-cols-1 lg:grid-cols-3 gap-8' : 'dashboard-grid'}">
328
+ {/* Profile Card */}
329
+ <div className="${isTailwind ? 'p-6 rounded-xl border border-border bg-card h-fit' : 'dashboard-card'}">
330
+ <h2 className="text-xl font-semibold mb-4">Profile</h2>
331
+ <div className="space-y-4">
332
+ <div className="flex items-center gap-4">
333
+ <div className="w-12 h-12 rounded-full bg-primary/20 flex items-center justify-center text-primary font-bold text-xl">
334
+ {user.name.charAt(0)}
335
+ </div>
336
+ <div>
337
+ <div className="font-medium">{user.name}</div>
338
+ <div className="text-sm text-muted-foreground">{user.email}</div>
339
+ </div>
340
+ </div>
341
+ <div className="pt-4 border-t border-border">
342
+ <div className="text-sm text-muted-foreground mb-1">Role</div>
343
+ <div className="inline-flex items-center px-2 py-1 rounded bg-primary/10 text-primary text-xs font-medium">
344
+ Admin
345
+ </div>
346
+ </div>
347
+ </div>
348
+ </div>
349
+
350
+ {/* Todo List / Items (CRUD Example) */}
351
+ <div className="${isTailwind ? 'col-span-1 lg:col-span-2 p-6 rounded-xl border border-border bg-card' : 'dashboard-card'}">
352
+ <div className="flex items-center justify-between mb-6">
353
+ <h2 className="text-xl font-semibold">Your Tasks</h2>
354
+ <form action="/api/items" method="POST" className="flex gap-2">
355
+ <input
356
+ type="text"
357
+ name="content"
358
+ placeholder="New task..."
359
+ className="${isTailwind ? 'px-3 py-1.5 rounded-lg bg-background border border-border text-sm focus:ring-1 focus:ring-primary outline-none' : 'input'}"
360
+ required
361
+ />
362
+ <Button size="sm">Add</Button>
363
+ </form>
364
+ </div>
365
+
366
+ <div className="space-y-2">
367
+ {items.length > 0 ? (
368
+ items.map((item) => (
369
+ <div key={item.id} className="${isTailwind ? 'flex items-center justify-between p-3 rounded-lg border border-border bg-background/50 hover:bg-background transition-colors' : 'list-item'}">
370
+ <div className="flex items-center gap-3">
371
+ <form action={\`/api/items/\${item.id}/toggle\`} method="POST">
372
+ <button className={\`w-5 h-5 rounded border flex items-center justify-center transition-colors \${item.completed ? 'bg-primary border-primary text-black' : 'border-muted-foreground'}\`}>
373
+ {item.completed && '✓'}
374
+ </button>
375
+ </form>
376
+ <span className={item.completed ? 'line-through text-muted-foreground' : ''}>
377
+ {item.content}
378
+ </span>
379
+ </div>
380
+ <form action={\`/api/items/\${item.id}/delete\`} method="POST">
381
+ <button className="text-muted-foreground hover:text-red-500 transition-colors">
382
+ <TrashIcon />
383
+ </button>
384
+ </form>
385
+ </div>
386
+ ))
387
+ ) : (
388
+ <p className="text-muted-foreground text-center py-8">No tasks yet.</p>
389
+ )}
390
+ </div>
391
+ </div>
392
+ </div>
393
+ </div>
394
+ );
395
+ }
396
+
397
+ function TrashIcon() {
398
+ return (
399
+ <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
400
+ <path d="M3 6h18M19 6v14a2 2 0 01-2 2H7a2 2 0 01-2-2V6m3 0V4a2 2 0 012-2h4a2 2 0 012 2v2" />
401
+ </svg>
402
+ );
403
+ }
404
+ `,
405
+ // API Routes
406
+ 'routes/api/items/index.ts': `import { db } from '@/lib/db';
407
+ import { items } from '@/schema';
408
+ // import { getSession } from '@/lib/auth';
409
+
410
+ export async function POST(req: Request) {
411
+ // const session = await getSession(req);
412
+ // if (!session) return new Response('Unauthorized', { status: 401 });
413
+
414
+ const formData = await req.formData();
415
+ const content = formData.get('content') as string;
416
+ const userId = 'demo-user-id'; // session.user.id
417
+
418
+ if (!content) return new Response('Content required', { status: 400 });
419
+
420
+ await db.insert(items).values({
421
+ id: crypto.randomUUID(),
422
+ userId,
423
+ content,
424
+ });
425
+
426
+ // Redirect back to dashboard to refresh
427
+ return new Response(null, { status: 302, headers: { Location: '/dashboard' } });
428
+ }
429
+ `,
430
+ 'routes/api/items/[id]/toggle.ts': `import { db } from '@/lib/db';
431
+ import { items } from '@/schema';
432
+ import { eq } from 'drizzle-orm';
433
+
434
+ export async function POST(req: Request, { params }: { params: { id: string } }) {
435
+ // In real app, check user ID match
436
+ const item = await db.select().from(items).where(eq(items.id, params.id)).get();
437
+
438
+ if (item) {
439
+ await db.update(items)
440
+ .set({ completed: !item.completed })
441
+ .where(eq(items.id, params.id));
442
+ }
443
+
444
+ return new Response(null, { status: 302, headers: { Location: '/dashboard' } });
445
+ }
446
+ `,
447
+ 'routes/api/items/[id]/delete.ts': `import { db } from '@/lib/db';
448
+ import { items } from '@/schema';
449
+ import { eq } from 'drizzle-orm';
450
+
451
+ export async function POST(req: Request, { params }: { params: { id: string } }) {
452
+ await db.delete(items).where(eq(items.id, params.id));
453
+ return new Response(null, { status: 302, headers: { Location: '/dashboard' } });
454
+ }
455
+ `,
456
+ // ========================================================================
457
+ // Components
458
+ // ========================================================================
459
+ 'app/components/ui/Button.tsx': `import React from 'react';
460
+ import { cn } from '@/lib/utils'; // Keep utility usage, fallback implementation below if not tailwind
461
+
462
+ interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
463
+ variant?: 'primary' | 'secondary' | 'outline' | 'ghost';
464
+ size?: 'sm' | 'md' | 'lg';
465
+ href?: string;
466
+ }
467
+
468
+ export function Button({
469
+ className,
470
+ variant = 'primary',
471
+ size = 'md',
472
+ href,
473
+ children,
474
+ ...props
475
+ }: ButtonProps) {
476
+ const baseStyles = ${isTailwind
477
+ ? "'inline-flex items-center justify-center font-medium rounded-lg transition-colors focus:ring-2 focus:ring-offset-2 disabled:opacity-50 disabled:pointer-events-none'"
478
+ : "'btn'"};
479
+
480
+ const variants = {
481
+ primary: ${isTailwind ? "'bg-primary text-black hover:bg-primary/90 focus:ring-primary'" : "'btn-primary'"},
482
+ secondary: ${isTailwind ? "'bg-secondary text-secondary-foreground hover:bg-secondary/80'" : "'btn-secondary'"},
483
+ outline: ${isTailwind ? "'border border-input hover:bg-accent hover:text-accent-foreground'" : "'btn-outline'"},
484
+ ghost: ${isTailwind ? "'hover:bg-accent hover:text-accent-foreground'" : "'btn-ghost'"},
485
+ };
486
+
487
+ const sizes = {
488
+ sm: ${isTailwind ? "'h-9 px-3 text-sm'" : "'btn-sm'"},
489
+ md: ${isTailwind ? "'h-10 px-4 py-2'" : "'btn-md'"},
490
+ lg: ${isTailwind ? "'h-11 px-8 text-lg'" : "'btn-lg'"},
491
+ };
492
+
493
+ const classes = cn(
494
+ baseStyles,
495
+ variants[variant],
496
+ sizes[size],
497
+ className
498
+ );
499
+
500
+ if (href) {
501
+ return <a href={href} className={classes}>{children}</a>;
502
+ }
503
+
504
+ return (
505
+ <button className={classes} {...props}>
506
+ {children}
507
+ </button>
508
+ );
509
+ }
510
+ `,
511
+ 'app/components/layout/Navbar.tsx': `import React from 'react';
512
+ import { Zap } from 'lucide-react';
513
+
514
+ export function Navbar() {
515
+ return (
516
+ <nav className="${isTailwind ? 'border-b border-border bg-background' : 'navbar'}">
517
+ <div className="${isTailwind ? 'container mx-auto px-4 h-16 flex items-center justify-between' : 'navbar-container'}">
518
+ <a href="/" className="${isTailwind ? 'flex items-center gap-2 font-bold text-xl' : 'navbar-brand'}">
519
+ <Zap className="text-primary" />
520
+ <span>FlexiStack</span>
521
+ </a>
522
+ <div className="${isTailwind ? 'flex items-center gap-6' : 'navbar-links'}">
523
+ <a href="/login" className="${isTailwind ? 'text-sm font-medium hover:text-primary transition-colors' : 'nav-link'}">Login</a>
524
+ <a href="/register" className="${isTailwind ? 'text-sm font-medium hover:text-primary transition-colors' : 'nav-link'}">Register</a>
525
+ </div>
526
+ </div>
527
+ </nav>
528
+ );
529
+ }
530
+ `,
531
+ 'app/components/layout/Footer.tsx': `import React from 'react';
532
+
533
+ export function Footer() {
534
+ return (
535
+ <footer className="${isTailwind ? 'border-t border-border py-8 text-center text-sm text-muted-foreground' : 'footer'}">
536
+ <p>© {new Date().getFullYear()} FlexiStack. Built with FlexiReact v4.</p>
537
+ </footer>
538
+ );
539
+ }
540
+ `,
541
+ // ========================================================================
542
+ // Styles & Utils
543
+ // ========================================================================
544
+ 'app/styles/globals.css': isTailwind ? `@import "tailwindcss";
545
+
546
+ @theme {
547
+ --color-background: #0a0a0a;
548
+ --color-foreground: #ffffff;
549
+ --color-primary: #00FF9C;
550
+ --color-primary-foreground: #000000;
551
+ --color-secondary: #27272a;
552
+ --color-secondary-foreground: #ffffff;
553
+ --color-muted: #27272a;
554
+ --color-muted-foreground: #a1a1aa;
555
+ --color-accent: #27272a;
556
+ --color-accent-foreground: #ffffff;
557
+ --color-border: #27272a;
558
+ --color-input: #27272a;
559
+ --color-card: #18181b;
560
+ }
561
+
562
+ body {
563
+ font-family: system-ui, -apple-system, sans-serif;
564
+ background-color: var(--color-background);
565
+ color: var(--color-foreground);
566
+ }
567
+ ` : `/* Modern CSS Variables */
568
+ :root {
569
+ --bg-color: #0a0a0a;
570
+ --text-color: #ffffff;
571
+ --primary-color: #00FF9C;
572
+ --border-color: #333;
573
+ }
574
+
575
+ body {
576
+ background: var(--bg-color);
577
+ color: var(--text-color);
578
+ margin: 0;
579
+ font-family: system-ui, sans-serif;
580
+ }
581
+
582
+ .container { max-width: 1200px; margin: 0 auto; padding: 0 20px; }
583
+ .btn { display: inline-flex; padding: 10px 20px; border-radius: 6px; font-weight: 600; text-decoration: none; cursor: pointer; border: none; }
584
+ .btn-primary { background: var(--primary-color); color: #000; }
585
+ .btn-outline { border: 1px solid var(--border-color); color: white; background: transparent; }
586
+ .home-page { text-align: center; padding: 80px 20px; }
587
+ .page-title { font-size: 4rem; line-height: 1.1; margin-bottom: 20px; }
588
+ .highlight { color: var(--primary-color); }
589
+ .features-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 20px; margin-top: 60px; }
590
+ .feature-card { padding: 20px; border: 1px solid var(--border-color); border-radius: 10px; background: #111; }
591
+ .navbar { border-bottom: 1px solid var(--border-color); padding: 15px 0; }
592
+ .navbar-container { display: flex; justify-content: space-between; align-items: center; max-width: 1200px; margin: 0 auto; padding: 0 20px; }
593
+ .navbar-brand { display: flex; align-items: center; gap: 10px; font-weight: bold; font-size: 1.2rem; color: white; text-decoration: none; }
594
+ .nav-link { color: #888; text-decoration: none; font-weight: 500; }
595
+ .nav-link:hover { color: var(--primary-color); }
596
+ `,
597
+ 'lib/utils.ts': `import { clsx, type ClassValue } from 'clsx';
598
+ import { twMerge } from 'tailwind-merge';
599
+
600
+ export function cn(...inputs: ClassValue[]) {
601
+ return twMerge(clsx(inputs));
602
+ }
603
+ `,
604
+ };
605
+ }
606
+ //# sourceMappingURL=fullstack.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fullstack.js","sourceRoot":"","sources":["../../src/templates/fullstack.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,3 @@
1
- /**
2
- * Template definitions for create-flexireact
3
- */
4
1
  export interface Template {
5
2
  name: string;
6
3
  description: string;
@@ -8,5 +5,8 @@ export interface Template {
8
5
  }
9
6
  export declare const TEMPLATES: Record<string, Template>;
10
7
  export type TemplateFiles = Record<string, string>;
11
- export declare function getTemplateFiles(templateKey: string, projectName: string): TemplateFiles;
8
+ export interface TemplateOptions {
9
+ styling?: 'tailwind' | 'css';
10
+ }
11
+ export declare function getTemplateFiles(templateKey: string, projectName: string, options?: TemplateOptions): TemplateFiles;
12
12
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/templates/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,eAAO,MAAM,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAgB9C,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAEnD,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,aAAa,CASxF"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/templates/index.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,eAAO,MAAM,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAqB9C,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAEnD,MAAM,WAAW,eAAe;IAC9B,OAAO,CAAC,EAAE,UAAU,GAAG,KAAK,CAAC;CAC9B;AAED,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,GAAE,eAAoB,GAAG,aAAa,CAWvH"}