shipd 0.1.2 → 0.1.4

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 (115) hide show
  1. package/base-package/app/globals.css +126 -0
  2. package/base-package/app/layout.tsx +53 -0
  3. package/base-package/app/page.tsx +15 -0
  4. package/base-package/base.config.json +57 -0
  5. package/base-package/components/ui/avatar.tsx +53 -0
  6. package/base-package/components/ui/badge.tsx +46 -0
  7. package/base-package/components/ui/button.tsx +59 -0
  8. package/base-package/components/ui/card.tsx +92 -0
  9. package/base-package/components/ui/chart.tsx +353 -0
  10. package/base-package/components/ui/checkbox.tsx +32 -0
  11. package/base-package/components/ui/dialog.tsx +135 -0
  12. package/base-package/components/ui/dropdown-menu.tsx +257 -0
  13. package/base-package/components/ui/form.tsx +167 -0
  14. package/base-package/components/ui/input.tsx +21 -0
  15. package/base-package/components/ui/label.tsx +24 -0
  16. package/base-package/components/ui/progress.tsx +31 -0
  17. package/base-package/components/ui/resizable.tsx +56 -0
  18. package/base-package/components/ui/select.tsx +185 -0
  19. package/base-package/components/ui/separator.tsx +28 -0
  20. package/base-package/components/ui/sheet.tsx +139 -0
  21. package/base-package/components/ui/skeleton.tsx +13 -0
  22. package/base-package/components/ui/sonner.tsx +25 -0
  23. package/base-package/components/ui/switch.tsx +31 -0
  24. package/base-package/components/ui/tabs.tsx +66 -0
  25. package/base-package/components/ui/textarea.tsx +18 -0
  26. package/base-package/components/ui/toggle-group.tsx +73 -0
  27. package/base-package/components/ui/toggle.tsx +47 -0
  28. package/base-package/components/ui/tooltip.tsx +61 -0
  29. package/base-package/components.json +21 -0
  30. package/base-package/eslint.config.mjs +16 -0
  31. package/base-package/lib/utils.ts +6 -0
  32. package/base-package/middleware.ts +12 -0
  33. package/base-package/next.config.ts +27 -0
  34. package/base-package/package.json +49 -0
  35. package/base-package/postcss.config.mjs +5 -0
  36. package/base-package/public/favicon.svg +4 -0
  37. package/base-package/tailwind.config.ts +89 -0
  38. package/base-package/tsconfig.json +27 -0
  39. package/dist/index.js +1862 -948
  40. package/features/ai-chat/README.md +258 -0
  41. package/features/ai-chat/app/api/chat/route.ts +16 -0
  42. package/features/ai-chat/app/dashboard/_components/chatbot.tsx +39 -0
  43. package/features/ai-chat/app/dashboard/chat/page.tsx +73 -0
  44. package/features/ai-chat/feature.config.json +22 -0
  45. package/features/analytics/README.md +308 -0
  46. package/features/analytics/feature.config.json +20 -0
  47. package/features/analytics/lib/posthog.ts +36 -0
  48. package/features/auth/README.md +336 -0
  49. package/features/auth/app/api/auth/[...all]/route.ts +4 -0
  50. package/features/auth/app/dashboard/layout.tsx +15 -0
  51. package/features/auth/app/dashboard/page.tsx +140 -0
  52. package/features/auth/app/sign-in/page.tsx +228 -0
  53. package/features/auth/app/sign-up/page.tsx +243 -0
  54. package/features/auth/auth-schema.ts +47 -0
  55. package/features/auth/components/auth/setup-instructions.tsx +123 -0
  56. package/features/auth/feature.config.json +33 -0
  57. package/features/auth/lib/auth-client.ts +8 -0
  58. package/features/auth/lib/auth.ts +295 -0
  59. package/features/auth/lib/email-stub.ts +55 -0
  60. package/features/auth/lib/email.ts +47 -0
  61. package/features/auth/middleware.patch.ts +43 -0
  62. package/features/database/README.md +256 -0
  63. package/features/database/db/drizzle.ts +48 -0
  64. package/features/database/db/schema.ts +21 -0
  65. package/features/database/drizzle.config.ts +13 -0
  66. package/features/database/feature.config.json +30 -0
  67. package/features/email/README.md +282 -0
  68. package/features/email/emails/components/layout.tsx +181 -0
  69. package/features/email/emails/password-reset.tsx +67 -0
  70. package/features/email/emails/payment-failed.tsx +167 -0
  71. package/features/email/emails/subscription-confirmation.tsx +129 -0
  72. package/features/email/emails/welcome.tsx +100 -0
  73. package/features/email/feature.config.json +22 -0
  74. package/features/email/lib/email.ts +118 -0
  75. package/features/file-upload/README.md +271 -0
  76. package/features/file-upload/app/api/upload-image/route.ts +64 -0
  77. package/features/file-upload/app/dashboard/upload/page.tsx +324 -0
  78. package/features/file-upload/feature.config.json +23 -0
  79. package/features/file-upload/lib/upload-image.ts +28 -0
  80. package/features/marketing-landing/README.md +266 -0
  81. package/features/marketing-landing/app/page.tsx +25 -0
  82. package/features/marketing-landing/components/homepage/cli-workflow-section.tsx +231 -0
  83. package/features/marketing-landing/components/homepage/features-section.tsx +152 -0
  84. package/features/marketing-landing/components/homepage/footer.tsx +53 -0
  85. package/features/marketing-landing/components/homepage/hero-section.tsx +112 -0
  86. package/features/marketing-landing/components/homepage/integrations.tsx +124 -0
  87. package/features/marketing-landing/components/homepage/navigation.tsx +116 -0
  88. package/features/marketing-landing/components/homepage/news-section.tsx +82 -0
  89. package/features/marketing-landing/components/homepage/pricing-section.tsx +98 -0
  90. package/features/marketing-landing/components/homepage/testimonials-section.tsx +34 -0
  91. package/features/marketing-landing/components/logos/BetterAuth.tsx +21 -0
  92. package/features/marketing-landing/components/logos/NeonPostgres.tsx +41 -0
  93. package/features/marketing-landing/components/logos/Nextjs.tsx +72 -0
  94. package/features/marketing-landing/components/logos/Polar.tsx +7 -0
  95. package/features/marketing-landing/components/logos/TailwindCSS.tsx +27 -0
  96. package/features/marketing-landing/components/logos/index.ts +6 -0
  97. package/features/marketing-landing/components/logos/shadcnui.tsx +8 -0
  98. package/features/marketing-landing/feature.config.json +23 -0
  99. package/features/payments/README.md +306 -0
  100. package/features/payments/app/api/subscription/route.ts +25 -0
  101. package/features/payments/app/dashboard/payment/_components/manage-subscription.tsx +22 -0
  102. package/features/payments/app/dashboard/payment/page.tsx +126 -0
  103. package/features/payments/app/success/page.tsx +123 -0
  104. package/features/payments/feature.config.json +31 -0
  105. package/features/payments/lib/polar-products.ts +49 -0
  106. package/features/payments/lib/subscription.ts +148 -0
  107. package/features/payments/payments-schema.ts +30 -0
  108. package/features/seo/README.md +244 -0
  109. package/features/seo/app/blog/[slug]/page.tsx +314 -0
  110. package/features/seo/app/blog/page.tsx +107 -0
  111. package/features/seo/app/robots.txt +13 -0
  112. package/features/seo/app/sitemap.ts +70 -0
  113. package/features/seo/feature.config.json +19 -0
  114. package/features/seo/lib/seo-utils.ts +163 -0
  115. package/package.json +3 -1
