create-frootkit 1.1.4 → 1.2.1

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 (109) hide show
  1. package/README.md +50 -16
  2. package/dist/addons/database.d.ts +3 -2
  3. package/dist/addons/database.d.ts.map +1 -1
  4. package/dist/addons/database.js +472 -13
  5. package/dist/addons/database.js.map +1 -1
  6. package/dist/index.js +93 -18
  7. package/dist/index.js.map +1 -1
  8. package/dist/scaffold.d.ts +1 -0
  9. package/dist/scaffold.d.ts.map +1 -1
  10. package/dist/scaffold.js +3 -3
  11. package/dist/scaffold.js.map +1 -1
  12. package/dist/template.d.ts +4 -5
  13. package/dist/template.d.ts.map +1 -1
  14. package/dist/template.js +6 -404
  15. package/dist/template.js.map +1 -1
  16. package/dist/templates/auth.d.ts +3 -0
  17. package/dist/templates/auth.d.ts.map +1 -0
  18. package/dist/templates/auth.js +487 -0
  19. package/dist/templates/auth.js.map +1 -0
  20. package/dist/templates/blog.d.ts +3 -0
  21. package/dist/templates/blog.d.ts.map +1 -0
  22. package/dist/templates/blog.js +369 -0
  23. package/dist/templates/blog.js.map +1 -0
  24. package/dist/templates/common.d.ts +5 -0
  25. package/dist/templates/common.d.ts.map +1 -0
  26. package/dist/templates/common.js +116 -0
  27. package/dist/templates/common.js.map +1 -0
  28. package/dist/templates/ecommerce.d.ts +3 -0
  29. package/dist/templates/ecommerce.d.ts.map +1 -0
  30. package/dist/templates/ecommerce.js +474 -0
  31. package/dist/templates/ecommerce.js.map +1 -0
  32. package/dist/templates/empty.d.ts +3 -0
  33. package/dist/templates/empty.d.ts.map +1 -0
  34. package/dist/templates/empty.js +85 -0
  35. package/dist/templates/empty.js.map +1 -0
  36. package/dist/templates/index.d.ts +23 -0
  37. package/dist/templates/index.d.ts.map +1 -0
  38. package/dist/templates/index.js +100 -0
  39. package/dist/templates/index.js.map +1 -0
  40. package/dist/templates/starter.d.ts +3 -0
  41. package/dist/templates/starter.d.ts.map +1 -0
  42. package/dist/templates/starter.js +308 -0
  43. package/dist/templates/starter.js.map +1 -0
  44. package/dist/templates/types.d.ts +13 -0
  45. package/dist/templates/types.d.ts.map +1 -0
  46. package/dist/templates/types.js +5 -0
  47. package/dist/templates/types.js.map +1 -0
  48. package/package.json +2 -1
  49. package/templates/auth/README.md +11 -0
  50. package/templates/auth/package.json +24 -0
  51. package/templates/auth/src/app/api/auth/route.ts +148 -0
  52. package/templates/auth/src/app/dashboard/layout.tsx +34 -0
  53. package/templates/auth/src/app/dashboard/page.tsx +72 -0
  54. package/templates/auth/src/app/layout.tsx +31 -0
  55. package/templates/auth/src/app/login/page.tsx +18 -0
  56. package/templates/auth/src/app/page.tsx +60 -0
  57. package/templates/auth/src/app/signup/page.tsx +18 -0
  58. package/templates/auth/src/components/AuthForm.tsx +77 -0
  59. package/templates/auth/src/components/DashboardNav.tsx +51 -0
  60. package/templates/auth/src/components/MetricCard.tsx +26 -0
  61. package/templates/auth/src/components/Navbar.tsx +29 -0
  62. package/templates/auth/src/lib/auth.ts +145 -0
  63. package/templates/auth/src/styles.css +19 -0
  64. package/templates/auth/tsconfig.json +13 -0
  65. package/templates/blog/README.md +11 -0
  66. package/templates/blog/package.json +24 -0
  67. package/templates/blog/src/app/api/posts/route.ts +36 -0
  68. package/templates/blog/src/app/blog/[slug]/page.tsx +74 -0
  69. package/templates/blog/src/app/layout.tsx +31 -0
  70. package/templates/blog/src/app/page.tsx +44 -0
  71. package/templates/blog/src/components/Footer.tsx +16 -0
  72. package/templates/blog/src/components/Navbar.tsx +31 -0
  73. package/templates/blog/src/components/Newsletter.tsx +32 -0
  74. package/templates/blog/src/components/PostCard.tsx +47 -0
  75. package/templates/blog/src/data/posts.ts +75 -0
  76. package/templates/blog/src/styles.css +19 -0
  77. package/templates/blog/tsconfig.json +13 -0
  78. package/templates/ecommerce/README.md +11 -0
  79. package/templates/ecommerce/package.json +24 -0
  80. package/templates/ecommerce/src/app/api/checkout/route.ts +19 -0
  81. package/templates/ecommerce/src/app/api/products/route.ts +28 -0
  82. package/templates/ecommerce/src/app/cart/page.tsx +22 -0
  83. package/templates/ecommerce/src/app/layout.tsx +31 -0
  84. package/templates/ecommerce/src/app/page.tsx +59 -0
  85. package/templates/ecommerce/src/app/products/[id]/page.tsx +88 -0
  86. package/templates/ecommerce/src/components/CartDrawer.tsx +64 -0
  87. package/templates/ecommerce/src/components/Footer.tsx +16 -0
  88. package/templates/ecommerce/src/components/Navbar.tsx +32 -0
  89. package/templates/ecommerce/src/components/ProductCard.tsx +52 -0
  90. package/templates/ecommerce/src/data/products.ts +87 -0
  91. package/templates/ecommerce/src/styles.css +19 -0
  92. package/templates/ecommerce/tsconfig.json +13 -0
  93. package/templates/empty/README.md +10 -0
  94. package/templates/empty/package.json +24 -0
  95. package/templates/empty/src/app/layout.tsx +29 -0
  96. package/templates/empty/src/app/page.tsx +38 -0
  97. package/templates/empty/src/styles.css +19 -0
  98. package/templates/empty/tsconfig.json +13 -0
  99. package/templates/starter/README.md +22 -0
  100. package/templates/starter/package.json +24 -0
  101. package/templates/starter/src/app/api/health/route.ts +23 -0
  102. package/templates/starter/src/app/layout.tsx +31 -0
  103. package/templates/starter/src/app/page.tsx +122 -0
  104. package/templates/starter/src/components/FeatureCard.tsx +25 -0
  105. package/templates/starter/src/components/Footer.tsx +16 -0
  106. package/templates/starter/src/components/Header.tsx +45 -0
  107. package/templates/starter/src/components/TerminalPreview.tsx +56 -0
  108. package/templates/starter/src/styles.css +19 -0
  109. package/templates/starter/tsconfig.json +13 -0
