shipd 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (145) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +205 -0
  3. package/dist/index.d.ts +1 -0
  4. package/dist/index.js +1366 -0
  5. package/docs-template/README.md +255 -0
  6. package/docs-template/[slug]/[subslug]/page.tsx +1242 -0
  7. package/docs-template/[slug]/page.tsx +422 -0
  8. package/docs-template/api/page.tsx +47 -0
  9. package/docs-template/components/docs/docs-category-page.tsx +162 -0
  10. package/docs-template/components/docs/docs-code-card.tsx +135 -0
  11. package/docs-template/components/docs/docs-header.tsx +69 -0
  12. package/docs-template/components/docs/docs-nav.ts +95 -0
  13. package/docs-template/components/docs/docs-sidebar.tsx +112 -0
  14. package/docs-template/components/docs/docs-toc.tsx +38 -0
  15. package/docs-template/components/ui/badge.tsx +47 -0
  16. package/docs-template/components/ui/button.tsx +60 -0
  17. package/docs-template/components/ui/card.tsx +93 -0
  18. package/docs-template/components/ui/sheet.tsx +140 -0
  19. package/docs-template/documentation/page.tsx +80 -0
  20. package/docs-template/layout.tsx +27 -0
  21. package/docs-template/lib/utils.ts +7 -0
  22. package/docs-template/page.tsx +360 -0
  23. package/package.json +66 -0
  24. package/template/.env.example +45 -0
  25. package/template/README.md +239 -0
  26. package/template/app/api/auth/[...all]/route.ts +4 -0
  27. package/template/app/api/chat/route.ts +16 -0
  28. package/template/app/api/subscription/route.ts +25 -0
  29. package/template/app/api/upload-image/route.ts +64 -0
  30. package/template/app/blog/[slug]/page.tsx +314 -0
  31. package/template/app/blog/page.tsx +107 -0
  32. package/template/app/dashboard/_components/chart-interactive.tsx +289 -0
  33. package/template/app/dashboard/_components/chatbot.tsx +39 -0
  34. package/template/app/dashboard/_components/mode-toggle.tsx +46 -0
  35. package/template/app/dashboard/_components/navbar.tsx +84 -0
  36. package/template/app/dashboard/_components/section-cards.tsx +102 -0
  37. package/template/app/dashboard/_components/sidebar.tsx +90 -0
  38. package/template/app/dashboard/_components/subscribe-button.tsx +49 -0
  39. package/template/app/dashboard/billing/page.tsx +277 -0
  40. package/template/app/dashboard/chat/page.tsx +73 -0
  41. package/template/app/dashboard/cli/page.tsx +260 -0
  42. package/template/app/dashboard/layout.tsx +24 -0
  43. package/template/app/dashboard/page.tsx +216 -0
  44. package/template/app/dashboard/payment/_components/manage-subscription.tsx +22 -0
  45. package/template/app/dashboard/payment/page.tsx +126 -0
  46. package/template/app/dashboard/settings/page.tsx +613 -0
  47. package/template/app/dashboard/upload/page.tsx +324 -0
  48. package/template/app/error.tsx +78 -0
  49. package/template/app/favicon.ico +0 -0
  50. package/template/app/globals.css +126 -0
  51. package/template/app/layout.tsx +135 -0
  52. package/template/app/not-found.tsx +45 -0
  53. package/template/app/page.tsx +28 -0
  54. package/template/app/pricing/_component/pricing-table.tsx +276 -0
  55. package/template/app/pricing/page.tsx +23 -0
  56. package/template/app/privacy-policy/page.tsx +280 -0
  57. package/template/app/robots.txt +12 -0
  58. package/template/app/sign-in/page.tsx +228 -0
  59. package/template/app/sign-up/page.tsx +243 -0
  60. package/template/app/sitemap.ts +62 -0
  61. package/template/app/success/page.tsx +123 -0
  62. package/template/app/terms-of-service/page.tsx +212 -0
  63. package/template/auth-schema.ts +47 -0
  64. package/template/components/homepage/cli-workflow-section.tsx +138 -0
  65. package/template/components/homepage/features-section.tsx +150 -0
  66. package/template/components/homepage/footer.tsx +53 -0
  67. package/template/components/homepage/hero-section.tsx +112 -0
  68. package/template/components/homepage/integrations.tsx +124 -0
  69. package/template/components/homepage/navigation.tsx +116 -0
  70. package/template/components/homepage/news-section.tsx +82 -0
  71. package/template/components/homepage/testimonials-section.tsx +34 -0
  72. package/template/components/logos/BetterAuth.tsx +21 -0
  73. package/template/components/logos/NeonPostgres.tsx +41 -0
  74. package/template/components/logos/Nextjs.tsx +72 -0
  75. package/template/components/logos/Polar.tsx +7 -0
  76. package/template/components/logos/TailwindCSS.tsx +27 -0
  77. package/template/components/logos/index.ts +6 -0
  78. package/template/components/logos/shadcnui.tsx +8 -0
  79. package/template/components/provider.tsx +8 -0
  80. package/template/components/ui/avatar.tsx +53 -0
  81. package/template/components/ui/badge.tsx +46 -0
  82. package/template/components/ui/button.tsx +59 -0
  83. package/template/components/ui/card.tsx +92 -0
  84. package/template/components/ui/chart.tsx +353 -0
  85. package/template/components/ui/checkbox.tsx +32 -0
  86. package/template/components/ui/dialog.tsx +135 -0
  87. package/template/components/ui/dropdown-menu.tsx +257 -0
  88. package/template/components/ui/form.tsx +167 -0
  89. package/template/components/ui/input.tsx +21 -0
  90. package/template/components/ui/label.tsx +24 -0
  91. package/template/components/ui/progress.tsx +31 -0
  92. package/template/components/ui/resizable.tsx +56 -0
  93. package/template/components/ui/select.tsx +185 -0
  94. package/template/components/ui/separator.tsx +28 -0
  95. package/template/components/ui/sheet.tsx +139 -0
  96. package/template/components/ui/skeleton.tsx +13 -0
  97. package/template/components/ui/sonner.tsx +25 -0
  98. package/template/components/ui/switch.tsx +31 -0
  99. package/template/components/ui/tabs.tsx +66 -0
  100. package/template/components/ui/textarea.tsx +18 -0
  101. package/template/components/ui/toggle-group.tsx +73 -0
  102. package/template/components/ui/toggle.tsx +47 -0
  103. package/template/components/ui/tooltip.tsx +61 -0
  104. package/template/components/user-profile.tsx +139 -0
  105. package/template/components.json +21 -0
  106. package/template/db/drizzle.ts +14 -0
  107. package/template/db/migrations/0000_worried_rawhide_kid.sql +77 -0
  108. package/template/db/migrations/meta/0000_snapshot.json +494 -0
  109. package/template/db/migrations/meta/_journal.json +13 -0
  110. package/template/db/schema.ts +85 -0
  111. package/template/drizzle.config.ts +13 -0
  112. package/template/emails/components/layout.tsx +181 -0
  113. package/template/emails/password-reset.tsx +67 -0
  114. package/template/emails/payment-failed.tsx +167 -0
  115. package/template/emails/subscription-confirmation.tsx +129 -0
  116. package/template/emails/welcome.tsx +100 -0
  117. package/template/eslint.config.mjs +16 -0
  118. package/template/hooks/use-mobile.ts +21 -0
  119. package/template/lib/auth-client.ts +8 -0
  120. package/template/lib/auth.ts +276 -0
  121. package/template/lib/email.ts +118 -0
  122. package/template/lib/polar-products.ts +49 -0
  123. package/template/lib/subscription.ts +148 -0
  124. package/template/lib/upload-image.ts +28 -0
  125. package/template/lib/utils.ts +6 -0
  126. package/template/middleware.ts +30 -0
  127. package/template/next-env.d.ts +5 -0
  128. package/template/next.config.ts +27 -0
  129. package/template/package.json +99 -0
  130. package/template/postcss.config.mjs +5 -0
  131. package/template/public/add.png +0 -0
  132. package/template/public/favicon.svg +4 -0
  133. package/template/public/file.svg +1 -0
  134. package/template/public/globe.svg +1 -0
  135. package/template/public/iphone.png +0 -0
  136. package/template/public/logo.png +0 -0
  137. package/template/public/next.svg +1 -0
  138. package/template/public/polar-sh.svg +1 -0
  139. package/template/public/shadcn-ui.svg +1 -0
  140. package/template/public/site.webmanifest +21 -0
  141. package/template/public/vercel.svg +1 -0
  142. package/template/public/window.svg +1 -0
  143. package/template/tailwind.config.ts +89 -0
  144. package/template/template.config.json +138 -0
  145. package/template/tsconfig.json +27 -0