@@ -0,0 +1,98 @@
1
+ "use client";
2
+
3
+ import { Badge } from "@/components/ui/badge";
4
+ import { Button } from "@/components/ui/button";
5
+ import {
6
+ Card,
7
+ CardContent,
8
+ CardDescription,
9
+ CardFooter,
10
+ CardHeader,
11
+ CardTitle,
12
+ } from "@/components/ui/card";
13
+ import { Check } from "lucide-react";
14
+
15
+ const plans = [
16
+ {
17
+ name: "Starter",
18
+ price: "$29",
19
+ interval: "month",
20
+ description: "Perfect to kick off your SaaS",
21
+ highlights: ["All core pages", "UI components", "Auth-ready"],
22
+ cta: "Get Starter",
23
+ featured: false,
24
+ },
25
+ {
26
+ name: "Pro",
27
+ price: "$99",
28
+ interval: "month",
29
+ description: "For teams shipping faster",
30
+ highlights: ["Everything in Starter", "Dashboard layout", "CLI + append"],
31
+ cta: "Go Pro",
32
+ featured: true,
33
+ },
34
+ ];
35
+
36
+ export default function PricingSection() {
37
+ return (
38
+ <section id="pricing" className="bg-black px-4 pb-24">
39
+ <div className="mx-auto max-w-5xl text-center">
40
+ <div className="mb-12 space-y-4">
41
+ <h2 className="text-4xl font-semibold bg-gradient-to-r from-white to-gray-400 bg-clip-text text-transparent">
42
+ Simple, transparent pricing
43
+ </h2>
44
+ <p className="text-gray-400 text-lg">
45
+ Choose a plan that fits your launch. Swap later as you grow.
46
+ </p>
47
+ </div>
48
+
49
+ <div className="grid gap-6 md:grid-cols-2">
50
+ {plans.map((plan) => (
51
+ <Card
52
+ key={plan.name}
53
+ className={`bg-[#0a0a0a] border-[#2a2a2a] hover:border-[#ff5722]/30 transition-all duration-300 ${
54
+ plan.featured ? "shadow-lg shadow-[#ff5722]/10" : ""
55
+ }`}
56
+ >
57
+ <CardHeader className="space-y-2">
58
+ <div className="flex items-center justify-between">
59
+ <CardTitle className="text-2xl text-white">{plan.name}</CardTitle>
60
+ {plan.featured && (
61
+ <Badge
62
+ variant="secondary"
63
+ className="bg-[#ff5722]/20 text-[#ff5722] border border-[#ff5722]/30"
64
+ >
65
+ Popular
66
+ </Badge>
67
+ )}
68
+ </div>
69
+ <CardDescription className="text-gray-400">
70
+ {plan.description}
71
+ </CardDescription>
72
+ <div className="mt-2">
73
+ <span className="text-4xl font-bold bg-gradient-to-r from-[#ff5722] to-[#ff7043] bg-clip-text text-transparent">
74
+ {plan.price}
75
+ </span>
76
+ <span className="text-gray-400">/{plan.interval}</span>
77
+ </div>
78
+ </CardHeader>
79
+ <CardContent className="space-y-3">
80
+ {plan.highlights.map((item) => (
81
+ <div key={item} className="flex items-center gap-3">
82
+ <Check className="h-5 w-5 text-[#ff5722]" />
83
+ <span className="text-gray-300">{item}</span>
84
+ </div>
85
+ ))}
86
+ </CardContent>
87
+ <CardFooter>
88
+ <Button className="w-full" variant={plan.featured ? "default" : "outline"}>
89
+ {plan.cta}
90
+ </Button>
91
+ </CardFooter>
92
+ </Card>
93
+ ))}
94
+ </div>
95
+ </div>
96
+ </section>
97
+ );
98
+ }
@@ -0,0 +1,34 @@
1
+ export default function TestimonialsSection() {
2
+ return (
3
+ <section className="py-20 px-6 lg:px-0 bg-gradient-to-b from-black via-[#0a0a0a] to-black">
4
+ <div className="mx-auto max-w-6xl">
5
+ <div className="text-center mb-16">
6
+ <h2 className="text-4xl font-bold mb-4 bg-gradient-to-r from-white to-gray-400 bg-clip-text text-transparent">
7
+ Built for Speed
8
+ </h2>
9
+ <p className="text-gray-400 text-xl max-w-2xl mx-auto">
10
+ Everything you need to launch your SaaS in minutes, not weeks
11
+ </p>
12
+ </div>
13
+
14
+ {/* Stats */}
15
+ <div className="flex flex-wrap items-center justify-center gap-8 text-center">
16
+ <div>
17
+ <p className="text-4xl font-bold bg-gradient-to-r from-[#ff5722] to-[#ff7043] bg-clip-text text-transparent">10+</p>
18
+ <p className="text-gray-400 mt-1">Pre-built Integrations</p>
19
+ </div>
20
+ <div className="h-12 w-px bg-[#2a2a2a] hidden sm:block" />
21
+ <div>
22
+ <p className="text-4xl font-bold bg-gradient-to-r from-[#ff5722] to-[#ff7043] bg-clip-text text-transparent">24+</p>
23
+ <p className="text-gray-400 mt-1">UI Components</p>
24
+ </div>
25
+ <div className="h-12 w-px bg-[#2a2a2a] hidden sm:block" />
26
+ <div>
27
+ <p className="text-4xl font-bold bg-gradient-to-r from-[#ff5722] to-[#ff7043] bg-clip-text text-transparent">5 Min</p>
28
+ <p className="text-gray-400 mt-1">Setup Time</p>
29
+ </div>
30
+ </div>
31
+ </div>
32
+ </section>
33
+ );
34
+ }
@@ -0,0 +1,21 @@
1
+ import * as React from "react";
2
+ import type { SVGProps } from "react";
3
+ const BetterAuth = (props: SVGProps<SVGSVGElement>) => (
4
+ <svg
5
+ xmlns="http://www.w3.org/2000/svg"
6
+ fill="none"
7
+ viewBox="0 0 500 500"
8
+ width="1em"
9
+ height="1em"
10
+ {...props}
11
+ >
12
+ <path fill="#fff" d="M0 0h500v500H0z" />
13
+ <path fill="#000" d="M69 121h86.988v259H69zM337.575 121H430v259h-92.425z" />
14
+ <path
15
+ fill="#000"
16
+ d="M427.282 121v83.456h-174.52V121zM430 296.544V380H252.762v-83.456z"
17
+ />
18
+ <path fill="#000" d="M252.762 204.455v92.089h-96.774v-92.089z" />
19
+ </svg>
20
+ );
21
+ export default BetterAuth;
@@ -0,0 +1,41 @@
1
+ import * as React from "react";
2
+ import type { SVGProps } from "react";
3
+ const Neon = (props: SVGProps<SVGSVGElement>) => (
4
+ <svg
5
+ viewBox="0 0 256 256"
6
+ xmlns="http://www.w3.org/2000/svg"
7
+ width="1em"
8
+ height="1em"
9
+ preserveAspectRatio="xMidYMid"
10
+ {...props}
11
+ >
12
+ <defs>
13
+ <linearGradient id="a" x1="100%" x2="12.069%" y1="100%" y2="0%">
14
+ <stop offset="0%" stopColor="#62F755" />
15
+ <stop offset="100%" stopColor="#8FF986" stopOpacity={0} />
16
+ </linearGradient>
17
+ <linearGradient id="b" x1="100%" x2="40.603%" y1="100%" y2="76.897%">
18
+ <stop offset="0%" stopOpacity={0.9} />
19
+ <stop offset="100%" stopColor="#1A1A1A" stopOpacity={0} />
20
+ </linearGradient>
21
+ </defs>
22
+ <path
23
+ fill="#00E0D9"
24
+ d="M0 44.139C0 19.762 19.762 0 44.139 0H211.86C236.238 0 256 19.762 256 44.139v142.649c0 25.216-31.915 36.16-47.388 16.256l-48.392-62.251v75.484c0 21.939-17.784 39.723-39.722 39.723h-76.36C19.763 256 0 236.238 0 211.861V44.14Zm44.139-8.825c-4.879 0-8.825 3.946-8.825 8.818v167.73c0 4.878 3.946 8.831 8.818 8.831h77.688c2.44 0 3.087-1.977 3.087-4.416v-101.22c0-25.222 31.914-36.166 47.395-16.255l48.391 62.243V44.14c0-4.879.455-8.825-4.416-8.825H44.14Z"
25
+ />
26
+ <path
27
+ fill="url(#a)"
28
+ d="M0 44.139C0 19.762 19.762 0 44.139 0H211.86C236.238 0 256 19.762 256 44.139v142.649c0 25.216-31.915 36.16-47.388 16.256l-48.392-62.251v75.484c0 21.939-17.784 39.723-39.722 39.723h-76.36C19.763 256 0 236.238 0 211.861V44.14Zm44.139-8.825c-4.879 0-8.825 3.946-8.825 8.818v167.73c0 4.878 3.946 8.831 8.818 8.831h77.688c2.44 0 3.087-1.977 3.087-4.416v-101.22c0-25.222 31.914-36.166 47.395-16.255l48.391 62.243V44.14c0-4.879.455-8.825-4.416-8.825H44.14Z"
29
+ />
30
+ <path
31
+ fill="url(#b)"
32
+ fillOpacity={0.4}
33
+ d="M0 44.139C0 19.762 19.762 0 44.139 0H211.86C236.238 0 256 19.762 256 44.139v142.649c0 25.216-31.915 36.16-47.388 16.256l-48.392-62.251v75.484c0 21.939-17.784 39.723-39.722 39.723h-76.36C19.763 256 0 236.238 0 211.861V44.14Zm44.139-8.825c-4.879 0-8.825 3.946-8.825 8.818v167.73c0 4.878 3.946 8.831 8.818 8.831h77.688c2.44 0 3.087-1.977 3.087-4.416v-101.22c0-25.222 31.914-36.166 47.395-16.255l48.391 62.243V44.14c0-4.879.455-8.825-4.416-8.825H44.14Z"
34
+ />
35
+ <path
36
+ fill="#63F655"
37
+ d="M211.861 0C236.238 0 256 19.762 256 44.139v142.649c0 25.216-31.915 36.16-47.388 16.256l-48.392-62.251v75.484c0 21.939-17.784 39.723-39.722 39.723a4.409 4.409 0 0 0 4.409-4.409V115.058c0-25.223 31.914-36.167 47.395-16.256l48.391 62.243V8.825c0-4.871-3.953-8.825-8.832-8.825Z"
38
+ />
39
+ </svg>
40
+ );
41
+ export default Neon;
@@ -0,0 +1,72 @@
1
+ import * as React from "react";
2
+ import type { SVGProps } from "react";
3
+ const Nextjs = (props: SVGProps<SVGSVGElement>) => (
4
+ <svg
5
+ width="1em"
6
+ height="1em"
7
+ viewBox="0 0 180 180"
8
+ fill="none"
9
+ xmlns="http://www.w3.org/2000/svg"
10
+ {...props}
11
+ >
12
+ <mask
13
+ id="mask0_408_139"
14
+ style={{
15
+ maskType: "alpha",
16
+ }}
17
+ maskUnits="userSpaceOnUse"
18
+ x={0}
19
+ y={0}
20
+ width={180}
21
+ height={180}
22
+ >
23
+ <circle cx={90} cy={90} r={90} fill="black" />
24
+ </mask>
25
+ <g mask="url(#mask0_408_139)">
26
+ <circle
27
+ cx={90}
28
+ cy={90}
29
+ r={87}
30
+ fill="black"
31
+ stroke="white"
32
+ strokeWidth={6}
33
+ />
34
+ <path
35
+ d="M149.508 157.52L69.142 54H54V125.97H66.1136V69.3836L139.999 164.845C143.333 162.614 146.509 160.165 149.508 157.52Z"
36
+ fill="url(#paint0_linear_408_139)"
37
+ />
38
+ <rect
39
+ x={115}
40
+ y={54}
41
+ width={12}
42
+ height={72}
43
+ fill="url(#paint1_linear_408_139)"
44
+ />
45
+ </g>
46
+ <defs>
47
+ <linearGradient
48
+ id="paint0_linear_408_139"
49
+ x1={109}
50
+ y1={116.5}
51
+ x2={144.5}
52
+ y2={160.5}
53
+ gradientUnits="userSpaceOnUse"
54
+ >
55
+ <stop stopColor="white" />
56
+ <stop offset={1} stopColor="white" stopOpacity={0} />
57
+ </linearGradient>
58
+ <linearGradient
59
+ id="paint1_linear_408_139"
60
+ x1={121}
61
+ y1={54}
62
+ x2={120.799}
63
+ y2={106.875}
64
+ gradientUnits="userSpaceOnUse"
65
+ >
66
+ <stop stopColor="white" />
67
+ <stop offset={1} stopColor="white" stopOpacity={0} />
68
+ </linearGradient>
69
+ </defs>
70
+ </svg>
71
+ );
72
+ export default Nextjs;
@@ -0,0 +1,7 @@
1
+ import Image from "next/image";
2
+
3
+ export default function Polar() {
4
+ return (
5
+ <Image src="/polar-sh.svg" alt="Polar Logo" width={100} height={100} />
6
+ );
7
+ }
@@ -0,0 +1,27 @@
1
+ import * as React from "react";
2
+ import type { SVGProps } from "react";
3
+ const TailwindCSS = (props: SVGProps<SVGSVGElement>) => (
4
+ <svg
5
+ xmlns="http://www.w3.org/2000/svg"
6
+ fill="none"
7
+ viewBox="0 0 54 33"
8
+ width="1em"
9
+ height="1em"
10
+ {...props}
11
+ >
12
+ <g clipPath="url(#a)">
13
+ <path
14
+ fill="#38bdf8"
15
+ fillRule="evenodd"
16
+ d="M27 0c-7.2 0-11.7 3.6-13.5 10.8 2.7-3.6 5.85-4.95 9.45-4.05 2.054.513 3.522 2.004 5.147 3.653C30.744 13.09 33.808 16.2 40.5 16.2c7.2 0 11.7-3.6 13.5-10.8-2.7 3.6-5.85 4.95-9.45 4.05-2.054-.513-3.522-2.004-5.147-3.653C36.756 3.11 33.692 0 27 0zM13.5 16.2C6.3 16.2 1.8 19.8 0 27c2.7-3.6 5.85-4.95 9.45-4.05 2.054.514 3.522 2.004 5.147 3.653C17.244 29.29 20.308 32.4 27 32.4c7.2 0 11.7-3.6 13.5-10.8-2.7 3.6-5.85 4.95-9.45 4.05-2.054-.513-3.522-2.004-5.147-3.653C23.256 19.31 20.192 16.2 13.5 16.2z"
17
+ clipRule="evenodd"
18
+ />
19
+ </g>
20
+ <defs>
21
+ <clipPath id="a">
22
+ <path fill="#fff" d="M0 0h54v32.4H0z" />
23
+ </clipPath>
24
+ </defs>
25
+ </svg>
26
+ );
27
+ export default TailwindCSS;
@@ -0,0 +1,6 @@
1
+ export { default as Nextjs } from "./Nextjs";
2
+ export { default as Polar } from "./Polar";
3
+ export { default as BetterAuth } from "./BetterAuth";
4
+ export { default as NeonPostgres } from "./NeonPostgres";
5
+ export { default as TailwindCSS } from "./TailwindCSS";
6
+ export { default as Shadcnui } from "./shadcnui";
@@ -0,0 +1,8 @@
1
+ import Image from "next/image";
2
+
3
+ const Shadcnui = () => {
4
+ return (
5
+ <Image src="/shadcn-ui.svg" alt="Shadcnui Logo" width={100} height={100} />
6
+ );
7
+ };
8
+ export default Shadcnui;
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "marketing-landing",
3
+ "version": "1.0.0",
4
+ "description": "Landing page module with hero, features, workflow, integrations, pricing, and footer",
5
+ "files": [
6
+ "app/page.tsx",
7
+ "components/homepage/navigation.tsx",
8
+ "components/homepage/hero-section.tsx",
9
+ "components/homepage/cli-workflow-section.tsx",
10
+ "components/homepage/features-section.tsx",
11
+ "components/homepage/testimonials-section.tsx",
12
+ "components/homepage/news-section.tsx",
13
+ "components/homepage/integrations.tsx",
14
+ "components/homepage/pricing-section.tsx",
15
+ "components/homepage/footer.tsx",
16
+ "components/logos/*"
17
+ ],
18
+ "dependencies": {},
19
+ "devDependencies": {},
20
+ "envVars": [],
21
+ "requires": [],
22
+ "conflicts": []
23
+ }
@@ -0,0 +1,306 @@
1
+ # Payments Module - Integration Guide
2
+
3
+ **Module Version:** 1.0.0
4
+ **Last Updated:** 2025-12-22
5
+ **Standalone:** ⚠️ Requires Auth + Database Modules
6
+
7
+ ---
8
+
9
+ ## Overview
10
+
11
+ This module adds complete subscription management and payment processing using Polar.sh. It includes subscription management pages, billing interfaces, webhook handling, and success pages.
12
+
13
+ **Key Features:**
14
+ - Polar.sh subscription integration
15
+ - Subscription management dashboard
16
+ - Customer portal access
17
+ - Webhook handling for subscription events
18
+ - Payment success page
19
+ - Subscription status tracking
20
+ - Product and pricing management
21
+
22
+ ---
23
+
24
+ ## Files Added
25
+
26
+ ### Pages/Routes
27
+ - `app/dashboard/payment/page.tsx` - Payment and subscription management page
28
+ - `app/success/page.tsx` - Success page after payment completion
29
+ - `app/api/subscription/route.ts` - Subscription API endpoint
30
+
31
+ ### Components
32
+ - `app/dashboard/payment/_components/manage-subscription.tsx` - Subscription management component
33
+
34
+ ### Utilities/Libraries
35
+ - `lib/subscription.ts` - Subscription utilities and helpers
36
+ - `lib/polar-products.ts` - Polar product fetching utilities
37
+ - `payments-schema.ts` - Subscription table schema (merged into db/schema.ts)
38
+
39
+ ---
40
+
41
+ ## Dependencies
42
+
43
+ ### Package Dependencies
44
+ The following packages will be added to `package.json`:
45
+ - `@polar-sh/sdk@^0.42.1` - Polar.sh SDK
46
+
47
+ ### Required Modules
48
+ - **Auth Module** - Payments requires authentication
49
+ - **Database Module** - Payments requires database for subscription storage
50
+
51
+ ### Included Components
52
+ This module uses UI components from the base package:
53
+ - ✅ `components/ui/button.tsx` - For action buttons
54
+ - ✅ `components/ui/card.tsx` - For subscription cards
55
+ - ✅ `components/ui/badge.tsx` - For status badges
56
+
57
+ ---
58
+
59
+ ## Environment Variables
60
+
61
+ Add these to your `.env.local`:
62
+
63
+ ```env
64
+ # Payments (Polar.sh)
65
+ POLAR_ACCESS_TOKEN="your-polar-access-token"
66
+ POLAR_WEBHOOK_SECRET="your-webhook-secret"
67
+ POLAR_SUCCESS_URL="success" # Path to success page (e.g., "success")
68
+ NEXT_PUBLIC_STARTER_TIER="your-product-id" # Product ID for starter tier
69
+ NEXT_PUBLIC_STARTER_SLUG="starter" # Product slug
70
+ NEXT_PUBLIC_APP_URL="http://localhost:3000" # Your app URL (for webhooks)
71
+ ```
72
+
73
+ **Required Variables:**
74
+ - `POLAR_ACCESS_TOKEN` - Your Polar.sh API access token
75
+ - `POLAR_WEBHOOK_SECRET` - Secret for webhook signature verification
76
+ - `NEXT_PUBLIC_STARTER_TIER` - Product ID from Polar.sh dashboard
77
+ - `NEXT_PUBLIC_STARTER_SLUG` - Product slug
78
+ - `NEXT_PUBLIC_APP_URL` - Your application URL (for webhook callbacks)
79
+
80
+ **Optional Variables:**
81
+ - `POLAR_SUCCESS_URL` - Custom success page path (defaults to "success")
82
+
83
+ **Where to get them:**
84
+ - **Polar.sh Dashboard**: [polar.sh](https://polar.sh) - Create account and products
85
+ - Get access token from API settings
86
+ - Create webhook secret for signature verification
87
+ - Create products and get product IDs
88
+
89
+ ---
90
+
91
+ ## Manual Integration Steps
92
+
93
+ If you're appending this module to an existing project, follow these steps:
94
+
95
+ ### Step 1: Install Dependencies
96
+
97
+ ```bash
98
+ npm install
99
+ # or
100
+ pnpm install
101
+ # or
102
+ yarn install
103
+ ```
104
+
105
+ The append command automatically adds missing dependencies to `package.json`, but you need to install them.
106
+
107
+ ### Step 2: Add Environment Variables
108
+
109
+ 1. Copy `.env.example` to `.env.local` (if not exists)
110
+ 2. Add the required environment variables listed above
111
+ 3. Get your Polar.sh credentials from the [Polar.sh dashboard](https://polar.sh)
112
+
113
+ ### Step 3: Update Database Schema
114
+
115
+ The payments module adds a subscription table. If you have the database module installed, the schema will be merged automatically. Otherwise:
116
+
117
+ 1. Add the subscription table to your `db/schema.ts`:
118
+ ```typescript
119
+ // Import from payments-schema.ts or copy the table definition
120
+ export { subscription } from '@/payments-schema';
121
+ ```
122
+
123
+ 2. Generate and run migrations:
124
+ ```bash
125
+ npm run db:generate
126
+ npm run db:push
127
+ ```
128
+
129
+ ### Step 4: Update Auth Configuration
130
+
131
+ The payments module integrates with the auth module's Polar webhook handling. The auth module already includes webhook code, but you need to ensure:
132
+
133
+ 1. `lib/auth.ts` includes Polar integration (already done if auth module is installed)
134
+ 2. Webhook endpoint is accessible at `/api/auth/callback/polar`
135
+ 3. Webhook secret matches your Polar.sh configuration
136
+
137
+ ### Step 5: Verify Installation
138
+
139
+ 1. Start your dev server: `npm run dev`
140
+ 2. Visit `http://localhost:3000/dashboard/payment` to see subscription management
141
+ 3. Visit `http://localhost:3000/success` to see the success page
142
+ 4. Test the subscription API: `GET /api/subscription`
143
+
144
+ ---
145
+
146
+ ## Usage Examples
147
+
148
+ ### Checking Subscription Status
149
+
150
+ ```typescript
151
+ import { getSubscriptionDetails, hasActiveSubscription } from "@/lib/subscription";
152
+
153
+ // Get full subscription details
154
+ const details = await getSubscriptionDetails();
155
+ if (details.hasSubscription && details.subscription) {
156
+ console.log("Status:", details.subscription.status);
157
+ console.log("Amount:", details.subscription.amount);
158
+ }
159
+
160
+ // Quick check for active subscription
161
+ const isActive = await hasActiveSubscription();
162
+ ```
163
+
164
+ ### Opening Customer Portal
165
+
166
+ ```typescript
167
+ "use client";
168
+
169
+ import { authClient } from "@/lib/auth-client";
170
+
171
+ export function ManageSubscriptionButton() {
172
+ const handleOpenPortal = async () => {
173
+ try {
174
+ await authClient.customer.portal();
175
+ } catch (error) {
176
+ console.error("Failed to open portal:", error);
177
+ }
178
+ };
179
+
180
+ return <button onClick={handleOpenPortal}>Manage Subscription</button>;
181
+ }
182
+ ```
183
+
184
+ ### Creating Checkout Session
185
+
186
+ ```typescript
187
+ "use client";
188
+
189
+ import { authClient } from "@/lib/auth-client";
190
+
191
+ export function SubscribeButton({ productId }: { productId: string }) {
192
+ const handleSubscribe = async () => {
193
+ try {
194
+ await authClient.checkout({
195
+ productId,
196
+ successUrl: `${window.location.origin}/success`,
197
+ });
198
+ } catch (error) {
199
+ console.error("Checkout failed:", error);
200
+ }
201
+ };
202
+
203
+ return <button onClick={handleSubscribe}>Subscribe</button>;
204
+ }
205
+ ```
206
+
207
+ ---
208
+
209
+ ## Customization
210
+
211
+ ### Styling
212
+ - Payment pages use Tailwind CSS classes
213
+ - Customize colors in `tailwind.config.ts`
214
+ - Modify page layouts in `app/dashboard/payment/page.tsx`
215
+
216
+ ### Configuration
217
+ - Product IDs are configured via environment variables
218
+ - Webhook handling is in `lib/auth.ts` (auth module)
219
+ - Customize success page in `app/success/page.tsx`
220
+
221
+ ### Subscription Management
222
+ - Customize subscription display in `app/dashboard/payment/page.tsx`
223
+ - Add custom subscription actions in `_components/manage-subscription.tsx`
224
+
225
+ ---
226
+
227
+ ## Integration Points
228
+
229
+ ### Files That May Need Manual Updates
230
+
231
+ **lib/auth.ts** (if auth module installed):
232
+ - Polar webhook handling is already included
233
+ - Ensure webhook secret matches your Polar.sh configuration
234
+
235
+ **db/schema.ts** (if database module installed):
236
+ - Subscription table will be automatically merged
237
+ - If manual merge needed, import from `payments-schema.ts`
238
+
239
+ **Middleware** (if auth module installed):
240
+ - No changes needed - payments uses existing auth protection
241
+
242
+ ---
243
+
244
+ ## Troubleshooting
245
+
246
+ ### Common Issues
247
+
248
+ **Issue:** "Subscription table not found" error
249
+ **Solution:**
250
+ - Ensure database module is installed
251
+ - Run `npm run db:push` to create tables
252
+ - Verify subscription table exists in `db/schema.ts`
253
+
254
+ **Issue:** Webhooks not working
255
+ **Solution:**
256
+ - Verify `POLAR_WEBHOOK_SECRET` matches Polar.sh dashboard
257
+ - Check webhook URL is correct: `https://yourdomain.com/api/auth/callback/polar`
258
+ - Ensure webhook events are enabled in Polar.sh dashboard
259
+
260
+ **Issue:** "POLAR_ACCESS_TOKEN is required"
261
+ **Solution:**
262
+ - Add `POLAR_ACCESS_TOKEN` to `.env.local`
263
+ - Get token from Polar.sh API settings
264
+ - Restart dev server after adding env vars
265
+
266
+ **Issue:** Checkout not redirecting
267
+ **Solution:**
268
+ - Verify `NEXT_PUBLIC_APP_URL` is set correctly
269
+ - Check `POLAR_SUCCESS_URL` matches your success page path
270
+ - Ensure product IDs are correct
271
+
272
+ ---
273
+
274
+ ## Next Steps
275
+
276
+ After installing this module:
277
+
278
+ 1. Set up Polar.sh account and create products
279
+ 2. Configure environment variables
280
+ 3. Run database migrations
281
+ 4. Test checkout flow
282
+ 5. Configure webhooks in Polar.sh dashboard
283
+ 6. Customize success page
284
+ 7. Add pricing page (optional - can use marketing landing pricing section)
285
+
286
+ ---
287
+
288
+ ## Related Modules
289
+
290
+ This module requires:
291
+ - **Auth Module** - For user authentication and webhook handling
292
+ - **Database Module** - For subscription storage
293
+
294
+ This module works well with:
295
+ - **Email Module** - For subscription confirmation emails
296
+ - **Marketing Landing Module** - For pricing page display
297
+
298
+ ---
299
+
300
+ ## Module Status
301
+
302
+ ✅ **Core Files Included** - All payment pages and utilities
303
+ ⚠️ **Requires Auth + Database** - Must be installed first
304
+ ✅ **Webhook Integration** - Works with auth module's webhook handler
305
+ ✅ **Well Documented** - Comprehensive integration guide
306
+
@@ -0,0 +1,25 @@
1
+ import { auth } from "@/lib/auth";
2
+ import { getSubscriptionDetails } from "@/lib/subscription";
3
+ import { headers } from "next/headers";
4
+ import { NextResponse } from "next/server";
5
+
6
+ export async function GET() {
7
+ try {
8
+ const result = await auth.api.getSession({
9
+ headers: await headers(),
10
+ });
11
+
12
+ if (!result?.session?.userId) {
13
+ return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
14
+ }
15
+
16
+ const subscriptionDetails = await getSubscriptionDetails();
17
+ return NextResponse.json(subscriptionDetails);
18
+ } catch (error) {
19
+ console.error("Error fetching subscription details:", error);
20
+ return NextResponse.json(
21
+ { error: "Failed to fetch subscription details" },
22
+ { status: 500 }
23
+ );
24
+ }
25
+ }