create-cronus-app 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.
Files changed (56) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +173 -0
  3. package/dist/compose.d.ts +56 -0
  4. package/dist/compose.js +92 -0
  5. package/dist/index.d.ts +33 -0
  6. package/dist/index.js +255 -0
  7. package/dist/scaffold.d.ts +31 -0
  8. package/dist/scaffold.js +118 -0
  9. package/dist/utils.d.ts +121 -0
  10. package/dist/utils.js +285 -0
  11. package/dist/version.d.ts +3 -0
  12. package/dist/version.js +3 -0
  13. package/package.json +56 -0
  14. package/templates/dashboard/README.md +61 -0
  15. package/templates/dashboard/app/globals.css +16 -0
  16. package/templates/dashboard/app/layout.tsx +40 -0
  17. package/templates/dashboard/app/page.tsx +77 -0
  18. package/templates/dashboard/app/settings/page.tsx +21 -0
  19. package/templates/dashboard/components/dashboard-shell.tsx +120 -0
  20. package/templates/dashboard/components/orders-table.tsx +132 -0
  21. package/templates/dashboard/components/revenue-chart.tsx +50 -0
  22. package/templates/dashboard/components/settings-form.tsx +167 -0
  23. package/templates/dashboard/cronus-ui.json +17 -0
  24. package/templates/dashboard/gitignore +34 -0
  25. package/templates/dashboard/next.config.mjs +11 -0
  26. package/templates/dashboard/package.json +30 -0
  27. package/templates/dashboard/postcss.config.mjs +7 -0
  28. package/templates/dashboard/tsconfig.json +23 -0
  29. package/templates/default/README.md +46 -0
  30. package/templates/default/app/globals.css +16 -0
  31. package/templates/default/app/layout.tsx +39 -0
  32. package/templates/default/app/page.tsx +112 -0
  33. package/templates/default/cronus-ui.json +17 -0
  34. package/templates/default/gitignore +34 -0
  35. package/templates/default/next.config.mjs +11 -0
  36. package/templates/default/package.json +27 -0
  37. package/templates/default/postcss.config.mjs +7 -0
  38. package/templates/default/tsconfig.json +23 -0
  39. package/templates/marketing/README.md +65 -0
  40. package/templates/marketing/app/globals.css +16 -0
  41. package/templates/marketing/app/layout.tsx +39 -0
  42. package/templates/marketing/app/page.tsx +25 -0
  43. package/templates/marketing/components/faq.tsx +62 -0
  44. package/templates/marketing/components/feature-grid.tsx +67 -0
  45. package/templates/marketing/components/hero.tsx +61 -0
  46. package/templates/marketing/components/pricing.tsx +116 -0
  47. package/templates/marketing/components/site-footer.tsx +91 -0
  48. package/templates/marketing/components/site-header.tsx +47 -0
  49. package/templates/marketing/components/testimonials.tsx +91 -0
  50. package/templates/marketing/components/waitlist-cta.tsx +93 -0
  51. package/templates/marketing/cronus-ui.json +17 -0
  52. package/templates/marketing/gitignore +34 -0
  53. package/templates/marketing/next.config.mjs +11 -0
  54. package/templates/marketing/package.json +28 -0
  55. package/templates/marketing/postcss.config.mjs +7 -0
  56. package/templates/marketing/tsconfig.json +23 -0
