@emberkit/cli 0.5.1 → 0.6.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.
- package/dist/commands/create.js +7 -6
- package/dist/templates/action.js +12 -0
- package/dist/templates/api/api.js +280 -0
- package/dist/templates/apiRoute.js +20 -0
- package/dist/templates/blog/blog.js +358 -0
- package/dist/templates/component.js +14 -0
- package/dist/templates/config.js +13 -0
- package/dist/templates/context.js +21 -0
- package/dist/templates/dashboard/dashboard.js +406 -0
- package/dist/templates/entry.js +15 -0
- package/dist/templates/errorBoundary.js +17 -0
- package/dist/templates/form.js +59 -0
- package/dist/templates/index.js +0 -260
- package/dist/templates/layout.js +16 -0
- package/dist/templates/layoutRoutes.js +9 -0
- package/dist/templates/loader.js +10 -0
- package/dist/templates/minimal/minimal.js +89 -0
- package/dist/templates/projects/starter.js +286 -0
- package/dist/templates/projects/with-ui.js +445 -0
- package/dist/templates/projects.js +419 -191
- package/dist/templates/route.js +12 -0
- package/dist/templates/saas/saas.js +539 -0
- package/dist/templates/signal.js +25 -0
- package/dist/utils/filesystem.js +10 -12
- package/dist/utils/generator.js +30 -2
- package/package.json +1 -1
|
@@ -100,14 +100,34 @@ if (root) {
|
|
|
100
100
|
--font-sans: 'Inter', system-ui, sans-serif;
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
+
@keyframes float {
|
|
104
|
+
0%, 100% { transform: translateY(0px); }
|
|
105
|
+
50% { transform: translateY(-20px); }
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
@keyframes fade-in-up {
|
|
109
|
+
from { opacity: 0; transform: translateY(20px); }
|
|
110
|
+
to { opacity: 1; transform: translateY(0); }
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
@keyframes pulse-glow {
|
|
114
|
+
0%, 100% { opacity: 0.4; transform: scale(1); }
|
|
115
|
+
50% { opacity: 0.6; transform: scale(1.05); }
|
|
116
|
+
}
|
|
117
|
+
|
|
103
118
|
body {
|
|
104
|
-
@apply bg-
|
|
119
|
+
@apply bg-[#0b0f19] text-slate-200 font-sans min-h-screen;
|
|
105
120
|
}
|
|
106
121
|
|
|
107
122
|
a {
|
|
108
123
|
@apply text-inherit no-underline transition-colors;
|
|
109
|
-
}
|
|
110
|
-
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
.animate-float { animation: float 6s ease-in-out infinite; }
|
|
127
|
+
.animate-fade-in-up { animation: fade-in-up 0.6s ease-out forwards; }
|
|
128
|
+
.animate-pulse-glow { animation: pulse-glow 4s ease-in-out infinite; }`,
|
|
129
|
+
"src/routes/_layout.tsx":
|
|
130
|
+
} `import type { RouteComponent } from '@emberkit/core';
|
|
111
131
|
import { Head } from '@emberkit/core';
|
|
112
132
|
|
|
113
133
|
const Layout: RouteComponent = ({ children }) => {
|
|
@@ -117,26 +137,32 @@ const Layout: RouteComponent = ({ children }) => {
|
|
|
117
137
|
<title>{{name}}</title>
|
|
118
138
|
<meta name="description" content="Built with EmberKit" />
|
|
119
139
|
</Head>
|
|
120
|
-
<div className="
|
|
121
|
-
|
|
140
|
+
<div className="relative min-h-screen flex flex-col">
|
|
141
|
+
{/* Ambient background */}
|
|
142
|
+
<div className="pointer-events-none fixed inset-0 overflow-hidden">
|
|
143
|
+
<div className="absolute -top-40 -right-40 w-96 h-96 rounded-full bg-ember-500/10 blur-[120px] animate-pulse-glow" />
|
|
144
|
+
<div className="absolute -bottom-40 -left-40 w-96 h-96 rounded-full bg-amber-500/5 blur-[120px] animate-pulse-glow" style={{ animationDelay: '2s' }} />
|
|
145
|
+
</div>
|
|
146
|
+
|
|
147
|
+
<header className="relative z-50 border-b border-slate-800/50 bg-[#0b0f19]/80 backdrop-blur-xl sticky top-0">
|
|
122
148
|
<div className="max-w-6xl mx-auto px-6 py-4 flex items-center justify-between">
|
|
123
149
|
<a href="/" className="flex items-center gap-2 group">
|
|
124
|
-
<span className="text-2xl">🔥</span>
|
|
150
|
+
<span className="text-2xl animate-float">🔥</span>
|
|
125
151
|
<span className="text-xl font-bold bg-gradient-to-r from-ember-400 to-ember-500 bg-clip-text text-transparent">
|
|
126
152
|
{{name}}
|
|
127
153
|
</span>
|
|
128
154
|
</a>
|
|
129
155
|
<nav className="flex items-center gap-6">
|
|
130
|
-
<a href="/" className="text-slate-400 hover:text-ember-500 font-medium">Home</a>
|
|
131
|
-
<a href="/about" className="text-slate-400 hover:text-ember-500 font-medium">About</a>
|
|
132
|
-
<a href="https://emberkit.dev/docs" target="_blank" className="text-slate-400 hover:text-ember-500 font-medium">
|
|
156
|
+
<a href="/" className="text-slate-400 hover:text-ember-500 font-medium transition-colors">Home</a>
|
|
157
|
+
<a href="/about" className="text-slate-400 hover:text-ember-500 font-medium transition-colors">About</a>
|
|
158
|
+
<a href="https://emberkit.dev/docs" target="_blank" className="text-slate-400 hover:text-ember-500 font-medium transition-colors">
|
|
133
159
|
Docs <span className="text-xs">↗</span>
|
|
134
160
|
</a>
|
|
135
161
|
</nav>
|
|
136
162
|
</div>
|
|
137
163
|
</header>
|
|
138
|
-
<main className="flex-1">{children}</main>
|
|
139
|
-
<footer className="border-t border-slate-800 py-8 text-center text-slate-500">
|
|
164
|
+
<main className="relative z-10 flex-1">{children}</main>
|
|
165
|
+
<footer className="relative z-10 border-t border-slate-800/50 py-8 text-center text-slate-500">
|
|
140
166
|
<p>Built with <a href="https://emberkit.dev" className="text-ember-500 hover:underline">EmberKit</a></p>
|
|
141
167
|
</footer>
|
|
142
168
|
</div>
|
|
@@ -144,63 +170,92 @@ const Layout: RouteComponent = ({ children }) => {
|
|
|
144
170
|
);
|
|
145
171
|
};
|
|
146
172
|
|
|
147
|
-
export default Layout
|
|
148
|
-
"src/routes/index.tsx": `import type { RouteComponent } from '@emberkit/core';
|
|
149
|
-
import { signal } from '@emberkit/core';
|
|
173
|
+
export default Layout;\`,
|
|
150
174
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
<
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
175
|
+
"src/routes/index.tsx": `;
|
|
176
|
+
import { signal } from '@emberkit/core';
|
|
177
|
+
const HomePage = () => {
|
|
178
|
+
const count = signal(0);
|
|
179
|
+
return className = "relative max-w-6xl mx-auto px-6 py-16 space-y-24" >
|
|
180
|
+
{ /* Hero Section */}
|
|
181
|
+
< section;
|
|
182
|
+
className = "relative text-center space-y-6 animate-fade-in-down" >
|
|
183
|
+
className;
|
|
184
|
+
"pointer-events-none absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 h-[400px] w-[400px] rounded-full bg-ember-500/10 blur-[120px] animate-pulse-glow" / >
|
|
185
|
+
className;
|
|
186
|
+
"relative z-10 text-5xl md:text-6xl font-extrabold tracking-tight" >
|
|
187
|
+
Welcome;
|
|
188
|
+
to < span;
|
|
189
|
+
className = "bg-gradient-to-r from-ember-400 via-ember-500 to-amber-500 bg-clip-text text-transparent" > {};
|
|
190
|
+
{
|
|
191
|
+
name;
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
/span>
|
|
195
|
+
< /h1>
|
|
196
|
+
< p;
|
|
197
|
+
className = "relative z-10 text-xl text-slate-400 max-w-2xl mx-auto" >
|
|
198
|
+
A;
|
|
199
|
+
minimalist;
|
|
200
|
+
TypeScript - first;
|
|
201
|
+
JSX;
|
|
202
|
+
framework;
|
|
203
|
+
built;
|
|
204
|
+
for (speed; and; simplicity.
|
|
205
|
+
)
|
|
206
|
+
Get;
|
|
207
|
+
started in seconds;
|
|
208
|
+
with (hot)
|
|
209
|
+
;
|
|
210
|
+
and;
|
|
211
|
+
zero - config;
|
|
212
|
+
routing.
|
|
213
|
+
< /p>
|
|
214
|
+
< div;
|
|
215
|
+
className = "relative z-10 flex gap-4 justify-center pt-4" >
|
|
216
|
+
href;
|
|
217
|
+
"/about";
|
|
218
|
+
className = "px-6 py-3 bg-ember-500 hover:bg-ember-600 text-white font-semibold rounded-lg transition-all hover:scale-105 shadow-lg shadow-ember-500/20" >
|
|
219
|
+
Learn;
|
|
220
|
+
More
|
|
221
|
+
< /a>
|
|
222
|
+
< a;
|
|
223
|
+
href = "https://emberkit.dev/docs";
|
|
224
|
+
target = "_blank";
|
|
225
|
+
className = "px-6 py-3 border border-slate-700 hover:border-ember-500 text-slate-300 hover:text-ember-500 font-semibold rounded-lg transition-all" >
|
|
226
|
+
Read;
|
|
227
|
+
Docs & ;
|
|
228
|
+
8594;
|
|
229
|
+
/a>
|
|
230
|
+
< /div>
|
|
231
|
+
< /section>;
|
|
232
|
+
{ /* Features Grid */ }
|
|
233
|
+
className;
|
|
234
|
+
"grid md:grid-cols-3 gap-6" >
|
|
235
|
+
{ [{ icon: '⚡', title: 'Lightning Fast', desc: 'Sub-10KB runtime with tree-shakeable architecture' },
|
|
236
|
+
{ icon: '🔯', title: 'TypeScript First', desc: 'Full type safety with intelligent autocomplete' },
|
|
237
|
+
{ icon: '🛖', title: 'File-Based Routing', desc: 'Routes automatically created from your file structure' },
|
|
238
|
+
]: .map((f, i) => key = { f, : .title }, className = "p-6 rounded-xl border border-slate-800 bg-slate-800/30 hover:border-ember-500/50 transition-all duration-300 hover:-translate-y-1 group animate-fade-in-up", style = {}, { animationDelay: } `\${i * 100}ms\` }}>
|
|
239
|
+
<div className="text-3xl mb-4 group-hover:scale-110 transition-transform">{f.icon}</div>
|
|
240
|
+
<h3 className="text-lg font-semibold mb-2">{f.title}</h3>
|
|
241
|
+
<p className="text-slate-400">{f.desc}</p>
|
|
242
|
+
</div>
|
|
243
|
+
))}
|
|
190
244
|
</section>
|
|
191
245
|
|
|
192
|
-
|
|
246
|
+
{/* Counter Demo */}
|
|
247
|
+
<section className="relative p-8 rounded-3xl bg-gradient-to-br from-slate-800/50 to-slate-900/50 border border-slate-700/50 text-center backdrop-blur-sm">
|
|
193
248
|
<h2 className="text-2xl font-bold mb-6">Interactive Counter Demo</h2>
|
|
194
249
|
<div className="flex items-center justify-center gap-6">
|
|
195
250
|
<button
|
|
196
|
-
className="w-12 h-12 rounded-lg bg-slate-800 border border-slate-700 hover:bg-ember-500 hover:border-ember-500 text-ember-500 hover:text-white text-xl transition-all"
|
|
251
|
+
className="w-12 h-12 rounded-lg bg-slate-800 border border-slate-700 hover:bg-ember-500 hover:border-ember-500 text-ember-500 hover:text-white text-xl transition-all hover:scale-110"
|
|
197
252
|
onClick={() => count.value--}
|
|
198
253
|
>
|
|
199
254
|
−
|
|
200
255
|
</button>
|
|
201
|
-
<span className="text-5xl font-bold tabular-nums min-w-[80px]">{count}</span>
|
|
256
|
+
<span className="text-5xl font-bold tabular-nums min-w-[80px] bg-clip-text text-transparent bg-gradient-to-b from-white to-slate-400">{count}</span>
|
|
202
257
|
<button
|
|
203
|
-
className="w-12 h-12 rounded-lg bg-slate-800 border border-slate-700 hover:bg-ember-500 hover:border-ember-500 text-ember-500 hover:text-white text-xl transition-all"
|
|
258
|
+
className="w-12 h-12 rounded-lg bg-slate-800 border border-slate-700 hover:bg-ember-500 hover:border-ember-500 text-ember-500 hover:text-white text-xl transition-all hover:scale-110"
|
|
204
259
|
onClick={() => count.value++}
|
|
205
260
|
>
|
|
206
261
|
+
|
|
@@ -219,44 +274,45 @@ const HomePage: RouteComponent = () => {
|
|
|
219
274
|
);
|
|
220
275
|
};
|
|
221
276
|
|
|
222
|
-
export default HomePage;`,
|
|
223
|
-
"src/routes/about.tsx": `import type { RouteComponent } from '@emberkit/core';
|
|
277
|
+
export default HomePage;`, "src/routes/about.tsx", `import type { RouteComponent } from '@emberkit/core';
|
|
224
278
|
import { Head } from '@emberkit/core';
|
|
225
279
|
|
|
226
280
|
const AboutPage: RouteComponent = () => {
|
|
227
281
|
return (
|
|
228
|
-
<div className="max-w-3xl mx-auto px-6 py-16">
|
|
282
|
+
<div className="max-w-3xl mx-auto px-6 py-16 space-y-12 animate-fade-in-up">
|
|
229
283
|
<Head>
|
|
230
284
|
<title>About - {{name}}</title>
|
|
231
285
|
</Head>
|
|
232
|
-
<
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
286
|
+
<div className="text-center">
|
|
287
|
+
<h1 className="text-4xl font-bold mb-6">About {{name}}</h1>
|
|
288
|
+
<p className="text-slate-400 text-lg leading-relaxed max-w-2xl mx-auto">
|
|
289
|
+
EmberKit is a minimalist TypeScript-first JSX framework built for speed and simplicity.
|
|
290
|
+
It combines the best of modern frontend development with a lightweight runtime.
|
|
291
|
+
</p>
|
|
292
|
+
</div>
|
|
293
|
+
<div className="grid sm:grid-cols-3 gap-4">
|
|
294
|
+
{[
|
|
295
|
+
{ label: 'SPA & SSR', desc: 'Works in both modes' },
|
|
296
|
+
{ label: 'Zero Config', desc: 'Sensible defaults' },
|
|
297
|
+
{ label: 'HMR', desc: 'Hot module replacement' },
|
|
298
|
+
].map((f) => (
|
|
299
|
+
<div key={f.label} className="p-4 rounded-xl bg-slate-800/30 border border-slate-800 hover:border-ember-500/50 transition-all hover:-translate-y-1 group">
|
|
300
|
+
<span className="text-ember-500 text-sm font-semibold">{f.label}</span>
|
|
301
|
+
<p className="text-slate-500 text-sm mt-1">{f.desc}</p>
|
|
302
|
+
</div>
|
|
303
|
+
))}
|
|
304
|
+
</div>
|
|
305
|
+
<div className="text-center">
|
|
306
|
+
<a href="/" className="inline-flex items-center gap-2 text-ember-500 hover:text-ember-400 font-medium transition-colors">
|
|
307
|
+
← Back to Home
|
|
308
|
+
</a>
|
|
250
309
|
</div>
|
|
251
|
-
<a href="/" className="inline-flex items-center gap-2 text-ember-500 hover:text-ember-400 font-medium">
|
|
252
|
-
← Back to Home
|
|
253
|
-
</a>
|
|
254
310
|
</div>
|
|
255
311
|
);
|
|
256
312
|
};
|
|
257
313
|
|
|
258
|
-
export default AboutPage
|
|
259
|
-
};
|
|
314
|
+
export default AboutPage;`)
|
|
315
|
+
};
|
|
260
316
|
export const withUiTemplate = {
|
|
261
317
|
"package.json": `{
|
|
262
318
|
"name": "{{name}}",
|
|
@@ -362,14 +418,40 @@ if (root) {
|
|
|
362
418
|
--font-family-sans: 'Inter', system-ui, sans-serif;
|
|
363
419
|
}
|
|
364
420
|
|
|
421
|
+
@keyframes float {
|
|
422
|
+
0%, 100% { transform: translateY(0px); }
|
|
423
|
+
50% { transform: translateY(-20px); }
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
@keyframes fade-in-up {
|
|
427
|
+
from { opacity: 0; transform: translateY(20px); }
|
|
428
|
+
to { opacity: 1; transform: translateY(0); }
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
@keyframes fade-in-down {
|
|
432
|
+
from { opacity: 0; transform: translateY(-20px); }
|
|
433
|
+
to { opacity: 1; transform: translateY(0); }
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
@keyframes pulse-glow {
|
|
437
|
+
0%, 100% { opacity: 0.4; transform: scale(1); }
|
|
438
|
+
50% { opacity: 0.6; transform: scale(1.05); }
|
|
439
|
+
}
|
|
440
|
+
|
|
365
441
|
body {
|
|
366
|
-
@apply bg-
|
|
442
|
+
@apply bg-[#0b0f19] text-slate-200 font-sans;
|
|
367
443
|
}
|
|
368
444
|
|
|
369
445
|
a {
|
|
370
446
|
@apply text-inherit no-underline;
|
|
371
|
-
}
|
|
372
|
-
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
.animate-float { animation: float 6s ease-in-out infinite; }
|
|
450
|
+
.animate-fade-in-up { animation: fade-in-up 0.6s ease-out forwards; }
|
|
451
|
+
.animate-fade-in-down { animation: fade-in-down 0.6s ease-out forwards; }
|
|
452
|
+
.animate-pulse-glow { animation: pulse-glow 4s ease-in-out infinite; }`,
|
|
453
|
+
"src/routes/_layout.tsx":
|
|
454
|
+
} `import type { RouteComponent } from '@emberkit/core';
|
|
373
455
|
import { Head } from '@emberkit/core';
|
|
374
456
|
import { DefaultLayout } from '@emberkit/ui';
|
|
375
457
|
|
|
@@ -380,157 +462,303 @@ const Layout: RouteComponent = ({ children }) => {
|
|
|
380
462
|
<title>{{name}}</title>
|
|
381
463
|
<meta name="description" content="Built with EmberKit UI" />
|
|
382
464
|
</Head>
|
|
383
|
-
<
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
465
|
+
<div className="relative min-h-screen">
|
|
466
|
+
<div className="pointer-events-none fixed inset-0 overflow-hidden">
|
|
467
|
+
<div className="absolute -top-40 -right-40 w-96 h-96 rounded-full bg-ember-500/10 blur-[120px] animate-pulse-glow" />
|
|
468
|
+
<div className="absolute -bottom-40 -left-40 w-96 h-96 rounded-full bg-amber-500/5 blur-[120px] animate-pulse-glow" style={{ animationDelay: '2s' }} />
|
|
469
|
+
</div>
|
|
470
|
+
<DefaultLayout
|
|
471
|
+
logo={
|
|
472
|
+
<span className="flex items-center gap-2">
|
|
473
|
+
<span className="text-2xl animate-float">🔥</span>
|
|
474
|
+
<span className="font-bold text-xl bg-gradient-to-r from-ember-400 to-ember-600 bg-clip-text text-transparent">{{name}}</span>
|
|
475
|
+
</span>
|
|
476
|
+
}
|
|
477
|
+
navItems={[
|
|
478
|
+
{ label: 'Home', href: '/' },
|
|
479
|
+
{ label: 'About', href: '/about' },
|
|
480
|
+
{ label: 'Docs', href: 'https://emberkit.dev/docs', external: true },
|
|
481
|
+
]}
|
|
482
|
+
>
|
|
483
|
+
{children}
|
|
484
|
+
</DefaultLayout>
|
|
485
|
+
</div>
|
|
393
486
|
</>
|
|
394
487
|
);
|
|
395
488
|
};
|
|
396
489
|
|
|
397
|
-
export default Layout
|
|
398
|
-
|
|
490
|
+
export default Layout;\`,
|
|
491
|
+
|
|
492
|
+
"src/routes/index.tsx": \`import type { RouteComponent } from '@emberkit/core';
|
|
399
493
|
import { Button, Card, Heading, Text, Badge, Input } from '@emberkit/ui';
|
|
400
494
|
import { signal } from '@emberkit/core';
|
|
401
495
|
|
|
402
496
|
const HomePage: RouteComponent = () => {
|
|
403
497
|
const email = signal('');
|
|
498
|
+
const activeTab = signal('buttons');
|
|
404
499
|
|
|
405
500
|
return (
|
|
406
|
-
<div className="space-y-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
501
|
+
<div className="relative space-y-24">
|
|
502
|
+
{/* Hero */}
|
|
503
|
+
<section className="relative text-center py-20">
|
|
504
|
+
<div className="pointer-events-none absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 h-[400px] w-[400px] rounded-full bg-ember-500/15 blur-[150px] animate-pulse-glow" />
|
|
505
|
+
|
|
506
|
+
<div className="relative z-10 animate-fade-in-down">
|
|
507
|
+
<Badge variant="primary" className="mb-6 inline-flex">
|
|
508
|
+
✨ Built with EmberKit UI
|
|
509
|
+
</Badge>
|
|
510
|
+
<Heading level="h1" size="4xl" weight="bold" className="mb-6">
|
|
511
|
+
Welcome to{' '}
|
|
512
|
+
<span className="bg-gradient-to-r from-ember-400 via-ember-500 to-amber-500 bg-clip-text text-transparent">
|
|
513
|
+
{{name}}
|
|
514
|
+
</span>
|
|
515
|
+
</Heading>
|
|
516
|
+
<Text size="xl" color="muted" className="max-w-2xl mx-auto mb-10">
|
|
517
|
+
A modern starter template with EmberKit UI components and Tailwind CSS.
|
|
518
|
+
Build beautiful interfaces with our pre-built component library.
|
|
519
|
+
</Text>
|
|
520
|
+
<div className="flex gap-4 justify-center">
|
|
521
|
+
<Button variant="primary" size="lg" className="shadow-lg shadow-ember-500/20 hover:shadow-ember-500/40 transition-shadow">
|
|
522
|
+
Get Started
|
|
523
|
+
</Button>
|
|
524
|
+
<Button variant="secondary" size="lg">
|
|
525
|
+
View Docs →
|
|
526
|
+
</Button>
|
|
527
|
+
</div>
|
|
528
|
+
</div>
|
|
529
|
+
</section>
|
|
530
|
+
|
|
531
|
+
{/* Features Grid */}
|
|
532
|
+
<section>
|
|
533
|
+
<Heading level="h2" size="2xl" weight="semibold" className="mb-2 text-center">
|
|
534
|
+
Why EmberKit?
|
|
410
535
|
</Heading>
|
|
411
|
-
<Text
|
|
412
|
-
|
|
413
|
-
Build beautiful interfaces with our pre-built component library.
|
|
536
|
+
<Text color="muted" className="text-center mb-10 max-w-lg mx-auto">
|
|
537
|
+
Everything you need to build fast, beautiful web applications.
|
|
414
538
|
</Text>
|
|
415
|
-
<div className="
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
539
|
+
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
|
540
|
+
{[
|
|
541
|
+
{ icon: '⚡', title: 'Lightning Fast', desc: 'Sub-10KB runtime with tree-shakeable architecture' },
|
|
542
|
+
{ icon: '🔯', title: 'TypeScript First', desc: 'Full type safety with intelligent autocomplete' },
|
|
543
|
+
{ icon: '🛖', title: 'File-Based Routing', desc: 'Routes automatically created from your file structure' },
|
|
544
|
+
].map((f, i) => (
|
|
545
|
+
<Card key={f.title} padding="lg" className="relative group hover:border-ember-500/50 transition-all duration-300 hover:-translate-y-1" style={{ animationDelay: \`\${i * 100}ms\` }}>
|
|
546
|
+
<div className="absolute inset-0 rounded-xl bg-gradient-to-br from-ember-500/5 to-transparent opacity-0 group-hover:opacity-100 transition-opacity" />
|
|
547
|
+
<div className="relative">
|
|
548
|
+
<div className="w-12 h-12 rounded-xl bg-ember-500/10 flex items-center justify-center text-2xl mb-4 group-hover:scale-110 transition-transform">
|
|
549
|
+
{f.icon}
|
|
550
|
+
</div>
|
|
551
|
+
<Heading level="h3" size="lg" weight="semibold" className="mb-2">
|
|
552
|
+
{f.title}
|
|
553
|
+
</Heading>
|
|
554
|
+
<Text color="muted">{f.desc}</Text>
|
|
555
|
+
</div>
|
|
556
|
+
</Card>
|
|
557
|
+
))}
|
|
422
558
|
</div>
|
|
423
559
|
</section>
|
|
424
560
|
|
|
561
|
+
{/* Component Showcase */}
|
|
425
562
|
<section>
|
|
426
|
-
<Heading level="h2" size="2xl" weight="semibold" className="mb-
|
|
563
|
+
<Heading level="h2" size="2xl" weight="semibold" className="mb-2 text-center">
|
|
427
564
|
UI Components
|
|
428
565
|
</Heading>
|
|
429
|
-
<
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
566
|
+
<Text color="muted" className="text-center mb-8">
|
|
567
|
+
Explore our pre-built component library.
|
|
568
|
+
</Text>
|
|
569
|
+
|
|
570
|
+
{/* Tabs */}
|
|
571
|
+
<div className="flex justify-center mb-8">
|
|
572
|
+
<div className="inline-flex p-1 rounded-lg bg-slate-800/50 border border-slate-700/50">
|
|
573
|
+
{[
|
|
574
|
+
{ id: 'buttons', label: 'Buttons' },
|
|
575
|
+
{ id: 'cards', label: 'Cards' },
|
|
576
|
+
{ id: 'forms', label: 'Forms' },
|
|
577
|
+
].map((tab) => (
|
|
578
|
+
<button
|
|
579
|
+
key={tab.id}
|
|
580
|
+
className={\`px-4 py-2 text-sm font-medium rounded-md transition-all \${activeTab.value === tab.id ? 'bg-ember-500 text-white shadow-md' : 'text-slate-400 hover:text-slate-200'}\`}
|
|
581
|
+
onClick={() => { activeTab.value = tab.id; }}
|
|
582
|
+
>
|
|
583
|
+
{tab.label}
|
|
584
|
+
</button>
|
|
585
|
+
))}
|
|
586
|
+
</div>
|
|
587
|
+
</div>
|
|
588
|
+
|
|
589
|
+
{/* Tab Content */}
|
|
590
|
+
{activeTab.value === 'buttons' && (
|
|
591
|
+
<Card padding="xl" className="max-w-2xl mx-auto">
|
|
592
|
+
<div className="text-center mb-6">
|
|
593
|
+
<Badge variant="primary" className="mb-2">Buttons</Badge>
|
|
594
|
+
<Heading level="h3" size="lg" weight="semibold">Button Variants</Heading>
|
|
595
|
+
</div>
|
|
596
|
+
<div className="flex flex-wrap gap-3 justify-center">
|
|
439
597
|
<Button variant="primary">Primary</Button>
|
|
440
598
|
<Button variant="secondary">Secondary</Button>
|
|
441
599
|
<Button variant="ghost">Ghost</Button>
|
|
600
|
+
<Button variant="primary" size="sm">Small</Button>
|
|
601
|
+
<Button variant="secondary" size="lg">Large</Button>
|
|
602
|
+
</div>
|
|
603
|
+
<div className="mt-6 pt-6 border-t border-slate-700/50">
|
|
604
|
+
<Heading level="h4" size="sm" weight="semibold" className="mb-3 text-slate-400">With Icons</Heading>
|
|
605
|
+
<div className="flex flex-wrap gap-3 justify-center">
|
|
606
|
+
<Button variant="primary">⚡ Get Started</Button>
|
|
607
|
+
<Button variant="secondary">Learn More →</Button>
|
|
608
|
+
<Button variant="ghost">❤ Like</Button>
|
|
609
|
+
</div>
|
|
442
610
|
</div>
|
|
443
611
|
</Card>
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
<Text
|
|
612
|
+
)}
|
|
613
|
+
|
|
614
|
+
{activeTab.value === 'cards' && (
|
|
615
|
+
<div className="grid md:grid-cols-2 gap-6 max-w-3xl mx-auto">
|
|
616
|
+
<Card padding="lg" className="hover:border-ember-500/50 transition-colors">
|
|
617
|
+
<Badge variant="success" className="mb-3">Analytics</Badge>
|
|
618
|
+
<Heading level="h3" size="lg" weight="semibold" className="mb-2">
|
|
619
|
+
Revenue Growth
|
|
620
|
+
</Heading>
|
|
621
|
+
<div className="text-3xl font-bold text-ember-400 mb-1">$45,231</div>
|
|
622
|
+
<Text color="muted" className="text-sm">+20.1% from last month</Text>
|
|
623
|
+
<div className="mt-4 h-2 rounded-full bg-slate-700 overflow-hidden">
|
|
624
|
+
<div className="h-full w-3/4 rounded-full bg-gradient-to-r from-ember-500 to-amber-500" />
|
|
625
|
+
</div>
|
|
455
626
|
</Card>
|
|
456
|
-
|
|
627
|
+
<Card padding="lg" className="hover:border-ember-500/50 transition-colors">
|
|
628
|
+
<Badge variant="info" className="mb-3">Users</Badge>
|
|
629
|
+
<Heading level="h3" size="lg" weight="semibold" className="mb-2">
|
|
630
|
+
Active Users
|
|
631
|
+
</Heading>
|
|
632
|
+
<div className="text-3xl font-bold text-blue-400 mb-1">2,338</div>
|
|
633
|
+
<Text color="muted" className="text-sm">+15.3% from last month</Text>
|
|
634
|
+
<div className="mt-4 h-2 rounded-full bg-slate-700 overflow-hidden">
|
|
635
|
+
<div className="h-full w-1/2 rounded-full bg-gradient-to-r from-blue-500 to-cyan-500" />
|
|
636
|
+
</div>
|
|
637
|
+
</Card>
|
|
638
|
+
</div>
|
|
639
|
+
)}
|
|
457
640
|
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
<
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
641
|
+
{activeTab.value === 'forms' && (
|
|
642
|
+
<Card padding="xl" className="max-w-md mx-auto">
|
|
643
|
+
<div className="text-center mb-6">
|
|
644
|
+
<Badge variant="info" className="mb-2">Forms</Badge>
|
|
645
|
+
<Heading level="h3" size="lg" weight="semibold">Newsletter Signup</Heading>
|
|
646
|
+
</div>
|
|
647
|
+
<div className="space-y-4">
|
|
648
|
+
<Input
|
|
649
|
+
label="Name"
|
|
650
|
+
placeholder="John Doe"
|
|
651
|
+
/>
|
|
652
|
+
<Input
|
|
653
|
+
label="Email"
|
|
654
|
+
type="email"
|
|
655
|
+
placeholder="you@example.com"
|
|
656
|
+
value={email.value}
|
|
657
|
+
onChange={(e) => { email.value = e.currentTarget.value; }}
|
|
658
|
+
/>
|
|
659
|
+
<Button variant="primary" className="w-full shadow-lg shadow-ember-500/20">
|
|
660
|
+
Subscribe ➤
|
|
661
|
+
</Button>
|
|
662
|
+
</div>
|
|
472
663
|
</Card>
|
|
473
|
-
|
|
664
|
+
)}
|
|
474
665
|
</section>
|
|
475
666
|
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
667
|
+
{/* CTA */}
|
|
668
|
+
<section className="relative py-20">
|
|
669
|
+
<div className="pointer-events-none absolute inset-0 flex items-center justify-center">
|
|
670
|
+
<div className="w-[500px] h-[200px] rounded-full bg-ember-500/10 blur-[100px]" />
|
|
671
|
+
</div>
|
|
672
|
+
<div className="relative z-10 text-center">
|
|
673
|
+
<Heading level="h2" size="2xl" weight="semibold" className="mb-4">
|
|
674
|
+
Ready to build something amazing?
|
|
675
|
+
</Heading>
|
|
676
|
+
<Text color="muted" className="max-w-xl mx-auto mb-8">
|
|
677
|
+
Start building your next project with EmberKit's powerful components and TypeScript-first API.
|
|
678
|
+
</Text>
|
|
679
|
+
<Button variant="primary" size="lg" className="shadow-lg shadow-ember-500/25 hover:shadow-ember-500/40 transition-shadow">
|
|
680
|
+
Create Project ➤
|
|
681
|
+
</Button>
|
|
682
|
+
</div>
|
|
486
683
|
</section>
|
|
487
684
|
</div>
|
|
488
685
|
);
|
|
489
686
|
};
|
|
490
687
|
|
|
491
|
-
export default HomePage
|
|
492
|
-
|
|
688
|
+
export default HomePage;\`,
|
|
689
|
+
|
|
690
|
+
"src/routes/about.tsx": \`import type { RouteComponent } from '@emberkit/core';
|
|
493
691
|
import { Head } from '@emberkit/core';
|
|
494
|
-
import { Heading, Text, Button } from '@emberkit/ui';
|
|
692
|
+
import { Heading, Text, Button, Card, Badge } from '@emberkit/ui';
|
|
495
693
|
|
|
496
694
|
const AboutPage: RouteComponent = () => {
|
|
497
695
|
return (
|
|
498
|
-
|
|
696
|
+
<>
|
|
499
697
|
<Head>
|
|
500
698
|
<title>About - {{name}}</title>
|
|
501
699
|
</Head>
|
|
502
|
-
<
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
<div className="space-y-4">
|
|
511
|
-
<div className="flex items-center gap-3 p-4 bg-slate-800 rounded-lg">
|
|
512
|
-
<span className="text-ember-500 text-2xl">✓</span>
|
|
513
|
-
<Text>TypeScript-first development</Text>
|
|
514
|
-
</div>
|
|
515
|
-
<div className="flex items-center gap-3 p-4 bg-slate-800 rounded-lg">
|
|
516
|
-
<span className="text-ember-500 text-2xl">✓</span>
|
|
517
|
-
<Text>Pre-built UI components</Text>
|
|
700
|
+
<div className="max-w-3xl mx-auto py-12 space-y-12">
|
|
701
|
+
{/* Header */}
|
|
702
|
+
<div className="text-center">
|
|
703
|
+
<Badge variant="primary" className="mb-4 inline-flex">About</Badge>
|
|
704
|
+
<Heading level="h1" size="3xl" weight="bold">
|
|
705
|
+
About{' '}
|
|
706
|
+
<span className="bg-gradient-to-r from-ember-400 to-ember-600 bg-clip-text text-transparent">{{name}}</span>
|
|
707
|
+
</Heading>
|
|
518
708
|
</div>
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
709
|
+
|
|
710
|
+
{/* Description */}
|
|
711
|
+
<Card padding="xl" className="border-ember-500/20">
|
|
712
|
+
<Text size="lg" color="muted" className="leading-relaxed">
|
|
713
|
+
This project was created with EmberKit and the UI component library.
|
|
714
|
+
It demonstrates how to build modern, beautiful interfaces with our
|
|
715
|
+
pre-built components and Tailwind CSS.
|
|
716
|
+
</Text>
|
|
717
|
+
</Card>
|
|
718
|
+
|
|
719
|
+
{/* Features */}
|
|
720
|
+
<div className="grid sm:grid-cols-2 gap-4">
|
|
721
|
+
{[
|
|
722
|
+
{ icon: '🔌', title: 'TypeScript-first', desc: 'Full type safety with intelligent autocomplete' },
|
|
723
|
+
{ icon: '🎨', title: 'UI Components', desc: 'Pre-built atoms, molecules, and organisms' },
|
|
724
|
+
{ icon: '🌈', title: 'Tailwind CSS', desc: 'Utility-first styling with custom theme' },
|
|
725
|
+
{ icon: '🛖', title: 'File Routing', desc: 'Automatic routes from your file structure' },
|
|
726
|
+
].map((f) => (
|
|
727
|
+
<Card key={f.title} padding="lg" className="hover:border-ember-500/50 transition-all hover:-translate-y-0.5">
|
|
728
|
+
<div className="text-2xl mb-3">{f.icon}</div>
|
|
729
|
+
<Heading level="h3" size="md" weight="semibold" className="mb-1">
|
|
730
|
+
{f.title}
|
|
731
|
+
</Heading>
|
|
732
|
+
<Text color="muted" size="sm">{f.desc}</Text>
|
|
733
|
+
</Card>
|
|
734
|
+
))}
|
|
522
735
|
</div>
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
736
|
+
|
|
737
|
+
{/* Tech Stack */}
|
|
738
|
+
<Card padding="xl">
|
|
739
|
+
<Heading level="h3" size="lg" weight="semibold" className="mb-4 text-center">
|
|
740
|
+
Tech Stack
|
|
741
|
+
</Heading>
|
|
742
|
+
<div className="flex flex-wrap gap-2 justify-center">
|
|
743
|
+
{['EmberKit', 'TypeScript', 'Tailwind CSS', 'Vite', 'JSX'].map((tech) => (
|
|
744
|
+
<Badge key={tech} variant="primary" className="px-3 py-1.5">
|
|
745
|
+
{tech}
|
|
746
|
+
</Badge>
|
|
747
|
+
))}
|
|
748
|
+
</div>
|
|
749
|
+
</Card>
|
|
750
|
+
|
|
751
|
+
{/* Back */}
|
|
752
|
+
<div className="text-center">
|
|
753
|
+
<Button variant="secondary">
|
|
754
|
+
← Back to Home
|
|
755
|
+
</Button>
|
|
526
756
|
</div>
|
|
527
757
|
</div>
|
|
528
|
-
|
|
529
|
-
<Button variant="secondary">← Back to Home</Button>
|
|
530
|
-
</div>
|
|
531
|
-
</div>
|
|
758
|
+
</>
|
|
532
759
|
);
|
|
533
760
|
};
|
|
534
761
|
|
|
535
|
-
export default AboutPage
|
|
762
|
+
export default AboutPage;\`,
|
|
536
763
|
};
|
|
764
|
+
;
|