@@ -0,0 +1,369 @@
1
+ import { getBaseFiles } from './common.js';
2
+ export const blogTemplate = {
3
+ id: 'blog',
4
+ name: 'Blog & Content',
5
+ description: 'Fast, responsive blog with dynamic [slug] routes, post cards, and search API',
6
+ generate: (projectName) => {
7
+ const files = getBaseFiles(projectName);
8
+ files['src/types/blog.ts'] = `export interface Post {
9
+ slug: string;
10
+ title: string;
11
+ summary: string;
12
+ date: string;
13
+ readTime: string;
14
+ author: {
15
+ name: string;
16
+ role: string;
17
+ avatar: string;
18
+ };
19
+ tags: string[];
20
+ content: string[];
21
+ }
22
+ `;
23
+ files['src/data/posts.ts'] = `import type { Post } from '../types/blog.js';
24
+
25
+ export const POSTS: Post[] = [
26
+ {
27
+ slug: 'welcome-to-frootkit',
28
+ title: 'Introducing FrootKit: High-Performance Next.js Alternative',
29
+ summary: 'Why we combined Preact SSR, native Tailwind CSS v4, and the Froot runtime for maximum developer velocity and sub-millisecond page loads.',
30
+ date: '2026-10-31',
31
+ readTime: '3 min read',
32
+ author: {
33
+ name: 'OrbitNorth Team',
34
+ role: 'Core Engineering',
35
+ avatar: 'https://images.unsplash.com/photo-1534528741775-53994a69daeb?w=100&auto=format&fit=crop&q=80',
36
+ },
37
+ tags: ['Architecture', 'Performance', 'Preact'],
38
+ content: [
39
+ 'Modern web frameworks often carry extensive runtime baggage. FrootKit is built from first principles to provide the familiar ergonomics of Next.js App Router without the multi-megabyte bundle sizes.',
40
+ 'By utilizing Preact SSR on the server, FrootKit renders component trees directly into optimized HTML streams in under 1ms.',
41
+ 'With native Tailwind CSS v4 support, styles compile instantly using CSS-first @theme rules with zero configuration or complex build steps.',
42
+ ],
43
+ },
44
+ {
45
+ slug: 'nested-layouts-guide',
46
+ title: 'Mastering Nested Layouts and Route Scoping in FrootKit',
47
+ summary: 'How to structure hierarchical layouts, preserve client state across transitions, and isolate layout boundaries.',
48
+ date: '2026-10-28',
49
+ readTime: '4 min read',
50
+ author: {
51
+ name: 'Sarah Chen',
52
+ role: 'Frontend Architect',
53
+ avatar: 'https://images.unsplash.com/photo-1494790108377-be9c29b29330?w=100&auto=format&fit=crop&q=80',
54
+ },
55
+ tags: ['Routing', 'Layouts', 'Guide'],
56
+ content: [
57
+ 'In FrootKit, layouts compose naturally from the filesystem. A root layout.tsx wraps the entire application shell, while nested layouts wrap specific subsections.',
58
+ 'Route groups like (marketing) and (dashboard) allow you to organize routes cleanly without affecting the public URL paths.',
59
+ ],
60
+ },
61
+ {
62
+ slug: 'zero-config-api-routes',
63
+ title: 'Building High-Throughput API Routes on Top of Froot',
64
+ summary: 'Next.js-style route.ts handlers delivering Web Standard Request and Response processing with zero middleware overhead.',
65
+ date: '2026-10-25',
66
+ readTime: '5 min read',
67
+ author: {
68
+ name: 'Alex Rivera',
69
+ role: 'Backend Systems',
70
+ avatar: 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=100&auto=format&fit=crop&q=80',
71
+ },
72
+ tags: ['API', 'Backend', 'TypeScript'],
73
+ content: [
74
+ 'FrootKit bridges fullstack UI rendering and high-performance backend routing seamlessly. Any route.ts file in src/app/api automatically mounts onto Froot with zero extra configuration.',
75
+ 'Export HTTP verbs like GET, POST, PUT, and DELETE to handle API traffic with web standard Fetch API semantics.',
76
+ ],
77
+ },
78
+ ];
79
+ `;
80
+ files['src/components/Navbar.tsx'] = `export function Navbar() {
81
+ return (
82
+ <header class="border-b border-slate-800/80 bg-slate-950/60 backdrop-blur-md sticky top-0 z-50">
83
+ <div class="max-w-5xl mx-auto px-6 h-16 flex items-center justify-between">
84
+ <a href="/" class="flex items-center gap-2.5 font-bold text-white text-lg tracking-tight hover:opacity-90">
85
+ <span class="w-7 h-7 rounded-lg bg-emerald-500/10 border border-emerald-500/25 flex items-center justify-center text-emerald-400 font-extrabold text-sm">
86
+ ▲
87
+ </span>
88
+ <span>FrootKit<span class="text-emerald-400">Blog</span></span>
89
+ </a>
90
+
91
+ <nav class="flex items-center gap-6 text-sm font-medium">
92
+ <a href="/" class="text-slate-300 hover:text-white transition-colors">
93
+ Articles
94
+ </a>
95
+ <a href="/api/posts" class="text-slate-400 hover:text-emerald-400 font-mono text-xs px-2 py-1 rounded bg-slate-900 border border-slate-800">
96
+ /api/posts
97
+ </a>
98
+ <a
99
+ href="https://github.com/orbitnorth/frootkit"
100
+ target="_blank"
101
+ rel="noreferrer"
102
+ class="text-slate-300 hover:text-white transition-colors"
103
+ >
104
+ GitHub
105
+ </a>
106
+ </nav>
107
+ </div>
108
+ </header>
109
+ );
110
+ }
111
+ `;
112
+ files['src/components/Footer.tsx'] = `export function Footer() {
113
+ return (
114
+ <footer class="border-t border-slate-800/80 mt-20 py-10 bg-slate-950/40 text-center text-xs text-slate-500">
115
+ <div class="max-w-5xl mx-auto px-6 flex flex-col sm:flex-row items-center justify-between gap-4">
116
+ <div>
117
+ Published with <span class="text-slate-300 font-semibold">FrootKit</span> — Sub-millisecond Preact SSR.
118
+ </div>
119
+ <div class="flex items-center gap-5">
120
+ <a href="https://frootjs.org" target="_blank" rel="noreferrer" class="hover:text-slate-300 transition-colors">Documentation</a>
121
+ <a href="https://github.com/orbitnorth/frootkit" target="_blank" rel="noreferrer" class="hover:text-slate-300 transition-colors">GitHub</a>
122
+ </div>
123
+ </div>
124
+ </footer>
125
+ );
126
+ }
127
+ `;
128
+ files['src/components/PostCard.tsx'] = `import type { Post } from '../types/blog.js';
129
+
130
+ export function PostCard({ post }: { post: Post }) {
131
+ return (
132
+ <article class="p-6 rounded-2xl border border-slate-800/80 bg-slate-900/30 hover:border-emerald-500/30 transition-all hover:-translate-y-1 group flex flex-col justify-between">
133
+ <div>
134
+ <div class="flex items-center gap-2 mb-3">
135
+ {post.tags.map((tag) => (
136
+ <span key={tag} class="text-[11px] font-mono px-2 py-0.5 rounded-full bg-emerald-500/10 text-emerald-400 border border-emerald-500/20">
137
+ {tag}
138
+ </span>
139
+ ))}
140
+ <span class="text-xs text-slate-500 ml-auto font-mono">{post.readTime}</span>
141
+ </div>
142
+
143
+ <h2 class="text-xl font-bold text-white mb-2 group-hover:text-emerald-300 transition-colors leading-snug">
144
+ <a href={\`/blog/\${post.slug}\`}>{post.title}</a>
145
+ </h2>
146
+
147
+ <p class="text-sm text-slate-400 line-clamp-3 mb-6 leading-relaxed">
148
+ {post.summary}
149
+ </p>
150
+ </div>
151
+
152
+ <div class="flex items-center justify-between pt-4 border-t border-slate-800/60 text-xs">
153
+ <div class="flex items-center gap-2.5">
154
+ <img src={post.author.avatar} alt={post.author.name} class="w-6 h-6 rounded-full object-cover" />
155
+ <span class="font-medium text-slate-300">{post.author.name}</span>
156
+ </div>
157
+ <time class="text-slate-500 font-mono">{post.date}</time>
158
+ </div>
159
+ </article>
160
+ );
161
+ }
162
+ `;
163
+ files['src/app/layout.tsx'] = `import type { ComponentChildren } from 'preact';
164
+ import { Navbar } from '../components/Navbar.js';
165
+ import { Footer } from '../components/Footer.js';
166
+
167
+ export interface RootLayoutProps {
168
+ children: ComponentChildren;
169
+ metadata?: {
170
+ title?: string;
171
+ description?: string;
172
+ };
173
+ }
174
+
175
+ export default function RootLayout({ children, metadata }: RootLayoutProps) {
176
+ const title = metadata?.title || 'FrootKit Engineering Blog';
177
+ const description = metadata?.description || 'Articles on Preact SSR, web performance, and modern fullstack architecture.';
178
+
179
+ return (
180
+ <html lang="en" class="dark scroll-smooth">
181
+ <head>
182
+ <meta charSet="UTF-8" />
183
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
184
+ <title>{title}</title>
185
+ <meta name="description" content={description} />
186
+ <link rel="stylesheet" href="/styles.css" />
187
+ </head>
188
+ <body class="bg-[#030712] text-slate-100 min-h-screen flex flex-col justify-between antialiased selection:bg-emerald-500/20 selection:text-emerald-300">
189
+ <Navbar />
190
+ <div class="flex-1">{children}</div>
191
+ <Footer />
192
+ </body>
193
+ </html>
194
+ );
195
+ }
196
+ `;
197
+ files['src/app/page.tsx'] = `import { POSTS } from '../data/posts.js';
198
+ import { PostCard } from '../components/PostCard.js';
199
+
200
+ export const metadata = {
201
+ title: 'Blog & Engineering Notes — FrootKit',
202
+ description: 'Deep dives on high performance Preact SSR, Next.js App Router patterns, and Tailwind v4.',
203
+ };
204
+
205
+ export default function BlogHomePage() {
206
+ const [featured, ...recent] = POSTS;
207
+
208
+ return (
209
+ <main class="max-w-5xl mx-auto px-6 py-12 sm:py-16">
210
+ {/* Blog Hero */}
211
+ <div class="text-center max-w-2xl mx-auto mb-16">
212
+ <div class="inline-flex items-center gap-2 px-3 py-1 rounded-full bg-emerald-500/10 border border-emerald-500/20 text-xs font-semibold text-emerald-400 mb-4">
213
+ FrootKit Content Engine
214
+ </div>
215
+ <h1 class="text-4xl sm:text-5xl font-extrabold text-white tracking-tight mb-4">
216
+ Engineering & Ideas
217
+ </h1>
218
+ <p class="text-slate-400 text-base sm:text-lg">
219
+ Insights on ultra-fast SSR, nested layouts, and building modern web apps.
220
+ </p>
221
+ </div>
222
+
223
+ {/* Featured Post */}
224
+ {featured && (
225
+ <section class="mb-14">
226
+ <div class="p-8 rounded-3xl border border-slate-800 bg-gradient-to-br from-slate-900/60 to-emerald-950/20 hover:border-emerald-500/40 transition-all group">
227
+ <div class="flex items-center gap-2.5 mb-4">
228
+ <span class="text-xs font-bold uppercase tracking-wider text-emerald-400 bg-emerald-500/10 px-2.5 py-0.5 rounded-full border border-emerald-500/25">
229
+ Featured
230
+ </span>
231
+ <span class="text-xs text-slate-500 font-mono">{featured.date} &bull; {featured.readTime}</span>
232
+ </div>
233
+ <h2 class="text-2xl sm:text-3xl font-extrabold text-white mb-3 group-hover:text-emerald-300 transition-colors leading-tight">
234
+ <a href={\`/blog/\${featured.slug}\`}>{featured.title}</a>
235
+ </h2>
236
+ <p class="text-slate-300 text-base leading-relaxed mb-6 max-w-3xl">
237
+ {featured.summary}
238
+ </p>
239
+ <div class="flex items-center justify-between">
240
+ <div class="flex items-center gap-3">
241
+ <img src={featured.author.avatar} alt={featured.author.name} class="w-8 h-8 rounded-full object-cover" />
242
+ <div>
243
+ <div class="text-sm font-semibold text-white">{featured.author.name}</div>
244
+ <div class="text-xs text-slate-500">{featured.author.role}</div>
245
+ </div>
246
+ </div>
247
+ <a href={\`/blog/\${featured.slug}\`} class="text-sm font-bold text-emerald-400 hover:text-emerald-300 flex items-center gap-1">
248
+ Read Article &rarr;
249
+ </a>
250
+ </div>
251
+ </div>
252
+ </section>
253
+ )}
254
+
255
+ {/* Recent Posts Grid */}
256
+ <section>
257
+ <h3 class="text-xl font-bold text-white mb-6">Recent Articles</h3>
258
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
259
+ {recent.map((post) => (
260
+ <PostCard key={post.slug} post={post} />
261
+ ))}
262
+ </div>
263
+ </section>
264
+ </main>
265
+ );
266
+ }
267
+ `;
268
+ files['src/app/blog/[slug]/page.tsx'] = `import { POSTS } from '../../../data/posts.js';
269
+
270
+ export async function generateStaticParams() {
271
+ return POSTS.map((p) => ({ slug: p.slug }));
272
+ }
273
+
274
+ export async function generateMetadata({ params }: { params: { slug: string } }) {
275
+ const post = POSTS.find((p) => p.slug === params.slug);
276
+ return {
277
+ title: post ? \`\${post.title} — FrootKit Blog\` : 'Post Not Found',
278
+ description: post?.summary || '',
279
+ };
280
+ }
281
+
282
+ export default function BlogPostPage({ params }: { params: { slug: string } }) {
283
+ const post = POSTS.find((p) => p.slug === params.slug);
284
+
285
+ if (!post) {
286
+ return (
287
+ <main class="max-w-3xl mx-auto px-6 py-20 text-center">
288
+ <h1 class="text-3xl font-bold text-white mb-4">Post Not Found</h1>
289
+ <p class="text-slate-400 mb-6">The article you were looking for does not exist.</p>
290
+ <a href="/" class="text-emerald-400 font-bold hover:underline">&larr; Back to Articles</a>
291
+ </main>
292
+ );
293
+ }
294
+
295
+ return (
296
+ <article class="max-w-3xl mx-auto px-6 py-12 sm:py-16">
297
+ <a href="/" class="inline-flex items-center gap-1.5 text-xs font-semibold text-emerald-400 hover:text-emerald-300 mb-8 transition-colors">
298
+ &larr; Back to all articles
299
+ </a>
300
+
301
+ <div class="flex flex-wrap items-center gap-2 mb-4">
302
+ {post.tags.map((tag) => (
303
+ <span key={tag} class="text-xs font-mono px-2.5 py-0.5 rounded-full bg-emerald-500/10 text-emerald-400 border border-emerald-500/20">
304
+ {tag}
305
+ </span>
306
+ ))}
307
+ <span class="text-xs text-slate-500 ml-auto font-mono">{post.readTime}</span>
308
+ </div>
309
+
310
+ <h1 class="text-3xl sm:text-5xl font-extrabold text-white tracking-tight mb-6 leading-tight">
311
+ {post.title}
312
+ </h1>
313
+
314
+ <div class="flex items-center gap-3 pb-8 mb-8 border-b border-slate-800">
315
+ <img src={post.author.avatar} alt={post.author.name} class="w-10 h-10 rounded-full object-cover" />
316
+ <div>
317
+ <div class="text-sm font-semibold text-white">{post.author.name}</div>
318
+ <div class="text-xs text-slate-400">{post.author.role} &bull; <time>{post.date}</time></div>
319
+ </div>
320
+ </div>
321
+
322
+ <div class="space-y-6 text-slate-300 text-base sm:text-lg leading-relaxed">
323
+ {post.content.map((p, idx) => (
324
+ <p key={idx}>{p}</p>
325
+ ))}
326
+ </div>
327
+ </article>
328
+ );
329
+ }
330
+ `;
331
+ files['src/app/api/posts/route.ts'] = `import { POSTS } from '../../../data/posts.js';
332
+
333
+ export async function GET(request: Request) {
334
+ const url = new URL(request.url);
335
+ const tag = url.searchParams.get('tag');
336
+ const query = url.searchParams.get('q')?.toLowerCase();
337
+
338
+ let filtered = [...POSTS];
339
+
340
+ if (tag) {
341
+ filtered = filtered.filter((p) => p.tags.some((t) => t.toLowerCase() === tag.toLowerCase()));
342
+ }
343
+
344
+ if (query) {
345
+ filtered = filtered.filter(
346
+ (p) =>
347
+ p.title.toLowerCase().includes(query) ||
348
+ p.summary.toLowerCase().includes(query)
349
+ );
350
+ }
351
+
352
+ return Response.json({
353
+ total: filtered.length,
354
+ posts: filtered.map((p) => ({
355
+ slug: p.slug,
356
+ title: p.title,
357
+ summary: p.summary,
358
+ date: p.date,
359
+ readTime: p.readTime,
360
+ tags: p.tags,
361
+ author: p.author,
362
+ })),
363
+ });
364
+ }
365
+ `;
366
+ return files;
367
+ },
368
+ };
369
+ //# sourceMappingURL=blog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blog.js","sourceRoot":"","sources":["../../src/templates/blog.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG3C,MAAM,CAAC,MAAM,YAAY,GAAuB;IAC9C,EAAE,EAAE,MAAM;IACV,IAAI,EAAE,gBAAgB;IACtB,WAAW,EAAE,8EAA8E;IAC3F,QAAQ,EAAE,CAAC,WAAmB,EAAE,EAAE;QAChC,MAAM,KAAK,GAAG,YAAY,CAAC,WAAW,CAAC,CAAC;QAExC,KAAK,CAAC,mBAAmB,CAAC,GAAG;;;;;;;;;;;;;;CAchC,CAAC;QAEE,KAAK,CAAC,mBAAmB,CAAC,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwDhC,CAAC;QAEE,KAAK,CAAC,2BAA2B,CAAC,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+BxC,CAAC;QAEE,KAAK,CAAC,2BAA2B,CAAC,GAAG;;;;;;;;;;;;;;;CAexC,CAAC;QAEE,KAAK,CAAC,6BAA6B,CAAC,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkC1C,CAAC;QAEE,KAAK,CAAC,oBAAoB,CAAC,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiCjC,CAAC;QAEE,KAAK,CAAC,kBAAkB,CAAC,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsE/B,CAAC;QAEE,KAAK,CAAC,8BAA8B,CAAC,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8D3C,CAAC;QAEE,KAAK,CAAC,4BAA4B,CAAC,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkCzC,CAAC;QAEE,OAAO,KAAK,CAAC;IACf,CAAC;CACF,CAAC"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Common Base Files for All FrootKit Templates
3
+ */
4
+ export declare function getBaseFiles(projectName: string, extraScripts?: Record<string, string>): Record<string, string>;
5
+ //# sourceMappingURL=common.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../../src/templates/common.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,wBAAgB,YAAY,CAC1B,WAAW,EAAE,MAAM,EACnB,YAAY,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,GACxC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAwHxB"}
@@ -0,0 +1,116 @@
1
+ /**
2
+ * Common Base Files for All FrootKit Templates
3
+ */
4
+ export function getBaseFiles(projectName, extraScripts = {}) {
5
+ return {
6
+ 'package.json': JSON.stringify({
7
+ name: projectName,
8
+ version: '1.0.0',
9
+ type: 'module',
10
+ scripts: {
11
+ dev: 'frootkit dev',
12
+ build: 'frootkit build',
13
+ start: 'frootkit start',
14
+ ...extraScripts,
15
+ },
16
+ dependencies: {
17
+ frootkit: 'npm:froot-kit@^1.3.1',
18
+ 'froot-kit': '^1.3.1',
19
+ frootjs: '^1.0.6',
20
+ preact: '^11.1.0',
21
+ 'preact-render-to-string': '^6.8.2',
22
+ },
23
+ devDependencies: {
24
+ '@tailwindcss/cli': '^4.0.0',
25
+ tailwindcss: '^4.0.0',
26
+ '@types/node': '^22.10.0',
27
+ tsx: '^4.19.2',
28
+ typescript: '^5.8.0',
29
+ },
30
+ }, null, 2) + '\n',
31
+ 'tsconfig.json': `{
32
+ "compilerOptions": {
33
+ "target": "ES2024",
34
+ "module": "NodeNext",
35
+ "moduleResolution": "NodeNext",
36
+ "jsx": "react-jsx",
37
+ "jsxImportSource": "preact",
38
+ "strict": true,
39
+ "skipLibCheck": true,
40
+ "noEmit": true
41
+ },
42
+ "include": ["src/**/*"]
43
+ }
44
+ `,
45
+ '.gitignore': `# Dependencies
46
+ node_modules/
47
+ .pnpm-store/
48
+
49
+ # FrootKit build output
50
+ .froot/
51
+ dist/
52
+ .cache/
53
+
54
+ # SQLite databases
55
+ *.db
56
+ *.db-journal
57
+
58
+ # Environment
59
+ .env
60
+ .env.local
61
+
62
+ # OS and IDE files
63
+ .DS_Store
64
+ Thumbs.db
65
+ .vscode/
66
+ .idea/
67
+ *.log
68
+ `,
69
+ 'src/styles.css': `@import "tailwindcss";
70
+
71
+ @theme {
72
+ --color-brand-50: #ecfdf5;
73
+ --color-brand-100: #d1fae5;
74
+ --color-brand-200: #a7f3d0;
75
+ --color-brand-300: #6ee7b7;
76
+ --color-brand-400: #34d399;
77
+ --color-brand-500: #10b981;
78
+ --color-brand-600: #059669;
79
+ --color-brand-700: #047857;
80
+ --color-brand-800: #065f46;
81
+ --color-brand-900: #064e3b;
82
+ --color-brand-950: #022c22;
83
+ }
84
+
85
+ :root {
86
+ color-scheme: dark;
87
+ }
88
+
89
+ body {
90
+ margin: 0;
91
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
92
+ background-color: #030712;
93
+ color: #f8fafc;
94
+ }
95
+ `,
96
+ 'README.md': `# ${projectName}
97
+
98
+ A modern, high-performance web application built with **FrootKit** (Next.js Alternative with Preact SSR & Tailwind CSS v4).
99
+
100
+ ## Getting Started
101
+
102
+ \`\`\`bash
103
+ # Start development server
104
+ pnpm dev
105
+ # or npm run dev / bun run dev
106
+
107
+ # Export production static site
108
+ pnpm build
109
+
110
+ # Run production server
111
+ pnpm start
112
+ \`\`\`
113
+ `,
114
+ };
115
+ }
116
+ //# sourceMappingURL=common.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"common.js","sourceRoot":"","sources":["../../src/templates/common.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,UAAU,YAAY,CAC1B,WAAmB,EACnB,eAAuC,EAAE;IAEzC,OAAO;QACL,cAAc,EACZ,IAAI,CAAC,SAAS,CACZ;YACE,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,OAAO;YAChB,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE;gBACP,GAAG,EAAE,cAAc;gBACnB,KAAK,EAAE,gBAAgB;gBACvB,KAAK,EAAE,gBAAgB;gBACvB,GAAG,YAAY;aAChB;YACD,YAAY,EAAE;gBACZ,QAAQ,EAAE,sBAAsB;gBAChC,WAAW,EAAE,QAAQ;gBACrB,OAAO,EAAE,QAAQ;gBACjB,MAAM,EAAE,SAAS;gBACjB,yBAAyB,EAAE,QAAQ;aACpC;YACD,eAAe,EAAE;gBACf,kBAAkB,EAAE,QAAQ;gBAC5B,WAAW,EAAE,QAAQ;gBACrB,aAAa,EAAE,UAAU;gBACzB,GAAG,EAAE,SAAS;gBACd,UAAU,EAAE,QAAQ;aACrB;SACF,EACD,IAAI,EACJ,CAAC,CACF,GAAG,IAAI;QAEV,eAAe,EAAE;;;;;;;;;;;;;CAapB;QAEG,YAAY,EAAE;;;;;;;;;;;;;;;;;;;;;;;CAuBjB;QAEG,gBAAgB,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;CA0BrB;QAEG,WAAW,EAAE,KAAK,WAAW;;;;;;;;;;;;;;;;;CAiBhC;KACE,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { TemplateDefinition } from './types.js';
2
+ export declare const ecommerceTemplate: TemplateDefinition;
3
+ //# sourceMappingURL=ecommerce.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ecommerce.d.ts","sourceRoot":"","sources":["../../src/templates/ecommerce.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAErD,eAAO,MAAM,iBAAiB,EAAE,kBAme/B,CAAC"}