create-solostack 1.2.1 → 1.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/generators/base.js +187 -174
package/package.json
CHANGED
package/src/generators/base.js
CHANGED
|
@@ -316,206 +316,219 @@ export default function RootLayout({
|
|
|
316
316
|
|
|
317
317
|
import { useState, useEffect } from 'react';
|
|
318
318
|
import Link from 'next/link';
|
|
319
|
-
import {
|
|
319
|
+
import {
|
|
320
|
+
CheckCircle2,
|
|
321
|
+
AlertCircle,
|
|
322
|
+
Terminal,
|
|
323
|
+
Database,
|
|
324
|
+
Shield,
|
|
325
|
+
CreditCard,
|
|
326
|
+
Mail,
|
|
327
|
+
Loader2,
|
|
328
|
+
ChevronRight,
|
|
329
|
+
ExternalLink,
|
|
330
|
+
Book
|
|
331
|
+
} from 'lucide-react';
|
|
320
332
|
|
|
321
333
|
export default function Home() {
|
|
322
|
-
const [
|
|
323
|
-
const [
|
|
324
|
-
mrr: 0,
|
|
325
|
-
users: 0,
|
|
326
|
-
shipped: 0
|
|
327
|
-
});
|
|
334
|
+
const [status, setStatus] = useState<any>(null);
|
|
335
|
+
const [loading, setLoading] = useState(true);
|
|
328
336
|
|
|
329
337
|
useEffect(() => {
|
|
330
|
-
|
|
338
|
+
fetch('/api/setup')
|
|
339
|
+
.then(res => res.json())
|
|
340
|
+
.then(data => {
|
|
341
|
+
setStatus(data);
|
|
342
|
+
setLoading(false);
|
|
343
|
+
})
|
|
344
|
+
.catch(() => setLoading(false));
|
|
331
345
|
}, []);
|
|
332
346
|
|
|
333
|
-
const incrementStats = () => {
|
|
334
|
-
setStats(prev => ({
|
|
335
|
-
mrr: prev.mrr + 100,
|
|
336
|
-
users: prev.users + 5,
|
|
337
|
-
shipped: prev.shipped + 1
|
|
338
|
-
}));
|
|
339
|
-
};
|
|
340
|
-
|
|
341
|
-
if (!mounted) return null;
|
|
342
|
-
|
|
343
347
|
return (
|
|
344
348
|
<div className="min-h-screen bg-zinc-950 text-zinc-50 font-sans selection:bg-indigo-500/30">
|
|
345
349
|
|
|
346
|
-
{/*
|
|
347
|
-
<
|
|
348
|
-
<div className="max-w-
|
|
349
|
-
<div className="
|
|
350
|
-
<div className="
|
|
351
|
-
|
|
352
|
-
<Rocket className="h-5 w-5 text-white" />
|
|
353
|
-
</div>
|
|
354
|
-
<span className="text-xl font-bold tracking-tight">${projectName}</span>
|
|
355
|
-
</div>
|
|
356
|
-
<div className="flex items-center gap-4">
|
|
357
|
-
{process.env.NODE_ENV === 'development' && (
|
|
358
|
-
<Link
|
|
359
|
-
href="/setup"
|
|
360
|
-
className="text-sm font-medium text-zinc-400 hover:text-white transition-colors flex items-center gap-2"
|
|
361
|
-
>
|
|
362
|
-
<CheckCircle2 className="h-4 w-4" />
|
|
363
|
-
Diagnostics
|
|
364
|
-
</Link>
|
|
365
|
-
)}
|
|
366
|
-
<Link
|
|
367
|
-
href="/login"
|
|
368
|
-
className="text-sm font-medium text-zinc-400 hover:text-white transition-colors"
|
|
369
|
-
>
|
|
370
|
-
Sign In
|
|
371
|
-
</Link>
|
|
372
|
-
<Link
|
|
373
|
-
href="/signup"
|
|
374
|
-
className="inline-flex items-center justify-center rounded-md bg-white px-4 py-2 text-sm font-medium text-zinc-950 shadow-sm hover:bg-zinc-200 transition-colors"
|
|
375
|
-
>
|
|
376
|
-
Get Started
|
|
377
|
-
</Link>
|
|
378
|
-
</div>
|
|
350
|
+
{/* Header */}
|
|
351
|
+
<header className="border-b border-zinc-900 bg-zinc-950/50 backdrop-blur-xl sticky top-0 z-10">
|
|
352
|
+
<div className="max-w-5xl mx-auto px-6 h-16 flex items-center justify-between">
|
|
353
|
+
<div className="font-bold text-lg tracking-tight flex items-center gap-2">
|
|
354
|
+
<div className="w-3 h-3 rounded-full bg-indigo-500 shadow-[0_0_10px_rgba(99,102,241,0.5)]" />
|
|
355
|
+
<span className="text-zinc-100">${projectName}</span>
|
|
379
356
|
</div>
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
357
|
+
<div className="flex items-center gap-4">
|
|
358
|
+
<span className="text-xs font-mono text-zinc-500 bg-zinc-900 px-2 py-1 rounded border border-zinc-800">
|
|
359
|
+
v0.1.0 (Dev Mode)
|
|
360
|
+
</span>
|
|
361
|
+
<a
|
|
362
|
+
href="https://github.com/danish296/create-solostack"
|
|
363
|
+
target="_blank"
|
|
364
|
+
rel="noreferrer"
|
|
365
|
+
className="text-zinc-400 hover:text-white transition-colors"
|
|
366
|
+
>
|
|
367
|
+
<ExternalLink className="w-4 h-4" />
|
|
368
|
+
</a>
|
|
390
369
|
</div>
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
370
|
+
</div>
|
|
371
|
+
</header>
|
|
372
|
+
|
|
373
|
+
<main className="max-w-5xl mx-auto px-6 py-12">
|
|
374
|
+
{/* Welcome Section */}
|
|
375
|
+
<div className="mb-12 border-b border-zinc-900 pb-12">
|
|
376
|
+
<h1 className="text-4xl font-bold tracking-tight mb-4 text-white">
|
|
377
|
+
Your Stack is Ready.
|
|
395
378
|
</h1>
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
379
|
+
<p className="text-zinc-400 text-lg max-w-2xl leading-relaxed">
|
|
380
|
+
Welcome to your new SaaS application. This page is your
|
|
381
|
+
<span className="text-zinc-200 font-medium"> local development hub</span>.
|
|
382
|
+
Check your integrations, review the tech stack, and start building.
|
|
399
383
|
</p>
|
|
400
|
-
|
|
401
|
-
<div className="
|
|
402
|
-
<
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
>
|
|
406
|
-
|
|
407
|
-
</Link>
|
|
408
|
-
<a
|
|
409
|
-
href="https://github.com/yourusername/create-solostack"
|
|
410
|
-
target="_blank"
|
|
411
|
-
rel="noopener noreferrer"
|
|
412
|
-
className="w-full sm:w-auto inline-flex items-center justify-center gap-2 rounded-lg border border-zinc-800 bg-zinc-900/50 px-8 py-3.5 text-sm font-medium text-zinc-300 hover:bg-zinc-800 hover:text-white transition-all backdrop-blur-sm"
|
|
413
|
-
>
|
|
414
|
-
Star on GitHub
|
|
415
|
-
</a>
|
|
384
|
+
|
|
385
|
+
<div className="mt-8 flex items-center gap-4">
|
|
386
|
+
<div className="flex items-center gap-2 text-sm text-zinc-500 bg-zinc-900/50 px-3 py-2 rounded-md border border-zinc-800 font-mono">
|
|
387
|
+
<Terminal className="w-4 h-4 text-indigo-400" />
|
|
388
|
+
<span>src/app/page.tsx</span>
|
|
389
|
+
</div>
|
|
390
|
+
<span className="text-zinc-600 text-sm">← Edit this file to build your landing page</span>
|
|
416
391
|
</div>
|
|
392
|
+
</div>
|
|
393
|
+
|
|
394
|
+
{/* System Status Grid */}
|
|
395
|
+
<div className="grid grid-cols-1 md:grid-cols-2 gap-6 mb-12">
|
|
396
|
+
<StatusCard
|
|
397
|
+
title="Database"
|
|
398
|
+
icon={<Database className="w-5 h-5 text-emerald-400" />}
|
|
399
|
+
status={status?.database?.connected}
|
|
400
|
+
loading={loading}
|
|
401
|
+
description="PostgreSQL + Prisma"
|
|
402
|
+
details={status?.database?.connected ? \`User count: \${status.database.userCount}\` : status?.database?.error || "Not connected"}
|
|
403
|
+
actionLabel="Open Studio"
|
|
404
|
+
actionCommand="npm run db:studio"
|
|
405
|
+
/>
|
|
406
|
+
<StatusCard
|
|
407
|
+
title="Authentication"
|
|
408
|
+
icon={<Shield className="w-5 h-5 text-blue-400" />}
|
|
409
|
+
status={status?.auth?.configured}
|
|
410
|
+
loading={loading}
|
|
411
|
+
description={status?.auth?.providers?.map((p: any) => p.name).join(', ') || "No providers"}
|
|
412
|
+
details={status?.auth?.configured ? "Ready to authenticate users" : "Missing secrets"}
|
|
413
|
+
actionLabel="Read Docs"
|
|
414
|
+
actionUrl="https://next-auth.js.org"
|
|
415
|
+
/>
|
|
416
|
+
<StatusCard
|
|
417
|
+
title="Payments"
|
|
418
|
+
icon={<CreditCard className="w-5 h-5 text-purple-400" />}
|
|
419
|
+
status={status?.stripe?.configured}
|
|
420
|
+
loading={loading}
|
|
421
|
+
description="Stripe"
|
|
422
|
+
details={status?.stripe?.configured ? "API Keys present" : "Missing API Keys"}
|
|
423
|
+
actionLabel="Dashboard"
|
|
424
|
+
actionUrl="https://dashboard.stripe.com/test/apikeys"
|
|
425
|
+
/>
|
|
426
|
+
<StatusCard
|
|
427
|
+
title="Email"
|
|
428
|
+
icon={<Mail className="w-5 h-5 text-pink-400" />}
|
|
429
|
+
status={status?.email?.configured}
|
|
430
|
+
loading={loading}
|
|
431
|
+
description="Resend"
|
|
432
|
+
details={status?.email?.configured ? "Ready to send" : "Missing API Key"}
|
|
433
|
+
actionLabel="Send Test"
|
|
434
|
+
actionUrl="/setup"
|
|
435
|
+
/>
|
|
436
|
+
</div>
|
|
417
437
|
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
<div className="p-4 rounded-lg bg-zinc-900/50 border border-zinc-800">
|
|
441
|
-
<div className="flex items-center gap-2 text-zinc-400 mb-2">
|
|
442
|
-
<Box className="h-4 w-4 text-purple-500" /> Shipped
|
|
443
|
-
</div>
|
|
444
|
-
<div className="text-3xl font-mono font-bold text-white">
|
|
445
|
-
{stats.shipped}
|
|
446
|
-
</div>
|
|
447
|
-
</div>
|
|
448
|
-
</div>
|
|
449
|
-
|
|
450
|
-
<div className="text-center">
|
|
451
|
-
<p className="text-zinc-500 mb-6 font-mono text-sm">
|
|
452
|
-
> CLICK_BELOW_TO_SIMULATE_GROWTH.exe
|
|
453
|
-
</p>
|
|
454
|
-
<button
|
|
455
|
-
onClick={incrementStats}
|
|
456
|
-
className="group relative inline-flex items-center justify-center rounded-full bg-zinc-100 px-8 py-4 font-bold text-zinc-950 transition-all hover:scale-105 active:scale-95 shadow-lg hover:shadow-indigo-500/20"
|
|
457
|
-
>
|
|
458
|
-
<Play className="mr-2 h-5 w-5 fill-zinc-950 transition-transform group-hover:translate-x-1" />
|
|
459
|
-
SHIP FEATURE
|
|
460
|
-
</button>
|
|
461
|
-
<p className="mt-4 text-xs text-zinc-600">
|
|
462
|
-
* Results may vary. Consistency is key.
|
|
463
|
-
</p>
|
|
464
|
-
</div>
|
|
465
|
-
</div>
|
|
466
|
-
</div>
|
|
438
|
+
{/* Resources Section */}
|
|
439
|
+
<div>
|
|
440
|
+
<h2 className="text-xl font-semibold mb-6 flex items-center gap-2">
|
|
441
|
+
<Book className="w-5 h-5 text-zinc-400" />
|
|
442
|
+
Documentation & Resources
|
|
443
|
+
</h2>
|
|
444
|
+
<div className="grid grid-cols-1 sm:grid-cols-3 gap-4">
|
|
445
|
+
<ResourceLink
|
|
446
|
+
href="https://nextjs.org/docs"
|
|
447
|
+
title="Next.js 15"
|
|
448
|
+
desc="App Router, Server Actions"
|
|
449
|
+
/>
|
|
450
|
+
<ResourceLink
|
|
451
|
+
href="https://ui.shadcn.com"
|
|
452
|
+
title="shadcn/ui"
|
|
453
|
+
desc="Component Library"
|
|
454
|
+
/>
|
|
455
|
+
<ResourceLink
|
|
456
|
+
href="https://www.prisma.io/docs"
|
|
457
|
+
title="Prisma"
|
|
458
|
+
desc="Database ORM"
|
|
459
|
+
/>
|
|
467
460
|
</div>
|
|
468
461
|
</div>
|
|
469
462
|
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
463
|
+
</main>
|
|
464
|
+
</div>
|
|
465
|
+
);
|
|
466
|
+
}
|
|
473
467
|
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
title="Authentication"
|
|
481
|
-
description="Secure user management with NextAuth or Supabase. Login, signup, and protected routes."
|
|
482
|
-
/>
|
|
483
|
-
<FeatureCard
|
|
484
|
-
icon={<Database className="h-6 w-6 text-emerald-400" />}
|
|
485
|
-
title="Database"
|
|
486
|
-
description="Type-safe data access with Prisma and PostgreSQL. Seeding scripts included."
|
|
487
|
-
/>
|
|
488
|
-
<FeatureCard
|
|
489
|
-
icon={<CreditCard className="h-6 w-6 text-purple-400" />}
|
|
490
|
-
title="Payments"
|
|
491
|
-
description="Stripe integration with checkout sessions, webhooks, and subscription management."
|
|
492
|
-
/>
|
|
493
|
-
<FeatureCard
|
|
494
|
-
icon={<Mail className="h-6 w-6 text-pink-400" />}
|
|
495
|
-
title="Emails"
|
|
496
|
-
description="Transactional emails with Resend and React Email. Beautiful templates out of the box."
|
|
497
|
-
/>
|
|
498
|
-
</div>
|
|
468
|
+
function StatusCard({ title, icon, status, loading, description, details, actionLabel, actionCommand, actionUrl }: any) {
|
|
469
|
+
return (
|
|
470
|
+
<div className="border border-zinc-800 bg-zinc-900/30 rounded-xl p-6 hover:bg-zinc-900/50 transition-colors">
|
|
471
|
+
<div className="flex justify-between items-start mb-4">
|
|
472
|
+
<div className="p-2 bg-zinc-950 rounded-lg border border-zinc-800">
|
|
473
|
+
{icon}
|
|
499
474
|
</div>
|
|
475
|
+
{loading ? (
|
|
476
|
+
<Loader2 className="w-5 h-5 animate-spin text-zinc-600" />
|
|
477
|
+
) : status ? (
|
|
478
|
+
<CheckCircle2 className="w-5 h-5 text-emerald-500" />
|
|
479
|
+
) : (
|
|
480
|
+
<AlertCircle className="w-5 h-5 text-amber-500" />
|
|
481
|
+
)}
|
|
482
|
+
</div>
|
|
483
|
+
|
|
484
|
+
<h3 className="text-lg font-medium text-white mb-1">{title}</h3>
|
|
485
|
+
<p className="text-sm font-medium text-zinc-300 mb-2">{description}</p>
|
|
486
|
+
|
|
487
|
+
<div className="min-h-[20px] mb-6">
|
|
488
|
+
<p className={\`text-xs \${status ? 'text-zinc-500' : 'text-amber-500/80'}\`}>
|
|
489
|
+
{details}
|
|
490
|
+
</p>
|
|
500
491
|
</div>
|
|
501
492
|
|
|
502
|
-
{
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
493
|
+
{actionCommand ? (
|
|
494
|
+
<div className="flex items-center justify-between pt-4 border-t border-zinc-800/50">
|
|
495
|
+
<code className="text-xs bg-black px-2 py-1 rounded text-zinc-400 font-mono">
|
|
496
|
+
{actionCommand}
|
|
497
|
+
</code>
|
|
498
|
+
</div>
|
|
499
|
+
) : actionUrl ? (
|
|
500
|
+
<div className="pt-4 border-t border-zinc-800/50">
|
|
501
|
+
{actionUrl.startsWith('http') ? (
|
|
502
|
+
<a href={actionUrl} target="_blank" rel="noreferrer" className="text-xs font-medium text-indigo-400 hover:text-indigo-300 flex items-center gap-1">
|
|
503
|
+
{actionLabel} <ExternalLink className="w-3 h-3" />
|
|
504
|
+
</a>
|
|
505
|
+
) : (
|
|
506
|
+
<Link href={actionUrl} className="text-xs font-medium text-indigo-400 hover:text-indigo-300 flex items-center gap-1">
|
|
507
|
+
{actionLabel} <ChevronRight className="w-3 h-3" />
|
|
508
|
+
</Link>
|
|
509
|
+
)}
|
|
514
510
|
</div>
|
|
515
|
-
|
|
511
|
+
) : null}
|
|
516
512
|
</div>
|
|
517
513
|
);
|
|
518
514
|
}
|
|
515
|
+
|
|
516
|
+
function ResourceLink({ href, title, desc }: any) {
|
|
517
|
+
return (
|
|
518
|
+
<a
|
|
519
|
+
href={href}
|
|
520
|
+
target="_blank"
|
|
521
|
+
rel="noreferrer"
|
|
522
|
+
className="group block p-4 rounded-lg border border-zinc-800 bg-zinc-900/20 hover:bg-zinc-800/50 transition-all"
|
|
523
|
+
>
|
|
524
|
+
<div className="flex items-center justify-between mb-1">
|
|
525
|
+
<span className="font-medium text-zinc-200 group-hover:text-white transition-colors">{title}</span>
|
|
526
|
+
<ExternalLink className="w-3 h-3 text-zinc-600 group-hover:text-zinc-400" />
|
|
527
|
+
</div>
|
|
528
|
+
<p className="text-xs text-zinc-500">{desc}</p>
|
|
529
|
+
</a>
|
|
530
|
+
);
|
|
531
|
+
}
|
|
519
532
|
`;
|
|
520
533
|
|
|
521
534
|
await writeFile(path.join(projectPath, 'src/app/page.tsx'), pageTsx);
|