@@ -0,0 +1,228 @@
1
+ "use client";
2
+
3
+ import { Button } from "@/components/ui/button";
4
+ import {
5
+ Card,
6
+ CardContent,
7
+ CardDescription,
8
+ CardHeader,
9
+ CardTitle,
10
+ } from "@/components/ui/card";
11
+ import { Input } from "@/components/ui/input";
12
+ import { Label } from "@/components/ui/label";
13
+ import { authClient } from "@/lib/auth-client";
14
+ import { cn } from "@/lib/utils";
15
+ import Link from "next/link";
16
+ import { useRouter, useSearchParams } from "next/navigation";
17
+ import { Suspense, useState } from "react";
18
+ import { toast } from "sonner";
19
+
20
+ function SignInContent() {
21
+ const [loading, setLoading] = useState(false);
22
+ const [email, setEmail] = useState("");
23
+ const [password, setPassword] = useState("");
24
+ const searchParams = useSearchParams();
25
+ const returnTo = searchParams.get("returnTo");
26
+ const router = useRouter();
27
+
28
+ const handleEmailSignIn = async (e: React.FormEvent) => {
29
+ e.preventDefault();
30
+ setLoading(true);
31
+
32
+ try {
33
+ const { error } = await authClient.signIn.email({
34
+ email,
35
+ password,
36
+ callbackURL: returnTo || "/dashboard",
37
+ });
38
+
39
+ if (error) {
40
+ console.error("Sign-in error:", error);
41
+
42
+ // Provide helpful error messages
43
+ if (error.message?.includes("database") || error.message?.includes("connect")) {
44
+ toast.error("Database connection failed. Please configure DATABASE_URL in your .env.local file.", {
45
+ duration: 7000,
46
+ });
47
+ } else if (error.message?.includes("Invalid") || error.message?.includes("credentials")) {
48
+ toast.error("Invalid email or password. Please try again.");
49
+ } else {
50
+ toast.error(error.message || "Sign-in failed. Check your environment configuration.", {
51
+ duration: 5000,
52
+ });
53
+ }
54
+ } else {
55
+ toast.success("Signed in successfully!");
56
+ router.push(returnTo || "/dashboard");
57
+ }
58
+ } catch (err) {
59
+ console.error("Authentication error:", err);
60
+ toast.error("An unexpected error occurred. Check console for details.", {
61
+ duration: 5000,
62
+ });
63
+ } finally {
64
+ setLoading(false);
65
+ }
66
+ };
67
+
68
+ return (
69
+ <div className="flex flex-col justify-center items-center w-full h-screen bg-black">
70
+ <Card className="max-w-md w-full bg-[#0a0a0a] border-[#2a2a2a]">
71
+ <CardHeader>
72
+ <CardTitle className="text-lg md:text-xl text-white">
73
+ Welcome Back to {{PROJECT_NAME}}
74
+ </CardTitle>
75
+ <CardDescription className="text-xs md:text-sm text-gray-400">
76
+ Sign in to your account to continue
77
+ </CardDescription>
78
+ </CardHeader>
79
+ <CardContent>
80
+ <form onSubmit={handleEmailSignIn} className="grid gap-4">
81
+ <div className="grid gap-2">
82
+ <Label htmlFor="email" className="text-gray-300">Email</Label>
83
+ <Input
84
+ id="email"
85
+ type="email"
86
+ placeholder="you@example.com"
87
+ value={email}
88
+ onChange={(e) => setEmail(e.target.value)}
89
+ required
90
+ disabled={loading}
91
+ className="bg-[#1a1a1a] border-[#2a2a2a] text-white placeholder:text-gray-500"
92
+ />
93
+ </div>
94
+ <div className="grid gap-2">
95
+ <Label htmlFor="password" className="text-gray-300">Password</Label>
96
+ <Input
97
+ id="password"
98
+ type="password"
99
+ placeholder="Enter your password"
100
+ value={password}
101
+ onChange={(e) => setPassword(e.target.value)}
102
+ required
103
+ disabled={loading}
104
+ className="bg-[#1a1a1a] border-[#2a2a2a] text-white placeholder:text-gray-500"
105
+ />
106
+ </div>
107
+ <Button type="submit" className="w-full" disabled={loading}>
108
+ {loading ? "Signing in..." : "Sign In"}
109
+ </Button>
110
+ </form>
111
+
112
+ <div className="relative my-4">
113
+ <div className="absolute inset-0 flex items-center">
114
+ <span className="w-full border-t border-[#2a2a2a]" />
115
+ </div>
116
+ <div className="relative flex justify-center text-xs uppercase">
117
+ <span className="bg-[#0a0a0a] px-2 text-gray-500">Or continue with</span>
118
+ </div>
119
+ </div>
120
+
121
+ <Button
122
+ variant="outline"
123
+ className={cn("w-full gap-2 bg-[#1a1a1a] border-[#2a2a2a] text-white hover:bg-[#2a2a2a]")}
124
+ disabled={loading}
125
+ onClick={async () => {
126
+ try {
127
+ setLoading(true);
128
+ await authClient.signIn.social(
129
+ {
130
+ provider: "google",
131
+ callbackURL: returnTo || "/dashboard",
132
+ },
133
+ {
134
+ onResponse: () => {
135
+ setLoading(false);
136
+ },
137
+ onError: (ctx) => {
138
+ setLoading(false);
139
+ console.error("Sign-in failed:", ctx.error);
140
+
141
+ if (ctx.error?.message?.includes("database") || ctx.error?.message?.includes("connect")) {
142
+ toast.error("Database connection failed. Please configure DATABASE_URL in your .env.local file.", {
143
+ duration: 7000,
144
+ });
145
+ } else {
146
+ toast.error("Google sign-in failed. Check your Google OAuth configuration.", {
147
+ duration: 5000,
148
+ });
149
+ }
150
+ },
151
+ },
152
+ );
153
+ } catch (error) {
154
+ setLoading(false);
155
+ console.error("Authentication error:", error);
156
+ toast.error("Authentication error. Check console for details.", {
157
+ duration: 5000,
158
+ });
159
+ }
160
+ }}
161
+ >
162
+ <svg
163
+ xmlns="http://www.w3.org/2000/svg"
164
+ width="0.98em"
165
+ height="1em"
166
+ viewBox="0 0 256 262"
167
+ >
168
+ <path
169
+ fill="#4285F4"
170
+ d="M255.878 133.451c0-10.734-.871-18.567-2.756-26.69H130.55v48.448h71.947c-1.45 12.04-9.283 30.172-26.69 42.356l-.244 1.622l38.755 30.023l2.685.268c24.659-22.774 38.875-56.282 38.875-96.027"
171
+ ></path>
172
+ <path
173
+ fill="#34A853"
174
+ d="M130.55 261.1c35.248 0 64.839-11.605 86.453-31.622l-41.196-31.913c-11.024 7.688-25.82 13.055-45.257 13.055c-34.523 0-63.824-22.773-74.269-54.25l-1.531.13l-40.298 31.187l-.527 1.465C35.393 231.798 79.49 261.1 130.55 261.1"
175
+ ></path>
176
+ <path
177
+ fill="#FBBC05"
178
+ d="M56.281 156.37c-2.756-8.123-4.351-16.827-4.351-25.82c0-8.994 1.595-17.697 4.206-25.82l-.073-1.73L15.26 71.312l-1.335.635C5.077 89.644 0 109.517 0 130.55s5.077 40.905 13.925 58.602z"
179
+ ></path>
180
+ <path
181
+ fill="#EB4335"
182
+ d="M130.55 50.479c24.514 0 41.05 10.589 50.479 19.438l36.844-35.974C195.245 12.91 165.798 0 130.55 0C79.49 0 35.393 29.301 13.925 71.947l42.211 32.783c10.59-31.477 39.891-54.251 74.414-54.251"
183
+ ></path>
184
+ </svg>
185
+ Continue with Google
186
+ </Button>
187
+
188
+ <p className="mt-4 text-center text-sm text-gray-500">
189
+ Don&apos;t have an account?{" "}
190
+ <Link href="/sign-up" className="text-[#ff5722] hover:underline">
191
+ Sign up
192
+ </Link>
193
+ </p>
194
+ </CardContent>
195
+ </Card>
196
+ <p className="mt-6 text-xs text-center text-gray-500 dark:text-gray-400 max-w-md">
197
+ By signing in, you agree to our{" "}
198
+ <Link
199
+ href="/terms-of-service"
200
+ className="underline hover:text-gray-700 dark:hover:text-gray-300"
201
+ >
202
+ Terms of Service
203
+ </Link>{" "}
204
+ and{" "}
205
+ <Link
206
+ href="/privacy-policy"
207
+ className="underline hover:text-gray-700 dark:hover:text-gray-300"
208
+ >
209
+ Privacy Policy
210
+ </Link>
211
+ </p>
212
+ </div>
213
+ );
214
+ }
215
+
216
+ export default function SignIn() {
217
+ return (
218
+ <Suspense
219
+ fallback={
220
+ <div className="flex flex-col justify-center items-center w-full h-screen">
221
+ <div className="max-w-md w-full bg-gray-200 dark:bg-gray-800 animate-pulse rounded-lg h-96"></div>
222
+ </div>
223
+ }
224
+ >
225
+ <SignInContent />
226
+ </Suspense>
227
+ );
228
+ }
@@ -0,0 +1,243 @@
1
+ "use client";
2
+
3
+ import { Button } from "@/components/ui/button";
4
+ import {
5
+ Card,
6
+ CardContent,
7
+ CardDescription,
8
+ CardHeader,
9
+ CardTitle,
10
+ } from "@/components/ui/card";
11
+ import { Input } from "@/components/ui/input";
12
+ import { Label } from "@/components/ui/label";
13
+ import { authClient } from "@/lib/auth-client";
14
+ import { cn } from "@/lib/utils";
15
+ import Link from "next/link";
16
+ import { useRouter, useSearchParams } from "next/navigation";
17
+ import { Suspense, useState } from "react";
18
+ import { toast } from "sonner";
19
+
20
+ function SignUpContent() {
21
+ const [loading, setLoading] = useState(false);
22
+ const [name, setName] = useState("");
23
+ const [email, setEmail] = useState("");
24
+ const [password, setPassword] = useState("");
25
+ const searchParams = useSearchParams();
26
+ const returnTo = searchParams.get("returnTo");
27
+ const router = useRouter();
28
+
29
+ const handleEmailSignUp = async (e: React.FormEvent) => {
30
+ e.preventDefault();
31
+ setLoading(true);
32
+
33
+ try {
34
+ const { error } = await authClient.signUp.email({
35
+ email,
36
+ password,
37
+ name,
38
+ callbackURL: returnTo || "/dashboard",
39
+ });
40
+
41
+ if (error) {
42
+ console.error("Sign-up error:", error);
43
+
44
+ if (error.message?.includes("database") || error.message?.includes("connect")) {
45
+ toast.error("Database connection failed. Please configure DATABASE_URL in your .env.local file.", {
46
+ duration: 7000,
47
+ });
48
+ } else if (error.message?.includes("already exists") || error.message?.includes("duplicate")) {
49
+ toast.error("An account with this email already exists. Please sign in instead.");
50
+ } else {
51
+ toast.error(error.message || "Sign-up failed. Check your environment configuration.", {
52
+ duration: 5000,
53
+ });
54
+ }
55
+ } else {
56
+ toast.success("Account created successfully!");
57
+ router.push(returnTo || "/dashboard");
58
+ }
59
+ } catch (err) {
60
+ console.error("Authentication error:", err);
61
+ toast.error("An unexpected error occurred. Check console for details.", {
62
+ duration: 5000,
63
+ });
64
+ } finally {
65
+ setLoading(false);
66
+ }
67
+ };
68
+
69
+ return (
70
+ <div className="flex flex-col justify-center items-center w-full h-screen bg-black">
71
+ <Card className="max-w-md w-full bg-[#0a0a0a] border-[#2a2a2a]">
72
+ <CardHeader>
73
+ <CardTitle className="text-lg md:text-xl text-white">
74
+ Create Your {{PROJECT_NAME}} Account
75
+ </CardTitle>
76
+ <CardDescription className="text-xs md:text-sm text-gray-400">
77
+ Get started in seconds
78
+ </CardDescription>
79
+ </CardHeader>
80
+ <CardContent>
81
+ <form onSubmit={handleEmailSignUp} className="grid gap-4">
82
+ <div className="grid gap-2">
83
+ <Label htmlFor="name" className="text-gray-300">Name</Label>
84
+ <Input
85
+ id="name"
86
+ type="text"
87
+ placeholder="John Doe"
88
+ value={name}
89
+ onChange={(e) => setName(e.target.value)}
90
+ required
91
+ disabled={loading}
92
+ className="bg-[#1a1a1a] border-[#2a2a2a] text-white placeholder:text-gray-500"
93
+ />
94
+ </div>
95
+ <div className="grid gap-2">
96
+ <Label htmlFor="email" className="text-gray-300">Email</Label>
97
+ <Input
98
+ id="email"
99
+ type="email"
100
+ placeholder="you@example.com"
101
+ value={email}
102
+ onChange={(e) => setEmail(e.target.value)}
103
+ required
104
+ disabled={loading}
105
+ className="bg-[#1a1a1a] border-[#2a2a2a] text-white placeholder:text-gray-500"
106
+ />
107
+ </div>
108
+ <div className="grid gap-2">
109
+ <Label htmlFor="password" className="text-gray-300">Password</Label>
110
+ <Input
111
+ id="password"
112
+ type="password"
113
+ placeholder="Create a strong password"
114
+ value={password}
115
+ onChange={(e) => setPassword(e.target.value)}
116
+ required
117
+ disabled={loading}
118
+ minLength={8}
119
+ className="bg-[#1a1a1a] border-[#2a2a2a] text-white placeholder:text-gray-500"
120
+ />
121
+ </div>
122
+ <Button type="submit" className="w-full" disabled={loading}>
123
+ {loading ? "Creating account..." : "Create Account"}
124
+ </Button>
125
+ </form>
126
+
127
+ <div className="relative my-4">
128
+ <div className="absolute inset-0 flex items-center">
129
+ <span className="w-full border-t border-[#2a2a2a]" />
130
+ </div>
131
+ <div className="relative flex justify-center text-xs uppercase">
132
+ <span className="bg-[#0a0a0a] px-2 text-gray-500">Or continue with</span>
133
+ </div>
134
+ </div>
135
+
136
+ <Button
137
+ variant="outline"
138
+ className={cn("w-full gap-2 bg-[#1a1a1a] border-[#2a2a2a] text-white hover:bg-[#2a2a2a]")}
139
+ disabled={loading}
140
+ onClick={async () => {
141
+ try {
142
+ setLoading(true);
143
+ await authClient.signIn.social(
144
+ {
145
+ provider: "google",
146
+ callbackURL: returnTo || "/dashboard",
147
+ },
148
+ {
149
+ onResponse: () => {
150
+ setLoading(false);
151
+ },
152
+ onError: (ctx) => {
153
+ setLoading(false);
154
+ console.error("Sign-up failed:", ctx.error);
155
+
156
+ if (ctx.error?.message?.includes("database") || ctx.error?.message?.includes("connect")) {
157
+ toast.error("Database connection failed. Please configure DATABASE_URL in your .env.local file.", {
158
+ duration: 7000,
159
+ });
160
+ } else {
161
+ toast.error("Google sign-up failed. Check your Google OAuth configuration.", {
162
+ duration: 5000,
163
+ });
164
+ }
165
+ },
166
+ },
167
+ );
168
+ } catch (error) {
169
+ setLoading(false);
170
+ console.error("Authentication error:", error);
171
+ toast.error("Authentication error. Check console for details.", {
172
+ duration: 5000,
173
+ });
174
+ }
175
+ }}
176
+ >
177
+ <svg
178
+ xmlns="http://www.w3.org/2000/svg"
179
+ width="0.98em"
180
+ height="1em"
181
+ viewBox="0 0 256 262"
182
+ >
183
+ <path
184
+ fill="#4285F4"
185
+ d="M255.878 133.451c0-10.734-.871-18.567-2.756-26.69H130.55v48.448h71.947c-1.45 12.04-9.283 30.172-26.69 42.356l-.244 1.622l38.755 30.023l2.685.268c24.659-22.774 38.875-56.282 38.875-96.027"
186
+ ></path>
187
+ <path
188
+ fill="#34A853"
189
+ d="M130.55 261.1c35.248 0 64.839-11.605 86.453-31.622l-41.196-31.913c-11.024 7.688-25.82 13.055-45.257 13.055c-34.523 0-63.824-22.773-74.269-54.25l-1.531.13l-40.298 31.187l-.527 1.465C35.393 231.798 79.49 261.1 130.55 261.1"
190
+ ></path>
191
+ <path
192
+ fill="#FBBC05"
193
+ d="M56.281 156.37c-2.756-8.123-4.351-16.827-4.351-25.82c0-8.994 1.595-17.697 4.206-25.82l-.073-1.73L15.26 71.312l-1.335.635C5.077 89.644 0 109.517 0 130.55s5.077 40.905 13.925 58.602z"
194
+ ></path>
195
+ <path
196
+ fill="#EB4335"
197
+ d="M130.55 50.479c24.514 0 41.05 10.589 50.479 19.438l36.844-35.974C195.245 12.91 165.798 0 130.55 0C79.49 0 35.393 29.301 13.925 71.947l42.211 32.783c10.59-31.477 39.891-54.251 74.414-54.251"
198
+ ></path>
199
+ </svg>
200
+ Continue with Google
201
+ </Button>
202
+
203
+ <p className="mt-4 text-center text-sm text-gray-500">
204
+ Already have an account?{" "}
205
+ <Link href="/sign-in" className="text-[#ff5722] hover:underline">
206
+ Sign in
207
+ </Link>
208
+ </p>
209
+ </CardContent>
210
+ </Card>
211
+ <p className="mt-6 text-xs text-center text-gray-500 max-w-md">
212
+ By signing up, you agree to our{" "}
213
+ <Link
214
+ href="/terms-of-service"
215
+ className="underline hover:text-gray-400"
216
+ >
217
+ Terms of Service
218
+ </Link>{" "}
219
+ and{" "}
220
+ <Link
221
+ href="/privacy-policy"
222
+ className="underline hover:text-gray-400"
223
+ >
224
+ Privacy Policy
225
+ </Link>
226
+ </p>
227
+ </div>
228
+ );
229
+ }
230
+
231
+ export default function SignUp() {
232
+ return (
233
+ <Suspense
234
+ fallback={
235
+ <div className="flex flex-col justify-center items-center w-full h-screen bg-black">
236
+ <div className="max-w-md w-full bg-[#0a0a0a] animate-pulse rounded-lg h-96"></div>
237
+ </div>
238
+ }
239
+ >
240
+ <SignUpContent />
241
+ </Suspense>
242
+ );
243
+ }
@@ -0,0 +1,62 @@
1
+ import { MetadataRoute } from 'next'
2
+
3
+ export default function sitemap(): MetadataRoute.Sitemap {
4
+ const baseUrl = process.env.NEXT_PUBLIC_APP_URL || 'http://localhost:3000'
5
+
6
+ // Blog posts
7
+ const blogPosts = [
8
+ {
9
+ slug: 'getting-started-with-saas',
10
+ date: '2024-12-15',
11
+ },
12
+ {
13
+ slug: 'optimizing-conversion-rates',
14
+ date: '2024-12-10',
15
+ },
16
+ {
17
+ slug: 'scaling-your-saas',
18
+ date: '2024-12-05',
19
+ },
20
+ ]
21
+
22
+ const blogRoutes = blogPosts.map((post) => ({
23
+ url: `${baseUrl}/blog/${post.slug}`,
24
+ lastModified: new Date(post.date),
25
+ changeFrequency: 'monthly' as const,
26
+ priority: 0.7,
27
+ }))
28
+
29
+ return [
30
+ {
31
+ url: baseUrl,
32
+ lastModified: new Date(),
33
+ changeFrequency: 'weekly',
34
+ priority: 1,
35
+ },
36
+ {
37
+ url: `${baseUrl}/blog`,
38
+ lastModified: new Date(),
39
+ changeFrequency: 'weekly',
40
+ priority: 0.9,
41
+ },
42
+ ...blogRoutes,
43
+ {
44
+ url: `${baseUrl}/pricing`,
45
+ lastModified: new Date(),
46
+ changeFrequency: 'monthly',
47
+ priority: 0.8,
48
+ },
49
+ {
50
+ url: `${baseUrl}/terms-of-service`,
51
+ lastModified: new Date(),
52
+ changeFrequency: 'yearly',
53
+ priority: 0.3,
54
+ },
55
+ {
56
+ url: `${baseUrl}/privacy-policy`,
57
+ lastModified: new Date(),
58
+ changeFrequency: 'yearly',
59
+ priority: 0.3,
60
+ },
61
+ ]
62
+ }
@@ -0,0 +1,123 @@
1
+ "use client";
2
+
3
+ import { Button } from "@/components/ui/button";
4
+ import { Card, CardContent } from "@/components/ui/card";
5
+ import { CheckCircle2, Terminal, BookOpen, Zap } from "lucide-react";
6
+ import { useRouter } from "next/navigation";
7
+ import Link from "next/link";
8
+
9
+ export default function SuccessPage() {
10
+ const router = useRouter();
11
+
12
+ return (
13
+ <div className="min-h-screen bg-black flex items-center justify-center p-6">
14
+ <Card className="bg-[#0a0a0a] border-[#2a2a2a] max-w-2xl w-full">
15
+ <CardContent className="p-12">
16
+ {/* Success Icon */}
17
+ <div className="w-20 h-20 bg-green-500/10 rounded-full flex items-center justify-center mx-auto mb-6">
18
+ <CheckCircle2 className="w-12 h-12 text-green-400" />
19
+ </div>
20
+
21
+ {/* Success Message */}
22
+ <div className="text-center mb-8">
23
+ <h1 className="text-3xl font-bold text-white mb-3">
24
+ Welcome! 🎉
25
+ </h1>
26
+ <p className="text-gray-400 text-lg">
27
+ Your subscription is now active. Let&apos;s get you started building your SaaS.
28
+ </p>
29
+ </div>
30
+
31
+ {/* Next Steps */}
32
+ <div className="space-y-6 mb-8">
33
+ <h2 className="text-xl font-semibold text-white">Next Steps</h2>
34
+
35
+ {/* Step 1 */}
36
+ <div className="flex gap-4">
37
+ <div className="w-8 h-8 rounded-full bg-[#ff5722] flex items-center justify-center text-white text-sm font-semibold flex-shrink-0">
38
+ 1
39
+ </div>
40
+ <div className="flex-1">
41
+ <h3 className="text-white font-semibold mb-1">Authenticate the CLI</h3>
42
+ <p className="text-gray-400 text-sm mb-2">
43
+ Run this command in your terminal to authenticate:
44
+ </p>
45
+ <div className="bg-black/70 p-3 rounded-lg border border-[#2a2a2a]">
46
+ <code className="text-[#ff5722] font-mono text-sm">
47
+ npx your-cli login
48
+ </code>
49
+ </div>
50
+ </div>
51
+ </div>
52
+
53
+ {/* Step 2 */}
54
+ <div className="flex gap-4">
55
+ <div className="w-8 h-8 rounded-full bg-[#ff5722] flex items-center justify-center text-white text-sm font-semibold flex-shrink-0">
56
+ 2
57
+ </div>
58
+ <div className="flex-1">
59
+ <h3 className="text-white font-semibold mb-1">Create your first project</h3>
60
+ <p className="text-gray-400 text-sm mb-2">
61
+ Generate a complete SaaS application:
62
+ </p>
63
+ <div className="bg-black/70 p-3 rounded-lg border border-[#2a2a2a]">
64
+ <code className="text-[#ff5722] font-mono text-sm">
65
+ npx your-cli init my-app
66
+ </code>
67
+ </div>
68
+ </div>
69
+ </div>
70
+
71
+ {/* Step 3 */}
72
+ <div className="flex gap-4">
73
+ <div className="w-8 h-8 rounded-full bg-[#ff5722] flex items-center justify-center text-white text-sm font-semibold flex-shrink-0">
74
+ 3
75
+ </div>
76
+ <div className="flex-1">
77
+ <h3 className="text-white font-semibold mb-1">Start building</h3>
78
+ <p className="text-gray-400 text-sm">
79
+ Your project includes authentication, billing, dashboard, and more - all ready to customize and deploy.
80
+ </p>
81
+ </div>
82
+ </div>
83
+ </div>
84
+
85
+ {/* Action Buttons */}
86
+ <div className="grid grid-cols-1 sm:grid-cols-3 gap-3">
87
+ <Button
88
+ onClick={() => router.push("/dashboard")}
89
+ className="w-full bg-[#ff5722] hover:bg-[#d84315]"
90
+ >
91
+ <Zap className="w-4 h-4 mr-2" />
92
+ Go to Dashboard
93
+ </Button>
94
+ <Link href="/dashboard/cli" className="w-full">
95
+ <Button variant="outline" className="w-full border-[#2a2a2a] hover:bg-[#1a1a1a]">
96
+ <Terminal className="w-4 h-4 mr-2" />
97
+ CLI Guide
98
+ </Button>
99
+ </Link>
100
+ <Link href="/docs" className="w-full">
101
+ <Button variant="outline" className="w-full border-[#2a2a2a] hover:bg-[#1a1a1a]">
102
+ <BookOpen className="w-4 h-4 mr-2" />
103
+ Documentation
104
+ </Button>
105
+ </Link>
106
+ </div>
107
+
108
+ {/* Help Section */}
109
+ <div className="mt-8 pt-8 border-t border-[#2a2a2a] text-center">
110
+ <p className="text-gray-400 text-sm mb-2">
111
+ Need help getting started?
112
+ </p>
113
+ <Link href="mailto:support@yourdomain.com">
114
+ <Button variant="link" className="text-[#ff5722] hover:text-[#d84315]">
115
+ Contact Support
116
+ </Button>
117
+ </Link>
118
+ </div>
119
+ </CardContent>
120
+ </Card>
121
+ </div>
122
+ );
123
+ }