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,45 @@
1
+ # Environment Variables
2
+ # Copy this file to .env.local and customize the values
3
+
4
+ # ⚠️ REQUIRED FOR BASIC FUNCTIONALITY:
5
+ # - DATABASE_URL (for data storage)
6
+ # - BETTER_AUTH_SECRET (for authentication)
7
+ # - GOOGLE_CLIENT_ID & GOOGLE_CLIENT_SECRET (for Google login)
8
+
9
+ # ℹ️ OPTIONAL SERVICES:
10
+ # - POLAR_* variables (only needed for subscription payments)
11
+ # - RESEND_API_KEY (only needed for transactional emails)
12
+ # - OPENAI_API_KEY (only needed for AI chat features)
13
+ # - R2_* variables (only needed for file uploads)
14
+ # - POSTHOG_* variables (only needed for analytics)
15
+
16
+ # The app will launch with these placeholder values, but configure real services for production
17
+
18
+ # Application
19
+ NEXT_PUBLIC_APP_URL=http://localhost:3000
20
+
21
+ # Auth (Required)
22
+ BETTER_AUTH_SECRET=please-change-this-to-a-random-32-character-string-or-longer
23
+ GOOGLE_CLIENT_ID=your-google-client-id.apps.googleusercontent.com
24
+ GOOGLE_CLIENT_SECRET=your-google-client-secret
25
+
26
+ # Database (Required)
27
+ DATABASE_URL=postgresql://user:password@localhost:5432/mydb
28
+
29
+ # Payments (Optional - only needed if using this feature)
30
+ # Get your access token from https://polar.sh/dashboard/settings/api
31
+ # Required scopes: subscriptions:read, products:read, customers:read, checkouts:write, orders:read
32
+ POLAR_ACCESS_TOKEN=your-polar-access-token
33
+ POLAR_SUCCESS_URL=success
34
+ POLAR_WEBHOOK_SECRET=your-polar-webhook-secret
35
+ NEXT_PUBLIC_STARTER_TIER=your-starter-tier-id
36
+ NEXT_PUBLIC_STARTER_SLUG=your-organization-slug
37
+
38
+ # Email (Optional - only needed if using this feature)
39
+ # Get your API key from https://resend.com/api-keys
40
+ RESEND_API_KEY=re_your-resend-api-key
41
+ EMAIL_FROM=SaaS Scaffold <noreply@yourdomain.com>
42
+
43
+ # Analytics (Optional - only needed if using this feature)
44
+ NEXT_PUBLIC_POSTHOG_KEY=phc_your-posthog-project-key
45
+ NEXT_PUBLIC_POSTHOG_HOST=https://app.posthog.com
@@ -0,0 +1,239 @@
1
+ # {{PROJECT_NAME}}
2
+
3
+ {{PROJECT_DESCRIPTION}}
4
+
5
+ ## ✨ Features
6
+
7
+ ### 🔐 Authentication & User Management
8
+ - **Better Auth v1.2.8** - Modern authentication system
9
+ - Google OAuth integration
10
+ - Session management with database persistence
11
+ - User profile management with image uploads
12
+ - Account linking for multiple providers
13
+
14
+ ### 💳 Subscription & Billing
15
+ - **Polar.sh** integration for subscription management
16
+ - Two-tier pricing: Starter ($99/month) & Professional ($499/month)
17
+ - Real-time webhook processing
18
+ - Customer portal for self-service billing
19
+ - Subscription status tracking (active, canceled, expired)
20
+ - Payment gating with elegant overlays
21
+
22
+ ### 🤖 AI Integration
23
+ - **OpenAI** powered chatbot
24
+ - React Markdown rendering for rich responses
25
+ - Multi-step conversation support
26
+ - Integrated chat widget in dashboard
27
+
28
+ ### 🎨 Modern UI/UX
29
+ - **Tailwind CSS v4** - Latest utility-first styling
30
+ - **shadcn/ui** components - Accessible, customizable
31
+ - **Radix UI** primitives - Unstyled, accessible components
32
+ - Dark/light theme support with smooth transitions
33
+ - Responsive design with mobile-first approach
34
+ - Loading skeletons and optimistic UI updates
35
+
36
+ ### 🗄️ Database & Storage
37
+ - **Neon PostgreSQL** - Serverless database
38
+ - **Drizzle ORM** - Type-safe database toolkit
39
+ - **Cloudflare R2** - Scalable file storage with zero egress fees
40
+ - Database migrations with Drizzle Kit
41
+ - Drag & drop file uploads with progress tracking
42
+
43
+ ### 📊 Analytics & Monitoring
44
+ - **PostHog** integration for product analytics
45
+ - User behavior tracking
46
+ - Custom event monitoring
47
+ - Error tracking and insights
48
+
49
+ ## 🚀 Tech Stack
50
+
51
+ - **Framework**: Next.js 15.3.1 with App Router
52
+ - **Language**: TypeScript with strict mode
53
+ - **Styling**: Tailwind CSS v4 + shadcn/ui
54
+ - **Database**: Neon PostgreSQL + Drizzle ORM
55
+ - **Authentication**: Better Auth v1.2.8
56
+ - **Payments**: Polar.sh
57
+ - **AI**: OpenAI SDK
58
+ - **Storage**: Cloudflare R2
59
+ - **Analytics**: PostHog
60
+ - **Deployment**: Vercel (recommended)
61
+
62
+ ## 📁 Project Structure
63
+
64
+ ```
65
+ ├── app/
66
+ │ ├── (auth)/ # Authentication pages
67
+ │ ├── dashboard/ # Protected dashboard area
68
+ │ │ ├── _components/ # Dashboard components
69
+ │ │ ├── chat/ # AI chat interface
70
+ │ │ ├── upload/ # File upload with R2
71
+ │ │ ├── payment/ # Subscription management
72
+ │ │ └── settings/ # User settings & billing
73
+ │ ├── pricing/ # Public pricing page
74
+ │ └── api/ # API routes
75
+ ├── components/
76
+ │ ├── ui/ # shadcn/ui components
77
+ │ └── homepage/ # Landing page sections
78
+ ├── lib/
79
+ │ ├── auth/ # Authentication config
80
+ │ ├── subscription.ts # Subscription utilities
81
+ │ └── upload-image.ts # R2 file upload utilities
82
+ └── db/
83
+ ├── schema.ts # Database schema
84
+ └── drizzle.ts # Database connection
85
+ ```
86
+
87
+ ## 🛠️ Quick Start
88
+
89
+ ### Prerequisites
90
+ - Node.js 18+
91
+ - PostgreSQL database (Neon recommended)
92
+ - Cloudflare R2 bucket for file storage
93
+ - Polar.sh account for subscriptions
94
+ - OpenAI API key for AI features
95
+ - Google OAuth credentials (optional)
96
+
97
+ ### Installation
98
+
99
+ 1. **Clone the repository**
100
+ ```bash
101
+ git clone <repository-url>
102
+ cd {{PROJECT_NAME}}
103
+ ```
104
+
105
+ 2. **Install dependencies**
106
+ ```bash
107
+ npm install
108
+ ```
109
+
110
+ 3. **Environment Setup**
111
+ Create a `.env.local` file with:
112
+ ```env
113
+ # Database
114
+ DATABASE_URL="your-neon-database-url"
115
+
116
+ # Authentication
117
+ BETTER_AUTH_SECRET="your-secret-key"
118
+ GOOGLE_CLIENT_ID="your-google-client-id"
119
+ GOOGLE_CLIENT_SECRET="your-google-client-secret"
120
+
121
+ # Polar.sh
122
+ POLAR_ACCESS_TOKEN="your-polar-access-token"
123
+ POLAR_WEBHOOK_SECRET="your-webhook-secret"
124
+
125
+ # OpenAI
126
+ OPENAI_API_KEY="your-openai-api-key"
127
+
128
+ # Cloudflare R2 Storage
129
+ CLOUDFLARE_ACCOUNT_ID="your-cloudflare-account-id"
130
+ R2_UPLOAD_IMAGE_ACCESS_KEY_ID="your-r2-access-key-id"
131
+ R2_UPLOAD_IMAGE_SECRET_ACCESS_KEY="your-r2-secret-access-key"
132
+ R2_UPLOAD_IMAGE_BUCKET_NAME="your-r2-bucket-name"
133
+
134
+ # Polar.sh Pricing Tiers
135
+ NEXT_PUBLIC_STARTER_TIER="your-starter-product-id"
136
+ NEXT_PUBLIC_STARTER_SLUG="your-starter-slug"
137
+ ```
138
+
139
+ 4. **Database Setup**
140
+ ```bash
141
+ # Generate and run migrations
142
+ npx drizzle-kit generate
143
+ npx drizzle-kit push
144
+ ```
145
+
146
+ 5. **Cloudflare R2 Setup**
147
+ - Create a Cloudflare account and set up R2 storage
148
+ - Create a bucket for file uploads
149
+ - Generate API tokens with R2 permissions
150
+ - Configure CORS settings for your domain
151
+
152
+ 6. **Polar.sh Setup**
153
+ - Create products for your pricing tiers
154
+ - Set up webhook endpoints for subscription events
155
+ - Configure your pricing structure
156
+
157
+ 7. **Start Development Server**
158
+ ```bash
159
+ npm run dev
160
+ ```
161
+
162
+ Open [http://localhost:3000](http://localhost:3000) to see your application.
163
+
164
+ ## 🎯 Key Features Explained
165
+
166
+ ### Subscription Management
167
+ - Automatic subscription status checking
168
+ - Payment gating for premium features
169
+ - Integration with Polar.sh customer portal
170
+ - Webhook handling for real-time updates
171
+
172
+ ### AI Chat Integration
173
+ - Built-in chatbot with OpenAI
174
+ - Markdown rendering for rich responses
175
+ - Conversation history and context
176
+
177
+ ### File Upload System
178
+ - **Cloudflare R2 integration** with S3-compatible API
179
+ - **Drag & drop interface** with visual feedback
180
+ - **File validation** - Type checking and size limits
181
+ - **Progress tracking** - Real-time upload progress
182
+ - **Image gallery** - View uploaded files with metadata
183
+ - **Copy URLs** - Easy sharing and integration
184
+
185
+ ### Analytics & Tracking
186
+ - PostHog event tracking
187
+ - User behavior monitoring
188
+ - Custom analytics dashboard
189
+
190
+ ## 🔧 Customization
191
+
192
+ ### Adding New Features
193
+ 1. Create components in `components/`
194
+ 2. Add API routes in `app/api/`
195
+ 3. Update database schema in `db/schema.ts`
196
+ 4. Run `npx drizzle-kit generate` and `npx drizzle-kit push`
197
+
198
+ ### Styling
199
+ - Modify `app/globals.css` for global styles
200
+ - Use Tailwind classes for component styling
201
+ - Customize theme in `tailwind.config.ts`
202
+
203
+ ### Authentication
204
+ - Configure providers in `lib/auth/auth.ts`
205
+ - Add new OAuth providers as needed
206
+ - Customize user profile fields in database schema
207
+
208
+ ## 📚 Learn More
209
+
210
+ - [Next.js Documentation](https://nextjs.org/docs)
211
+ - [Better Auth Documentation](https://better-auth.com)
212
+ - [Polar.sh Documentation](https://docs.polar.sh)
213
+ - [Drizzle ORM Documentation](https://orm.drizzle.team)
214
+ - [Tailwind CSS Documentation](https://tailwindcss.com/docs)
215
+
216
+ ## 🚀 Deployment
217
+
218
+ ### Vercel (Recommended)
219
+ 1. Connect your GitHub repository to Vercel
220
+ 2. Add environment variables in Vercel dashboard
221
+ 3. Deploy automatically on every push
222
+
223
+ ### Manual Deployment
224
+ ```bash
225
+ npm run build
226
+ npm start
227
+ ```
228
+
229
+ ## 📄 License
230
+
231
+ This project is licensed under the MIT License.
232
+
233
+ ## 🤝 Contributing
234
+
235
+ Contributions are welcome! Please feel free to submit a Pull Request.
236
+
237
+ ---
238
+
239
+ Built with ❤️ using Next.js and modern web technologies.
@@ -0,0 +1,4 @@
1
+ import { auth } from "@/lib/auth"; // path to your auth file
2
+ import { toNextJsHandler } from "better-auth/next-js";
3
+
4
+ export const { POST, GET } = toNextJsHandler(auth);
@@ -0,0 +1,16 @@
1
+ import { openai } from "@ai-sdk/openai";
2
+ import { streamText } from "ai";
3
+
4
+ export async function POST(req: Request) {
5
+ const { messages } = await req.json();
6
+
7
+ const result = streamText({
8
+ model: openai.responses("gpt-4o"),
9
+ messages,
10
+ tools: {
11
+ web_search_preview: openai.tools.webSearchPreview(),
12
+ },
13
+ });
14
+
15
+ return result.toDataStreamResponse();
16
+ }
@@ -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
+ }
@@ -0,0 +1,64 @@
1
+ import { uploadImageAssets } from "@/lib/upload-image";
2
+ import { NextRequest, NextResponse } from "next/server";
3
+
4
+ export const config = {
5
+ api: { bodyParser: false }, // Disable default body parsing
6
+ };
7
+
8
+ export async function POST(req: NextRequest) {
9
+ try {
10
+ // Parse the form data
11
+ const formData = await req.formData();
12
+ const file = formData.get("file") as File | null;
13
+
14
+ if (!file) {
15
+ return NextResponse.json({ error: "No file provided" }, { status: 400 });
16
+ }
17
+
18
+ // Validate MIME type - only allow image files
19
+ const allowedMimeTypes = [
20
+ "image/jpeg",
21
+ "image/jpg",
22
+ "image/png",
23
+ "image/gif",
24
+ "image/webp",
25
+ "image/svg+xml",
26
+ ];
27
+
28
+ if (!allowedMimeTypes.includes(file.type)) {
29
+ return NextResponse.json(
30
+ { error: "Invalid file type. Only image files are allowed." },
31
+ { status: 400 },
32
+ );
33
+ }
34
+
35
+ // Validate file size - limit to 10MB
36
+ const maxSizeInBytes = 10 * 1024 * 1024; // 10MB
37
+ if (file.size > maxSizeInBytes) {
38
+ return NextResponse.json(
39
+ { error: "File too large. Maximum size allowed is 10MB." },
40
+ { status: 400 },
41
+ );
42
+ }
43
+
44
+ // Convert file to buffer
45
+ const arrayBuffer = await file.arrayBuffer();
46
+ const buffer = Buffer.from(arrayBuffer);
47
+
48
+ // Generate a unique filename with original extension
49
+ const fileExt = file.name.split(".").pop() || "";
50
+ const timestamp = Date.now();
51
+ const filename = `upload-${timestamp}.${fileExt || "png"}`;
52
+
53
+ // Upload the file
54
+ const url = await uploadImageAssets(buffer, filename);
55
+
56
+ return NextResponse.json({ url });
57
+ } catch (error) {
58
+ console.error("Upload error:", error);
59
+ return NextResponse.json(
60
+ { error: "Failed to process upload" },
61
+ { status: 500 },
62
+ );
63
+ }
64
+ }