shipd 0.1.3 → 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.
- package/base-package/app/globals.css +126 -0
- package/base-package/app/layout.tsx +53 -0
- package/base-package/app/page.tsx +15 -0
- package/base-package/base.config.json +57 -0
- package/base-package/components/ui/avatar.tsx +53 -0
- package/base-package/components/ui/badge.tsx +46 -0
- package/base-package/components/ui/button.tsx +59 -0
- package/base-package/components/ui/card.tsx +92 -0
- package/base-package/components/ui/chart.tsx +353 -0
- package/base-package/components/ui/checkbox.tsx +32 -0
- package/base-package/components/ui/dialog.tsx +135 -0
- package/base-package/components/ui/dropdown-menu.tsx +257 -0
- package/base-package/components/ui/form.tsx +167 -0
- package/base-package/components/ui/input.tsx +21 -0
- package/base-package/components/ui/label.tsx +24 -0
- package/base-package/components/ui/progress.tsx +31 -0
- package/base-package/components/ui/resizable.tsx +56 -0
- package/base-package/components/ui/select.tsx +185 -0
- package/base-package/components/ui/separator.tsx +28 -0
- package/base-package/components/ui/sheet.tsx +139 -0
- package/base-package/components/ui/skeleton.tsx +13 -0
- package/base-package/components/ui/sonner.tsx +25 -0
- package/base-package/components/ui/switch.tsx +31 -0
- package/base-package/components/ui/tabs.tsx +66 -0
- package/base-package/components/ui/textarea.tsx +18 -0
- package/base-package/components/ui/toggle-group.tsx +73 -0
- package/base-package/components/ui/toggle.tsx +47 -0
- package/base-package/components/ui/tooltip.tsx +61 -0
- package/base-package/components.json +21 -0
- package/base-package/eslint.config.mjs +16 -0
- package/base-package/lib/utils.ts +6 -0
- package/base-package/middleware.ts +12 -0
- package/base-package/next.config.ts +27 -0
- package/base-package/package.json +49 -0
- package/base-package/postcss.config.mjs +5 -0
- package/base-package/public/favicon.svg +4 -0
- package/base-package/tailwind.config.ts +89 -0
- package/base-package/tsconfig.json +27 -0
- package/dist/index.js +1858 -956
- package/features/ai-chat/README.md +258 -0
- package/features/ai-chat/app/api/chat/route.ts +16 -0
- package/features/ai-chat/app/dashboard/_components/chatbot.tsx +39 -0
- package/features/ai-chat/app/dashboard/chat/page.tsx +73 -0
- package/features/ai-chat/feature.config.json +22 -0
- package/features/analytics/README.md +308 -0
- package/features/analytics/feature.config.json +20 -0
- package/features/analytics/lib/posthog.ts +36 -0
- package/features/auth/README.md +336 -0
- package/features/auth/app/api/auth/[...all]/route.ts +4 -0
- package/features/auth/app/dashboard/layout.tsx +15 -0
- package/features/auth/app/dashboard/page.tsx +140 -0
- package/features/auth/app/sign-in/page.tsx +228 -0
- package/features/auth/app/sign-up/page.tsx +243 -0
- package/features/auth/auth-schema.ts +47 -0
- package/features/auth/components/auth/setup-instructions.tsx +123 -0
- package/features/auth/feature.config.json +33 -0
- package/features/auth/lib/auth-client.ts +8 -0
- package/features/auth/lib/auth.ts +295 -0
- package/features/auth/lib/email-stub.ts +55 -0
- package/features/auth/lib/email.ts +47 -0
- package/features/auth/middleware.patch.ts +43 -0
- package/features/database/README.md +256 -0
- package/features/database/db/drizzle.ts +48 -0
- package/features/database/db/schema.ts +21 -0
- package/features/database/drizzle.config.ts +13 -0
- package/features/database/feature.config.json +30 -0
- package/features/email/README.md +282 -0
- package/features/email/emails/components/layout.tsx +181 -0
- package/features/email/emails/password-reset.tsx +67 -0
- package/features/email/emails/payment-failed.tsx +167 -0
- package/features/email/emails/subscription-confirmation.tsx +129 -0
- package/features/email/emails/welcome.tsx +100 -0
- package/features/email/feature.config.json +22 -0
- package/features/email/lib/email.ts +118 -0
- package/features/file-upload/README.md +271 -0
- package/features/file-upload/app/api/upload-image/route.ts +64 -0
- package/features/file-upload/app/dashboard/upload/page.tsx +324 -0
- package/features/file-upload/feature.config.json +23 -0
- package/features/file-upload/lib/upload-image.ts +28 -0
- package/features/marketing-landing/README.md +266 -0
- package/features/marketing-landing/app/page.tsx +25 -0
- package/features/marketing-landing/components/homepage/cli-workflow-section.tsx +231 -0
- package/features/marketing-landing/components/homepage/features-section.tsx +152 -0
- package/features/marketing-landing/components/homepage/footer.tsx +53 -0
- package/features/marketing-landing/components/homepage/hero-section.tsx +112 -0
- package/features/marketing-landing/components/homepage/integrations.tsx +124 -0
- package/features/marketing-landing/components/homepage/navigation.tsx +116 -0
- package/features/marketing-landing/components/homepage/news-section.tsx +82 -0
- package/features/marketing-landing/components/homepage/pricing-section.tsx +98 -0
- package/features/marketing-landing/components/homepage/testimonials-section.tsx +34 -0
- package/features/marketing-landing/components/logos/BetterAuth.tsx +21 -0
- package/features/marketing-landing/components/logos/NeonPostgres.tsx +41 -0
- package/features/marketing-landing/components/logos/Nextjs.tsx +72 -0
- package/features/marketing-landing/components/logos/Polar.tsx +7 -0
- package/features/marketing-landing/components/logos/TailwindCSS.tsx +27 -0
- package/features/marketing-landing/components/logos/index.ts +6 -0
- package/features/marketing-landing/components/logos/shadcnui.tsx +8 -0
- package/features/marketing-landing/feature.config.json +23 -0
- package/features/payments/README.md +306 -0
- package/features/payments/app/api/subscription/route.ts +25 -0
- package/features/payments/app/dashboard/payment/_components/manage-subscription.tsx +22 -0
- package/features/payments/app/dashboard/payment/page.tsx +126 -0
- package/features/payments/app/success/page.tsx +123 -0
- package/features/payments/feature.config.json +31 -0
- package/features/payments/lib/polar-products.ts +49 -0
- package/features/payments/lib/subscription.ts +148 -0
- package/features/payments/payments-schema.ts +30 -0
- package/features/seo/README.md +244 -0
- package/features/seo/app/blog/[slug]/page.tsx +314 -0
- package/features/seo/app/blog/page.tsx +107 -0
- package/features/seo/app/robots.txt +13 -0
- package/features/seo/app/sitemap.ts +70 -0
- package/features/seo/feature.config.json +19 -0
- package/features/seo/lib/seo-utils.ts +163 -0
- package/package.json +3 -1
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "analytics",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "PostHog analytics integration with event tracking and feature flags",
|
|
5
|
+
"dependencies": {
|
|
6
|
+
"posthog-js": "^1.248.1",
|
|
7
|
+
"posthog-node": "^4.18.0"
|
|
8
|
+
},
|
|
9
|
+
"devDependencies": {},
|
|
10
|
+
"envVars": [
|
|
11
|
+
"NEXT_PUBLIC_POSTHOG_KEY",
|
|
12
|
+
"NEXT_PUBLIC_POSTHOG_HOST"
|
|
13
|
+
],
|
|
14
|
+
"files": [
|
|
15
|
+
"lib/posthog.ts"
|
|
16
|
+
],
|
|
17
|
+
"requires": [],
|
|
18
|
+
"conflicts": []
|
|
19
|
+
}
|
|
20
|
+
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import posthog from 'posthog-js';
|
|
4
|
+
import { PostHogProvider } from 'posthog-js/react';
|
|
5
|
+
import { useEffect } from 'react';
|
|
6
|
+
|
|
7
|
+
if (typeof window !== 'undefined') {
|
|
8
|
+
const posthogKey = process.env.NEXT_PUBLIC_POSTHOG_KEY;
|
|
9
|
+
const posthogHost = process.env.NEXT_PUBLIC_POSTHOG_HOST || 'https://app.posthog.com';
|
|
10
|
+
|
|
11
|
+
if (posthogKey) {
|
|
12
|
+
posthog.init(posthogKey, {
|
|
13
|
+
api_host: posthogHost,
|
|
14
|
+
person_profiles: 'identified_only', // or 'always' to create profiles for anonymous users as well
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function PostHogProviderWrapper({ children }: { children: React.ReactNode }) {
|
|
20
|
+
useEffect(() => {
|
|
21
|
+
// Track pageviews
|
|
22
|
+
const handleRouteChange = () => {
|
|
23
|
+
posthog?.capture('$pageview');
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
// Track initial pageview
|
|
27
|
+
handleRouteChange();
|
|
28
|
+
|
|
29
|
+
return () => {
|
|
30
|
+
// Cleanup if needed
|
|
31
|
+
};
|
|
32
|
+
}, []);
|
|
33
|
+
|
|
34
|
+
return <PostHogProvider client={posthog}>{children}</PostHogProvider>;
|
|
35
|
+
}
|
|
36
|
+
|
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
# Authentication Module - Integration Guide
|
|
2
|
+
|
|
3
|
+
**Module Version:** 1.0.0
|
|
4
|
+
**Last Updated:** 2025-12-22
|
|
5
|
+
**Standalone:** ⚠️ Requires Database Module
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Overview
|
|
10
|
+
|
|
11
|
+
This module adds complete authentication functionality to your Next.js application using Better Auth. It includes email/password authentication, Google OAuth, session management, and route protection.
|
|
12
|
+
|
|
13
|
+
**Key Features:**
|
|
14
|
+
- Email/password authentication
|
|
15
|
+
- Google OAuth integration
|
|
16
|
+
- Session management with secure cookies
|
|
17
|
+
- Password reset functionality
|
|
18
|
+
- Protected route middleware
|
|
19
|
+
- User profile management
|
|
20
|
+
- Optional Polar.sh subscription integration
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Files Added
|
|
25
|
+
|
|
26
|
+
### Pages/Routes
|
|
27
|
+
- `app/sign-in/page.tsx` - Sign in page with email/password and Google OAuth
|
|
28
|
+
- `app/sign-up/page.tsx` - Sign up page with email/password and Google OAuth
|
|
29
|
+
- `app/api/auth/[...all]/route.ts` - Better Auth API route handler
|
|
30
|
+
|
|
31
|
+
### Utilities/Libraries
|
|
32
|
+
- `lib/auth.ts` - Better Auth server configuration
|
|
33
|
+
- `lib/auth-client.ts` - Better Auth client configuration
|
|
34
|
+
- `auth-schema.ts` - Drizzle ORM schema for auth tables (user, session, account, verification)
|
|
35
|
+
|
|
36
|
+
### Middleware
|
|
37
|
+
- `middleware.patch.ts` - Middleware logic for route protection (will be merged into base middleware)
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## Dependencies
|
|
42
|
+
|
|
43
|
+
### Package Dependencies
|
|
44
|
+
The following packages will be added to `package.json`:
|
|
45
|
+
- `better-auth@^1.0.0` - Core authentication library
|
|
46
|
+
- `@polar-sh/better-auth@^1.0.0` - Polar.sh integration for Better Auth (optional)
|
|
47
|
+
|
|
48
|
+
### Required Modules
|
|
49
|
+
- **Database Module** - Auth requires database for user/session storage
|
|
50
|
+
- **Email Module** (optional) - For password reset emails (works without it, but emails won't send)
|
|
51
|
+
|
|
52
|
+
### Included Components
|
|
53
|
+
This module uses UI components from the base package:
|
|
54
|
+
- ✅ `components/ui/button.tsx` - For form buttons
|
|
55
|
+
- ✅ `components/ui/card.tsx` - For sign-in/sign-up cards
|
|
56
|
+
- ✅ `components/ui/input.tsx` - For form inputs
|
|
57
|
+
- ✅ `components/ui/label.tsx` - For form labels
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## Environment Variables
|
|
62
|
+
|
|
63
|
+
Add these to your `.env.local`:
|
|
64
|
+
|
|
65
|
+
```env
|
|
66
|
+
# Authentication
|
|
67
|
+
BETTER_AUTH_SECRET="your-secret-key-here" # Generate with: openssl rand -base64 32
|
|
68
|
+
NEXT_PUBLIC_APP_URL="http://localhost:3000"
|
|
69
|
+
|
|
70
|
+
# Google OAuth (optional but recommended)
|
|
71
|
+
GOOGLE_CLIENT_ID="your-google-client-id"
|
|
72
|
+
GOOGLE_CLIENT_SECRET="your-google-client-secret"
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
**Required Variables:**
|
|
76
|
+
- `BETTER_AUTH_SECRET` - Secret key for signing tokens (generate a secure random string)
|
|
77
|
+
- `NEXT_PUBLIC_APP_URL` - Your application URL (used for OAuth callbacks)
|
|
78
|
+
|
|
79
|
+
**Optional Variables:**
|
|
80
|
+
- `GOOGLE_CLIENT_ID` - Google OAuth client ID (get from [Google Cloud Console](https://console.cloud.google.com/))
|
|
81
|
+
- `GOOGLE_CLIENT_SECRET` - Google OAuth client secret
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## Manual Integration Steps
|
|
86
|
+
|
|
87
|
+
If you're appending this module to an existing project, follow these steps:
|
|
88
|
+
|
|
89
|
+
### Step 1: Install Dependencies
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
npm install
|
|
93
|
+
# or
|
|
94
|
+
pnpm install
|
|
95
|
+
# or
|
|
96
|
+
yarn install
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
The append command automatically adds missing dependencies to `package.json`, but you need to install them.
|
|
100
|
+
|
|
101
|
+
### Step 2: Add Environment Variables
|
|
102
|
+
|
|
103
|
+
1. Copy `.env.example` to `.env.local` (if not exists)
|
|
104
|
+
2. Add the required environment variables listed above
|
|
105
|
+
3. Generate `BETTER_AUTH_SECRET`:
|
|
106
|
+
```bash
|
|
107
|
+
openssl rand -base64 32
|
|
108
|
+
```
|
|
109
|
+
4. Set up Google OAuth (optional):
|
|
110
|
+
- Go to [Google Cloud Console](https://console.cloud.google.com/)
|
|
111
|
+
- Create OAuth 2.0 credentials
|
|
112
|
+
- Add authorized redirect URI: `http://localhost:3000/api/auth/callback/google`
|
|
113
|
+
|
|
114
|
+
### Step 3: Update Database Schema
|
|
115
|
+
|
|
116
|
+
The auth module requires database tables. If you have the database module installed, the schema will be merged automatically. Otherwise, you need to:
|
|
117
|
+
|
|
118
|
+
1. Add the auth schema to your `db/schema.ts`:
|
|
119
|
+
```typescript
|
|
120
|
+
// Import from auth-schema.ts or copy the table definitions
|
|
121
|
+
export { user, session, account, verification } from '@/auth-schema';
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
2. Generate and run migrations:
|
|
125
|
+
```bash
|
|
126
|
+
npm run db:generate
|
|
127
|
+
npm run db:push
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Step 4: Update Middleware
|
|
131
|
+
|
|
132
|
+
The auth module includes middleware for route protection. Update your `middleware.ts`:
|
|
133
|
+
|
|
134
|
+
```typescript
|
|
135
|
+
import { NextRequest, NextResponse } from "next/server";
|
|
136
|
+
import { getSessionCookie } from "better-auth/cookies";
|
|
137
|
+
|
|
138
|
+
export async function middleware(request: NextRequest) {
|
|
139
|
+
const sessionCookie = getSessionCookie(request);
|
|
140
|
+
const { pathname } = request.nextUrl;
|
|
141
|
+
|
|
142
|
+
// Don't redirect from sign-in/sign-up pages
|
|
143
|
+
if (["/sign-in", "/sign-up"].includes(pathname)) {
|
|
144
|
+
return NextResponse.next();
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Redirect unauthenticated users from protected routes
|
|
148
|
+
const protectedRoutes = ["/dashboard"]; // Add your protected routes here
|
|
149
|
+
const isProtectedRoute = protectedRoutes.some(route => pathname.startsWith(route));
|
|
150
|
+
|
|
151
|
+
if (isProtectedRoute && !sessionCookie) {
|
|
152
|
+
const returnTo = encodeURIComponent(pathname);
|
|
153
|
+
return NextResponse.redirect(new URL(`/sign-in?returnTo=${returnTo}`, request.url));
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return NextResponse.next();
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export const config = {
|
|
160
|
+
matcher: ["/dashboard/:path*", "/sign-in", "/sign-up"],
|
|
161
|
+
};
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### Step 5: Verify Installation
|
|
165
|
+
|
|
166
|
+
1. Start your dev server: `npm run dev`
|
|
167
|
+
2. Visit `http://localhost:3000/sign-up` to create an account
|
|
168
|
+
3. Visit `http://localhost:3000/sign-in` to sign in
|
|
169
|
+
4. Try accessing `/dashboard` - you should be redirected to sign-in if not authenticated
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
## Usage Examples
|
|
174
|
+
|
|
175
|
+
### Using Auth Client in Components
|
|
176
|
+
|
|
177
|
+
```typescript
|
|
178
|
+
"use client";
|
|
179
|
+
|
|
180
|
+
import { authClient } from "@/lib/auth-client";
|
|
181
|
+
|
|
182
|
+
export default function ProfileButton() {
|
|
183
|
+
const handleSignOut = async () => {
|
|
184
|
+
await authClient.signOut({
|
|
185
|
+
fetchOptions: {
|
|
186
|
+
onSuccess: () => {
|
|
187
|
+
window.location.href = "/";
|
|
188
|
+
},
|
|
189
|
+
},
|
|
190
|
+
});
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
return <button onClick={handleSignOut}>Sign Out</button>;
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### Using Auth Server-Side
|
|
198
|
+
|
|
199
|
+
```typescript
|
|
200
|
+
import { auth } from "@/lib/auth";
|
|
201
|
+
import { getSession } from "better-auth/next-js";
|
|
202
|
+
|
|
203
|
+
export default async function DashboardPage() {
|
|
204
|
+
const session = await getSession({ auth });
|
|
205
|
+
|
|
206
|
+
if (!session) {
|
|
207
|
+
redirect("/sign-in");
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
return <div>Welcome, {session.user.email}!</div>;
|
|
211
|
+
}
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
### Checking Authentication Status
|
|
215
|
+
|
|
216
|
+
```typescript
|
|
217
|
+
"use client";
|
|
218
|
+
|
|
219
|
+
import { authClient } from "@/lib/auth-client";
|
|
220
|
+
import { useEffect, useState } from "react";
|
|
221
|
+
|
|
222
|
+
export default function AuthStatus() {
|
|
223
|
+
const [session, setSession] = useState(null);
|
|
224
|
+
|
|
225
|
+
useEffect(() => {
|
|
226
|
+
authClient.getSession().then(setSession);
|
|
227
|
+
}, []);
|
|
228
|
+
|
|
229
|
+
if (!session) {
|
|
230
|
+
return <div>Not signed in</div>;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
return <div>Signed in as {session.user.email}</div>;
|
|
234
|
+
}
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
---
|
|
238
|
+
|
|
239
|
+
## Customization
|
|
240
|
+
|
|
241
|
+
### Styling
|
|
242
|
+
- Sign-in/sign-up pages use Tailwind CSS classes
|
|
243
|
+
- Customize colors in `tailwind.config.ts`
|
|
244
|
+
- Modify page layouts in `app/sign-in/page.tsx` and `app/sign-up/page.tsx`
|
|
245
|
+
|
|
246
|
+
### Configuration
|
|
247
|
+
- Auth configuration is in `lib/auth.ts`
|
|
248
|
+
- Customize providers, session settings, and more
|
|
249
|
+
- See [Better Auth documentation](https://www.better-auth.com/docs) for options
|
|
250
|
+
|
|
251
|
+
### Protected Routes
|
|
252
|
+
Edit `middleware.ts` to customize which routes require authentication:
|
|
253
|
+
|
|
254
|
+
```typescript
|
|
255
|
+
const protectedRoutes = [
|
|
256
|
+
"/dashboard",
|
|
257
|
+
"/settings",
|
|
258
|
+
"/admin" // Add your custom routes
|
|
259
|
+
];
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
---
|
|
263
|
+
|
|
264
|
+
## Integration Points
|
|
265
|
+
|
|
266
|
+
### Files That May Need Manual Updates
|
|
267
|
+
|
|
268
|
+
**middleware.ts** (required):
|
|
269
|
+
- Add route protection logic (see Step 4 above)
|
|
270
|
+
|
|
271
|
+
**db/schema.ts** (if database module not installed):
|
|
272
|
+
- Import or merge auth schema tables
|
|
273
|
+
|
|
274
|
+
**lib/email.ts** (optional):
|
|
275
|
+
- For password reset emails, you'll need email functionality
|
|
276
|
+
- See Email module for integration
|
|
277
|
+
|
|
278
|
+
---
|
|
279
|
+
|
|
280
|
+
## Troubleshooting
|
|
281
|
+
|
|
282
|
+
### Common Issues
|
|
283
|
+
|
|
284
|
+
**Issue:** "Database connection failed" error
|
|
285
|
+
**Solution:**
|
|
286
|
+
- Ensure `DATABASE_URL` is set in `.env.local`
|
|
287
|
+
- Run database migrations: `npm run db:push`
|
|
288
|
+
- Verify database is accessible
|
|
289
|
+
|
|
290
|
+
**Issue:** Google OAuth not working
|
|
291
|
+
**Solution:**
|
|
292
|
+
- Verify `GOOGLE_CLIENT_ID` and `GOOGLE_CLIENT_SECRET` are set
|
|
293
|
+
- Check redirect URI matches in Google Cloud Console
|
|
294
|
+
- Ensure `NEXT_PUBLIC_APP_URL` is correct
|
|
295
|
+
|
|
296
|
+
**Issue:** "BETTER_AUTH_SECRET is required"
|
|
297
|
+
**Solution:**
|
|
298
|
+
- Generate a secret: `openssl rand -base64 32`
|
|
299
|
+
- Add to `.env.local`: `BETTER_AUTH_SECRET="your-secret"`
|
|
300
|
+
|
|
301
|
+
**Issue:** Users can't sign in after sign up
|
|
302
|
+
**Solution:**
|
|
303
|
+
- Check database migrations ran successfully
|
|
304
|
+
- Verify `user` and `session` tables exist
|
|
305
|
+
- Check database connection
|
|
306
|
+
|
|
307
|
+
---
|
|
308
|
+
|
|
309
|
+
## Next Steps
|
|
310
|
+
|
|
311
|
+
After installing this module:
|
|
312
|
+
|
|
313
|
+
1. Set up Google OAuth (optional but recommended)
|
|
314
|
+
2. Configure email for password resets (requires Email module)
|
|
315
|
+
3. Customize protected routes in middleware
|
|
316
|
+
4. Add user profile pages
|
|
317
|
+
5. Integrate with Payments module for subscription management
|
|
318
|
+
|
|
319
|
+
---
|
|
320
|
+
|
|
321
|
+
## Related Modules
|
|
322
|
+
|
|
323
|
+
This module works well with:
|
|
324
|
+
- **Database Module** - Required for user/session storage
|
|
325
|
+
- **Email Module** - For password reset emails
|
|
326
|
+
- **Payments Module** - For subscription-based access control
|
|
327
|
+
|
|
328
|
+
---
|
|
329
|
+
|
|
330
|
+
## Module Status
|
|
331
|
+
|
|
332
|
+
✅ **Core Files Included** - All auth pages and utilities
|
|
333
|
+
⚠️ **Requires Database** - Database module must be installed first
|
|
334
|
+
✅ **UI Components** - Uses base package components
|
|
335
|
+
✅ **Well Documented** - Comprehensive integration guide
|
|
336
|
+
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Metadata } from "next";
|
|
2
|
+
|
|
3
|
+
export const metadata: Metadata = {
|
|
4
|
+
title: "Dashboard",
|
|
5
|
+
description: "Your application dashboard",
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export default function DashboardLayout({
|
|
9
|
+
children,
|
|
10
|
+
}: {
|
|
11
|
+
children: React.ReactNode;
|
|
12
|
+
}) {
|
|
13
|
+
return <>{children}</>;
|
|
14
|
+
}
|
|
15
|
+
|
|
@@ -0,0 +1,140 @@
|
|
|
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 { authClient } from "@/lib/auth-client";
|
|
12
|
+
import { useRouter } from "next/navigation";
|
|
13
|
+
import { useEffect, useState } from "react";
|
|
14
|
+
import { toast } from "sonner";
|
|
15
|
+
|
|
16
|
+
export default function DashboardPage() {
|
|
17
|
+
const router = useRouter();
|
|
18
|
+
const [session, setSession] = useState<any>(null);
|
|
19
|
+
const [loading, setLoading] = useState(true);
|
|
20
|
+
|
|
21
|
+
useEffect(() => {
|
|
22
|
+
async function checkSession() {
|
|
23
|
+
try {
|
|
24
|
+
const currentSession = await authClient.getSession();
|
|
25
|
+
setSession(currentSession);
|
|
26
|
+
} catch (error) {
|
|
27
|
+
console.error("Failed to get session:", error);
|
|
28
|
+
router.push("/sign-in");
|
|
29
|
+
} finally {
|
|
30
|
+
setLoading(false);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
checkSession();
|
|
34
|
+
}, [router]);
|
|
35
|
+
|
|
36
|
+
const handleSignOut = async () => {
|
|
37
|
+
try {
|
|
38
|
+
await authClient.signOut({
|
|
39
|
+
fetchOptions: {
|
|
40
|
+
onSuccess: () => {
|
|
41
|
+
toast.success("Signed out successfully");
|
|
42
|
+
router.push("/");
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
} catch (error) {
|
|
47
|
+
console.error("Sign out error:", error);
|
|
48
|
+
toast.error("Failed to sign out");
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
if (loading) {
|
|
53
|
+
return (
|
|
54
|
+
<div className="flex items-center justify-center min-h-screen">
|
|
55
|
+
<div className="text-center">
|
|
56
|
+
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-gray-900 dark:border-gray-100 mx-auto"></div>
|
|
57
|
+
<p className="mt-4 text-gray-600 dark:text-gray-400">Loading...</p>
|
|
58
|
+
</div>
|
|
59
|
+
</div>
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (!session) {
|
|
64
|
+
return null; // Will redirect to sign-in
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return (
|
|
68
|
+
<div className="min-h-screen bg-gray-50 dark:bg-gray-900 p-8">
|
|
69
|
+
<div className="max-w-4xl mx-auto">
|
|
70
|
+
<div className="flex justify-between items-center mb-8">
|
|
71
|
+
<div>
|
|
72
|
+
<h1 className="text-3xl font-bold text-gray-900 dark:text-white">
|
|
73
|
+
Dashboard
|
|
74
|
+
</h1>
|
|
75
|
+
<p className="text-gray-600 dark:text-gray-400 mt-2">
|
|
76
|
+
Welcome back, {session.user?.name || session.user?.email}!
|
|
77
|
+
</p>
|
|
78
|
+
</div>
|
|
79
|
+
<Button onClick={handleSignOut} variant="outline">
|
|
80
|
+
Sign Out
|
|
81
|
+
</Button>
|
|
82
|
+
</div>
|
|
83
|
+
|
|
84
|
+
<div className="grid gap-6 md:grid-cols-2">
|
|
85
|
+
<Card>
|
|
86
|
+
<CardHeader>
|
|
87
|
+
<CardTitle>Account Information</CardTitle>
|
|
88
|
+
<CardDescription>Your account details</CardDescription>
|
|
89
|
+
</CardHeader>
|
|
90
|
+
<CardContent>
|
|
91
|
+
<div className="space-y-2">
|
|
92
|
+
<div>
|
|
93
|
+
<p className="text-sm text-gray-600 dark:text-gray-400">Email</p>
|
|
94
|
+
<p className="font-medium">{session.user?.email}</p>
|
|
95
|
+
</div>
|
|
96
|
+
{session.user?.name && (
|
|
97
|
+
<div>
|
|
98
|
+
<p className="text-sm text-gray-600 dark:text-gray-400">Name</p>
|
|
99
|
+
<p className="font-medium">{session.user.name}</p>
|
|
100
|
+
</div>
|
|
101
|
+
)}
|
|
102
|
+
{session.user?.image && (
|
|
103
|
+
<div>
|
|
104
|
+
<p className="text-sm text-gray-600 dark:text-gray-400">Profile Image</p>
|
|
105
|
+
<img
|
|
106
|
+
src={session.user.image}
|
|
107
|
+
alt="Profile"
|
|
108
|
+
className="w-16 h-16 rounded-full mt-2"
|
|
109
|
+
/>
|
|
110
|
+
</div>
|
|
111
|
+
)}
|
|
112
|
+
</div>
|
|
113
|
+
</CardContent>
|
|
114
|
+
</Card>
|
|
115
|
+
|
|
116
|
+
<Card>
|
|
117
|
+
<CardHeader>
|
|
118
|
+
<CardTitle>Getting Started</CardTitle>
|
|
119
|
+
<CardDescription>Next steps for your application</CardDescription>
|
|
120
|
+
</CardHeader>
|
|
121
|
+
<CardContent>
|
|
122
|
+
<div className="space-y-4">
|
|
123
|
+
<p className="text-sm text-gray-600 dark:text-gray-400">
|
|
124
|
+
Your authentication is set up and working! Here are some things you can do next:
|
|
125
|
+
</p>
|
|
126
|
+
<ul className="list-disc list-inside space-y-2 text-sm text-gray-600 dark:text-gray-400">
|
|
127
|
+
<li>Customize this dashboard page</li>
|
|
128
|
+
<li>Add more protected routes</li>
|
|
129
|
+
<li>Install additional modules (payments, etc.)</li>
|
|
130
|
+
<li>Configure your database connection</li>
|
|
131
|
+
</ul>
|
|
132
|
+
</div>
|
|
133
|
+
</CardContent>
|
|
134
|
+
</Card>
|
|
135
|
+
</div>
|
|
136
|
+
</div>
|
|
137
|
+
</div>
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
|