@@ -0,0 +1,67 @@
1
+ import { Badge } from "@cronus-ui/ui/badge";
2
+ import { Card, CardDescription, CardHeader, CardTitle } from "@cronus-ui/ui/card";
3
+ import { BarChart3, Layers, Lock, Palette, Workflow, Zap } from "lucide-react";
4
+
5
+ const FEATURES = [
6
+ {
7
+ icon: Zap,
8
+ title: "Lightning fast",
9
+ description: "Optimized rendering and zero-runtime styling keep every interaction instant.",
10
+ },
11
+ {
12
+ icon: Palette,
13
+ title: "Themeable by design",
14
+ description: "Swap a palette and every surface, border, and gradient updates live.",
15
+ },
16
+ {
17
+ icon: Lock,
18
+ title: "Secure by default",
19
+ description: "SOC 2 compliant infrastructure with end-to-end encryption on every request.",
20
+ },
21
+ {
22
+ icon: Layers,
23
+ title: "Composable primitives",
24
+ description: "Build complex layouts from small, predictable, accessible building blocks.",
25
+ },
26
+ {
27
+ icon: BarChart3,
28
+ title: "Insightful analytics",
29
+ description: "Understand how people use your product with real-time usage dashboards.",
30
+ },
31
+ {
32
+ icon: Workflow,
33
+ title: "Automate anything",
34
+ description: "Connect your favorite tools and wire up workflows without writing glue code.",
35
+ },
36
+ ] as const;
37
+
38
+ /** Six capability cards with gradient icon chips. */
39
+ export function FeatureGrid() {
40
+ return (
41
+ <section id="features" className="scroll-mt-16 px-6 py-20">
42
+ <div className="mx-auto max-w-2xl text-center">
43
+ <Badge variant="secondary">Features</Badge>
44
+ <h2 className="mt-4 font-display text-4xl font-semibold tracking-tight text-fg">
45
+ Everything you need, nothing you don&apos;t
46
+ </h2>
47
+ <p className="mt-4 text-balance text-fg-secondary">
48
+ A thoughtfully crafted set of tools that scales from your first prototype to production.
49
+ </p>
50
+ </div>
51
+
52
+ <div className="mx-auto mt-14 grid max-w-5xl grid-cols-[repeat(auto-fit,minmax(min(100%,16rem),1fr))] gap-6">
53
+ {FEATURES.map((feature) => (
54
+ <Card key={feature.title} className="border-border">
55
+ <CardHeader>
56
+ <span className="grid size-11 place-items-center rounded-xl bg-gradient-primary text-primary-foreground shadow-glow">
57
+ <feature.icon aria-hidden="true" className="size-5" />
58
+ </span>
59
+ <CardTitle className="mt-4">{feature.title}</CardTitle>
60
+ <CardDescription>{feature.description}</CardDescription>
61
+ </CardHeader>
62
+ </Card>
63
+ ))}
64
+ </div>
65
+ </section>
66
+ );
67
+ }
@@ -0,0 +1,61 @@
1
+ import { Avatar, AvatarFallback } from "@cronus-ui/ui/avatar";
2
+ import { Badge } from "@cronus-ui/ui/badge";
3
+ import { Button } from "@cronus-ui/ui/button";
4
+ import { ArrowRight, Sparkles } from "lucide-react";
5
+
6
+ const FOUNDER_INITIALS = ["AK", "MR", "JD", "SL"] as const;
7
+
8
+ /** Centered hero: announcement badge, display headline, CTAs, social proof. */
9
+ export function Hero() {
10
+ return (
11
+ <section className="relative overflow-hidden px-6 py-24 sm:py-32">
12
+ <div
13
+ aria-hidden="true"
14
+ className="pointer-events-none absolute inset-x-0 -top-24 -z-10 h-80 bg-gradient-primary opacity-20 blur-3xl"
15
+ />
16
+ <div className="mx-auto flex max-w-3xl flex-col items-center text-center">
17
+ <Badge variant="primary" className="gap-1.5">
18
+ <Sparkles aria-hidden="true" className="size-3.5" />
19
+ Now in public beta
20
+ </Badge>
21
+
22
+ <h1 className="mt-6 text-balance font-display text-5xl font-semibold leading-[1.05] tracking-tight text-fg sm:text-6xl">
23
+ Ship products your team is{" "}
24
+ <span className="bg-gradient-primary bg-clip-text text-transparent">proud of</span>
25
+ </h1>
26
+
27
+ <p className="mt-6 max-w-xl text-balance text-lg text-fg-secondary">
28
+ A modern toolkit for building accessible, themeable interfaces — so you spend less time on
29
+ plumbing and more time on the product your customers love.
30
+ </p>
31
+
32
+ <div className="mt-9 flex flex-col items-center gap-3 sm:flex-row">
33
+ <Button variant="primary" size="lg" asChild>
34
+ <a href="#waitlist">
35
+ Join the waitlist
36
+ <ArrowRight aria-hidden="true" />
37
+ </a>
38
+ </Button>
39
+ <Button variant="outline" size="lg" asChild>
40
+ <a href="#features">See what's inside</a>
41
+ </Button>
42
+ </div>
43
+
44
+ <div className="mt-10 flex flex-col items-center gap-3 sm:flex-row sm:gap-4">
45
+ <div className="flex -space-x-2">
46
+ {FOUNDER_INITIALS.map((initials) => (
47
+ <Avatar key={initials} className="size-9 border-2 border-surface-base shadow-xs">
48
+ <AvatarFallback className="bg-surface-overlay text-xs text-fg-secondary">
49
+ {initials}
50
+ </AvatarFallback>
51
+ </Avatar>
52
+ ))}
53
+ </div>
54
+ <p className="text-sm text-fg-tertiary">
55
+ Loved by <span className="font-medium text-fg">9,000+</span> builders
56
+ </p>
57
+ </div>
58
+ </div>
59
+ </section>
60
+ );
61
+ }
@@ -0,0 +1,116 @@
1
+ import { Badge } from "@cronus-ui/ui/badge";
2
+ import { Button } from "@cronus-ui/ui/button";
3
+ import {
4
+ Card,
5
+ CardContent,
6
+ CardDescription,
7
+ CardFooter,
8
+ CardHeader,
9
+ CardTitle,
10
+ } from "@cronus-ui/ui/card";
11
+ import { Check, Sparkles } from "lucide-react";
12
+
13
+ const PRICING_TIERS = [
14
+ {
15
+ name: "Starter",
16
+ price: "$0",
17
+ cadence: "/ month",
18
+ description: "Everything you need to launch your first project.",
19
+ features: ["Up to 3 projects", "Community support", "1 GB storage", "Basic analytics"],
20
+ cta: "Get started",
21
+ featured: false,
22
+ },
23
+ {
24
+ name: "Pro",
25
+ price: "$29",
26
+ cadence: "/ month",
27
+ description: "For growing teams that need more power and polish.",
28
+ features: [
29
+ "Unlimited projects",
30
+ "Priority support",
31
+ "50 GB storage",
32
+ "Advanced analytics",
33
+ "Custom domains",
34
+ ],
35
+ cta: "Start free trial",
36
+ featured: true,
37
+ },
38
+ {
39
+ name: "Enterprise",
40
+ price: "Custom",
41
+ cadence: "",
42
+ description: "Dedicated infrastructure and support at scale.",
43
+ features: ["Everything in Pro", "SSO & SAML", "Dedicated success manager", "99.99% uptime SLA"],
44
+ cta: "Contact sales",
45
+ featured: false,
46
+ },
47
+ ] as const;
48
+
49
+ /** Three pricing tiers with a featured middle card. */
50
+ export function Pricing() {
51
+ return (
52
+ <section id="pricing" className="scroll-mt-16 px-6 py-20">
53
+ <div className="mx-auto max-w-2xl text-center">
54
+ <Badge variant="secondary">Pricing</Badge>
55
+ <h2 className="mt-4 font-display text-4xl font-semibold tracking-tight text-fg">
56
+ Simple, transparent pricing
57
+ </h2>
58
+ <p className="mt-4 text-balance text-fg-secondary">
59
+ Start for free and scale as you grow. No hidden fees, cancel anytime.
60
+ </p>
61
+ </div>
62
+
63
+ <div className="mx-auto mt-14 grid max-w-5xl grid-cols-[repeat(auto-fit,minmax(min(100%,16rem),1fr))] items-start gap-6">
64
+ {PRICING_TIERS.map((tier) => (
65
+ <Card
66
+ key={tier.name}
67
+ className={
68
+ tier.featured
69
+ ? "relative border-primary shadow-glow lg:-translate-y-3"
70
+ : "border-border"
71
+ }
72
+ >
73
+ {tier.featured ? (
74
+ <Badge
75
+ variant="primary"
76
+ className="absolute -top-3 left-1/2 -translate-x-1/2 gap-1.5"
77
+ >
78
+ <Sparkles aria-hidden="true" className="size-3.5" />
79
+ Most popular
80
+ </Badge>
81
+ ) : null}
82
+ <CardHeader>
83
+ <CardTitle>{tier.name}</CardTitle>
84
+ <CardDescription>{tier.description}</CardDescription>
85
+ <div className="mt-2 flex items-baseline gap-1">
86
+ <span className="font-display text-4xl font-semibold tracking-tight text-fg">
87
+ {tier.price}
88
+ </span>
89
+ {tier.cadence ? (
90
+ <span className="text-sm text-fg-tertiary">{tier.cadence}</span>
91
+ ) : null}
92
+ </div>
93
+ </CardHeader>
94
+ <CardContent>
95
+ <ul className="flex flex-col gap-3">
96
+ {tier.features.map((feature) => (
97
+ <li key={feature} className="flex items-center gap-2.5 text-sm text-fg-secondary">
98
+ <span className="grid size-5 shrink-0 place-items-center rounded-full bg-primary/15">
99
+ <Check aria-hidden="true" className="size-3 text-primary" />
100
+ </span>
101
+ {feature}
102
+ </li>
103
+ ))}
104
+ </ul>
105
+ </CardContent>
106
+ <CardFooter>
107
+ <Button variant={tier.featured ? "primary" : "outline"} className="w-full">
108
+ {tier.cta}
109
+ </Button>
110
+ </CardFooter>
111
+ </Card>
112
+ ))}
113
+ </div>
114
+ </section>
115
+ );
116
+ }
@@ -0,0 +1,91 @@
1
+ import { Separator } from "@cronus-ui/ui/separator";
2
+ import { Sparkles } from "lucide-react";
3
+
4
+ const FOOTER_COLUMNS = [
5
+ {
6
+ heading: "Product",
7
+ links: [
8
+ { label: "Features", href: "#features" },
9
+ { label: "Pricing", href: "#pricing" },
10
+ { label: "FAQ", href: "#faq" },
11
+ { label: "Waitlist", href: "#waitlist" },
12
+ ],
13
+ },
14
+ {
15
+ heading: "Company",
16
+ links: [
17
+ { label: "About", href: "#about" },
18
+ { label: "Careers", href: "#careers" },
19
+ { label: "Contact", href: "#contact" },
20
+ ],
21
+ },
22
+ {
23
+ heading: "Resources",
24
+ links: [
25
+ { label: "Documentation", href: "#docs" },
26
+ { label: "Guides", href: "#guides" },
27
+ { label: "Support", href: "#support" },
28
+ ],
29
+ },
30
+ ] as const;
31
+
32
+ /** Brand block, link columns, and the legal bottom bar. */
33
+ export function SiteFooter() {
34
+ return (
35
+ <footer className="border-t border-border bg-surface-base px-6 py-16">
36
+ <div className="mx-auto max-w-6xl">
37
+ <div className="grid gap-12 lg:grid-cols-[1.5fr_repeat(3,1fr)]">
38
+ <div className="max-w-xs">
39
+ <div className="flex items-center gap-2.5">
40
+ <span className="grid size-9 place-items-center rounded-xl bg-gradient-primary text-primary-foreground shadow-glow">
41
+ <Sparkles aria-hidden="true" className="size-5" />
42
+ </span>
43
+ <span className="font-display text-lg font-semibold text-fg">__APP_NAME__</span>
44
+ </div>
45
+ <p className="mt-4 text-sm leading-6 text-fg-secondary">
46
+ Built with Cronus UI — themeable, accessible React components for teams who ship
47
+ polished products fast.
48
+ </p>
49
+ </div>
50
+
51
+ {FOOTER_COLUMNS.map((column) => (
52
+ <div key={column.heading}>
53
+ <h3 className="text-sm font-medium text-fg">{column.heading}</h3>
54
+ <ul className="mt-4 flex flex-col gap-3">
55
+ {column.links.map((link) => (
56
+ <li key={link.label}>
57
+ <a
58
+ href={link.href}
59
+ className="text-sm text-fg-secondary transition-colors hover:text-fg"
60
+ >
61
+ {link.label}
62
+ </a>
63
+ </li>
64
+ ))}
65
+ </ul>
66
+ </div>
67
+ ))}
68
+ </div>
69
+
70
+ <Separator className="my-8" />
71
+
72
+ <div className="flex flex-col items-center justify-between gap-4 sm:flex-row">
73
+ <p className="text-sm text-fg-tertiary">
74
+ © {new Date().getFullYear()} __APP_NAME__. All rights reserved.
75
+ </p>
76
+ <div className="flex items-center gap-6">
77
+ <a
78
+ href="#privacy"
79
+ className="text-sm text-fg-secondary transition-colors hover:text-fg"
80
+ >
81
+ Privacy
82
+ </a>
83
+ <a href="#terms" className="text-sm text-fg-secondary transition-colors hover:text-fg">
84
+ Terms
85
+ </a>
86
+ </div>
87
+ </div>
88
+ </div>
89
+ </footer>
90
+ );
91
+ }
@@ -0,0 +1,47 @@
1
+ import { Button } from "@cronus-ui/ui/button";
2
+ import { Sparkles } from "lucide-react";
3
+ import Link from "next/link";
4
+
5
+ const NAV_LINKS = [
6
+ { label: "Features", href: "#features" },
7
+ { label: "Pricing", href: "#pricing" },
8
+ { label: "FAQ", href: "#faq" },
9
+ ] as const;
10
+
11
+ /** Sticky translucent header: brand, anchor nav, and the primary CTA. */
12
+ export function SiteHeader() {
13
+ return (
14
+ <header className="sticky top-0 z-50 border-b border-border/70 bg-surface-base/70 backdrop-blur-xl">
15
+ <nav
16
+ aria-label="Primary"
17
+ className="mx-auto flex h-16 w-full max-w-6xl items-center justify-between gap-4 px-6"
18
+ >
19
+ <Link href="/" className="flex items-center gap-2.5">
20
+ <span className="grid size-8 place-items-center rounded-lg bg-gradient-primary text-primary-foreground shadow-glow">
21
+ <Sparkles className="size-4" aria-hidden="true" />
22
+ </span>
23
+ <span className="font-display text-base font-semibold tracking-tight text-fg">
24
+ __APP_NAME__
25
+ </span>
26
+ </Link>
27
+
28
+ <ul className="hidden items-center gap-1 sm:flex">
29
+ {NAV_LINKS.map((link) => (
30
+ <li key={link.href}>
31
+ <a
32
+ href={link.href}
33
+ className="rounded-lg px-3 py-2 text-sm text-fg-secondary transition-colors hover:text-fg"
34
+ >
35
+ {link.label}
36
+ </a>
37
+ </li>
38
+ ))}
39
+ </ul>
40
+
41
+ <Button variant="primary" size="sm" asChild>
42
+ <a href="#waitlist">Join the waitlist</a>
43
+ </Button>
44
+ </nav>
45
+ </header>
46
+ );
47
+ }
@@ -0,0 +1,91 @@
1
+ import { Avatar, AvatarFallback } from "@cronus-ui/ui/avatar";
2
+ import { Badge } from "@cronus-ui/ui/badge";
3
+ import { Card, CardContent } from "@cronus-ui/ui/card";
4
+ import { Sparkles } from "lucide-react";
5
+
6
+ const TESTIMONIALS = [
7
+ {
8
+ quote:
9
+ "We replaced a tangle of one-off components with one themeable system. Our redesign shipped weeks early.",
10
+ name: "Amara Okafor",
11
+ role: "VP Design, Northwind",
12
+ initials: "AO",
13
+ },
14
+ {
15
+ quote:
16
+ "Every surface inherits our brand the moment we change a token. It's the closest thing to magic our team has shipped.",
17
+ name: "Marco Rossi",
18
+ role: "Staff Engineer, Lumen",
19
+ initials: "MR",
20
+ },
21
+ {
22
+ quote:
23
+ "Accessibility used to be an afterthought. Now it's the default — we pass audits without a scramble before launch.",
24
+ name: "Priya Nair",
25
+ role: "Head of Product, Cobalt",
26
+ initials: "PN",
27
+ },
28
+ {
29
+ quote:
30
+ "We onboarded three new engineers in a day. The sections read like documentation you can paste straight into the app.",
31
+ name: "Jonas Berg",
32
+ role: "Engineering Lead, Fathom",
33
+ initials: "JB",
34
+ },
35
+ {
36
+ quote:
37
+ "The cards, the gradients, the polish — it all feels premium out of the box. Our marketing site looks bespoke.",
38
+ name: "Sofia Lindqvist",
39
+ role: "Founder, Driftwood",
40
+ initials: "SL",
41
+ },
42
+ {
43
+ quote:
44
+ "This is the first design system our designers and engineers actually agree on. That alone paid for itself.",
45
+ name: "David Chen",
46
+ role: "CTO, Parallel",
47
+ initials: "DC",
48
+ },
49
+ ] as const;
50
+
51
+ /** Quote cards in a responsive three-column grid. */
52
+ export function Testimonials() {
53
+ return (
54
+ <section className="px-6 py-20">
55
+ <div className="mx-auto flex max-w-2xl flex-col items-center text-center">
56
+ <Badge variant="secondary" className="gap-1.5">
57
+ <Sparkles aria-hidden="true" className="size-3.5" />
58
+ Loved by teams
59
+ </Badge>
60
+ <h2 className="mt-4 text-balance font-display text-3xl font-semibold tracking-tight text-fg sm:text-4xl">
61
+ Loved by modern product teams
62
+ </h2>
63
+ <p className="mt-4 text-balance text-fg-secondary">
64
+ From seed-stage startups to public companies — teams ship faster when every surface is
65
+ accessible, themeable, and consistent.
66
+ </p>
67
+ </div>
68
+
69
+ <div className="mx-auto mt-14 grid max-w-5xl gap-6 sm:grid-cols-2 lg:grid-cols-3">
70
+ {TESTIMONIALS.map((testimonial) => (
71
+ <Card key={testimonial.name} className="border-border">
72
+ <CardContent className="flex h-full flex-col gap-5 pt-6">
73
+ <p className="text-sm leading-6 text-fg-secondary">“{testimonial.quote}”</p>
74
+ <div className="mt-auto flex items-center gap-3">
75
+ <Avatar className="size-9">
76
+ <AvatarFallback className="bg-surface-overlay text-xs text-fg-secondary">
77
+ {testimonial.initials}
78
+ </AvatarFallback>
79
+ </Avatar>
80
+ <div className="min-w-0">
81
+ <p className="truncate text-sm font-medium text-fg">{testimonial.name}</p>
82
+ <p className="truncate text-xs text-fg-tertiary">{testimonial.role}</p>
83
+ </div>
84
+ </div>
85
+ </CardContent>
86
+ </Card>
87
+ ))}
88
+ </div>
89
+ </section>
90
+ );
91
+ }
@@ -0,0 +1,93 @@
1
+ "use client";
2
+
3
+ import { Button } from "@cronus-ui/ui/button";
4
+ import { Input } from "@cronus-ui/ui/input";
5
+ import { Label } from "@cronus-ui/ui/label";
6
+ import { ArrowRight, Check } from "lucide-react";
7
+ import { useState } from "react";
8
+
9
+ /**
10
+ * Waitlist email capture that swaps to a joined confirmation on submit. The
11
+ * swap area is a persistent `aria-live` region so the change is announced to
12
+ * screen readers. Replace the `onSubmit` with your API call or server action.
13
+ */
14
+ export function WaitlistCta() {
15
+ const [email, setEmail] = useState("");
16
+ const [joined, setJoined] = useState(false);
17
+
18
+ return (
19
+ <section id="waitlist" className="scroll-mt-16 px-6 py-20">
20
+ <div className="relative mx-auto max-w-5xl overflow-hidden rounded-2xl bg-gradient-primary px-8 py-16 text-center shadow-glow sm:px-16">
21
+ <div
22
+ aria-hidden="true"
23
+ className="pointer-events-none absolute inset-0 [mask-image:radial-gradient(ellipse_at_center,black,transparent_75%)]"
24
+ style={{
25
+ backgroundImage: "radial-gradient(circle, rgba(255,255,255,0.25) 1px, transparent 1px)",
26
+ backgroundSize: "22px 22px",
27
+ }}
28
+ />
29
+ <div className="relative mx-auto max-w-2xl">
30
+ <h2 className="font-display text-4xl font-semibold tracking-tight text-primary-foreground sm:text-5xl">
31
+ Be first in line
32
+ </h2>
33
+ <p className="mt-4 text-balance text-lg text-primary-foreground/80">
34
+ Join the waitlist and we&apos;ll email your invite the moment a spot opens. No spam, and
35
+ you can leave the list any time.
36
+ </p>
37
+
38
+ <div aria-live="polite" className="mx-auto mt-8 max-w-md">
39
+ {joined ? (
40
+ <div
41
+ role="status"
42
+ className="flex items-center gap-3 rounded-xl bg-surface-base px-4 py-3 text-left shadow-sm"
43
+ >
44
+ <span className="inline-flex size-9 shrink-0 items-center justify-center rounded-full bg-success/10 text-success">
45
+ <Check aria-hidden="true" className="size-4" />
46
+ </span>
47
+ <div className="min-w-0 flex-1">
48
+ <p className="text-sm font-medium text-fg">You&apos;re on the list</p>
49
+ <p className="truncate text-sm text-fg-tertiary">
50
+ We&apos;ll email {email} when your invite is ready.
51
+ </p>
52
+ </div>
53
+ </div>
54
+ ) : (
55
+ <form
56
+ aria-label="Join the waitlist"
57
+ className="flex flex-col gap-3 sm:flex-row"
58
+ onSubmit={(event) => {
59
+ event.preventDefault();
60
+ setJoined(true);
61
+ }}
62
+ >
63
+ <div className="flex-1 text-left">
64
+ <Label htmlFor="waitlist-email" className="sr-only">
65
+ Email address
66
+ </Label>
67
+ <Input
68
+ id="waitlist-email"
69
+ type="email"
70
+ required
71
+ autoComplete="email"
72
+ placeholder="you@company.com"
73
+ value={email}
74
+ onChange={(event) => setEmail(event.target.value)}
75
+ className="h-11 border-transparent bg-surface-base text-fg placeholder:text-fg-tertiary"
76
+ />
77
+ </div>
78
+ <Button type="submit" variant="secondary" size="lg">
79
+ Join the waitlist
80
+ <ArrowRight aria-hidden="true" />
81
+ </Button>
82
+ </form>
83
+ )}
84
+ </div>
85
+
86
+ <p className="mt-4 text-sm text-primary-foreground/70">
87
+ No spam. Unsubscribe at any time.
88
+ </p>
89
+ </div>
90
+ </div>
91
+ </section>
92
+ );
93
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "aliases": {
3
+ "ui": "@/components/ui",
4
+ "lib": "@/lib",
5
+ "blocks": "@/components/blocks"
6
+ },
7
+ "paths": {
8
+ "ui": "components/ui",
9
+ "lib": "lib",
10
+ "blocks": "components/blocks"
11
+ },
12
+ "registry": "https://raw.githubusercontent.com/pedrogbraz/cronus-ui/v0.6.0/registry",
13
+ "theme": {
14
+ "name": "__THEME__",
15
+ "mode": "__MODE__"
16
+ }
17
+ }
@@ -0,0 +1,34 @@
1
+ # dependencies
2
+ /node_modules
3
+ /.pnp
4
+ .pnp.*
5
+
6
+ # next.js
7
+ /.next/
8
+ /out/
9
+
10
+ # production
11
+ /build
12
+
13
+ # misc
14
+ .DS_Store
15
+ *.pem
16
+
17
+ # debug
18
+ npm-debug.log*
19
+ yarn-debug.log*
20
+ yarn-error.log*
21
+ .pnpm-debug.log*
22
+
23
+ # env files
24
+ .env*.local
25
+
26
+ # typescript
27
+ *.tsbuildinfo
28
+ next-env.d.ts
29
+
30
+ # lockfiles (keep the one your package manager writes)
31
+ # package-lock.json
32
+ # pnpm-lock.yaml
33
+ # yarn.lock
34
+ # bun.lockb
@@ -0,0 +1,11 @@
1
+ /**
2
+ * @cronus-ui/ui ships ESM with its `"use client"` boundaries already in place,
3
+ * so no `transpilePackages` is needed when it's installed (the normal case).
4
+ *
5
+ * @type {import('next').NextConfig}
6
+ */
7
+ const nextConfig = {
8
+ reactStrictMode: true,
9
+ };
10
+
11
+ export default nextConfig;
@@ -0,0 +1,28 @@
1
+ {
2
+ "name": "__APP_NAME__",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "next dev",
8
+ "build": "next build",
9
+ "start": "next start"
10
+ },
11
+ "dependencies": {
12
+ "@cronus-ui/theme": "^0.6.0",
13
+ "@cronus-ui/tokens": "^0.6.0",
14
+ "@cronus-ui/ui": "^0.6.0",
15
+ "lucide-react": "^0.577.0",
16
+ "next": "16.2.10",
17
+ "react": "^19.2.0",
18
+ "react-dom": "^19.2.0"
19
+ },
20
+ "devDependencies": {
21
+ "@tailwindcss/postcss": "^4.3.0",
22
+ "@types/node": "^22.10.0",
23
+ "@types/react": "^19.0.0",
24
+ "@types/react-dom": "^19.0.0",
25
+ "tailwindcss": "^4.3.0",
26
+ "typescript": "^6.0.3"
27
+ }
28
+ }
@@ -0,0 +1,7 @@
1
+ const config = {
2
+ plugins: {
3
+ "@tailwindcss/postcss": {},
4
+ },
5
+ };
6
+
7
+ export default config;