stackpatch 1.1.4 → 1.1.6
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/README.md +76 -69
- package/bin/stackpatch.js +79 -0
- package/bin/stackpatch.ts +2445 -3
- package/boilerplate/auth/app/api/auth/[...nextauth]/route.ts +124 -0
- package/boilerplate/auth/app/api/auth/signup/route.ts +45 -0
- package/boilerplate/auth/app/auth/login/page.tsx +24 -50
- package/boilerplate/auth/app/auth/signup/page.tsx +56 -69
- package/boilerplate/auth/app/dashboard/page.tsx +82 -0
- package/boilerplate/auth/app/login/page.tsx +136 -0
- package/boilerplate/auth/app/page.tsx +48 -0
- package/boilerplate/auth/components/auth-button.tsx +43 -0
- package/boilerplate/auth/components/auth-navbar.tsx +118 -0
- package/boilerplate/auth/components/protected-route.tsx +74 -0
- package/boilerplate/auth/components/session-provider.tsx +11 -0
- package/boilerplate/auth/middleware.ts +51 -0
- package/package.json +5 -6
- package/boilerplate/auth/app/stackpatch/page.tsx +0 -269
- package/boilerplate/auth/components/auth-wrapper.tsx +0 -61
- package/src/auth/generator.ts +0 -569
- package/src/auth/index.ts +0 -372
- package/src/auth/setup.ts +0 -293
- package/src/commands/add.ts +0 -112
- package/src/commands/create.ts +0 -128
- package/src/commands/revert.ts +0 -389
- package/src/config.ts +0 -52
- package/src/fileOps/copy.ts +0 -224
- package/src/fileOps/layout.ts +0 -304
- package/src/fileOps/protected.ts +0 -67
- package/src/index.ts +0 -215
- package/src/manifest.ts +0 -87
- package/src/ui/logo.ts +0 -24
- package/src/ui/progress.ts +0 -82
- package/src/utils/dependencies.ts +0 -114
- package/src/utils/deps-check.ts +0 -45
- package/src/utils/files.ts +0 -58
- package/src/utils/paths.ts +0 -217
- package/src/utils/scanner.ts +0 -109
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import React from "react";
|
|
4
|
+
import { AuthNavbar } from "@/components/auth-navbar";
|
|
5
|
+
import Link from "next/link";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Landing Page Example
|
|
9
|
+
*
|
|
10
|
+
* This is an example landing page with auth navbar.
|
|
11
|
+
*
|
|
12
|
+
* To use this:
|
|
13
|
+
* 1. This replaces your existing app/page.tsx (only if it's the default Next.js page)
|
|
14
|
+
* 2. The AuthNavbar automatically shows sign in/out based on session
|
|
15
|
+
* 3. Customize this page with your content
|
|
16
|
+
* 4. If you have an existing navbar, you can use AuthNavbar as reference or integrate its features
|
|
17
|
+
*/
|
|
18
|
+
export default function HomePage() {
|
|
19
|
+
return (
|
|
20
|
+
<div className="min-h-screen bg-zinc-50 dark:bg-black">
|
|
21
|
+
<AuthNavbar />
|
|
22
|
+
<main className="mx-auto max-w-7xl px-4 py-16 sm:px-6 lg:px-8">
|
|
23
|
+
<div className="text-center">
|
|
24
|
+
<h1 className="text-4xl font-bold tracking-tight text-zinc-900 dark:text-zinc-50 sm:text-6xl">
|
|
25
|
+
Welcome to Your App
|
|
26
|
+
</h1>
|
|
27
|
+
<p className="mt-6 text-lg leading-8 text-zinc-600 dark:text-zinc-400">
|
|
28
|
+
Get started by exploring the features below.
|
|
29
|
+
</p>
|
|
30
|
+
<div className="mt-10 flex items-center justify-center gap-x-6">
|
|
31
|
+
<Link
|
|
32
|
+
href="/dashboard"
|
|
33
|
+
className="rounded-md bg-zinc-900 px-3.5 py-2.5 text-sm font-semibold text-white shadow-sm hover:bg-zinc-700 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-zinc-600 dark:bg-zinc-50 dark:text-zinc-900 dark:hover:bg-zinc-200"
|
|
34
|
+
>
|
|
35
|
+
Go to Dashboard
|
|
36
|
+
</Link>
|
|
37
|
+
<Link
|
|
38
|
+
href="/auth/login"
|
|
39
|
+
className="text-sm font-semibold leading-6 text-zinc-900 dark:text-zinc-50"
|
|
40
|
+
>
|
|
41
|
+
Sign In <span aria-hidden="true">→</span>
|
|
42
|
+
</Link>
|
|
43
|
+
</div>
|
|
44
|
+
</div>
|
|
45
|
+
</main>
|
|
46
|
+
</div>
|
|
47
|
+
);
|
|
48
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { signIn, signOut, useSession } from "next-auth/react";
|
|
4
|
+
|
|
5
|
+
export function AuthButton() {
|
|
6
|
+
const { data: session, status } = useSession();
|
|
7
|
+
|
|
8
|
+
if (status === "loading") {
|
|
9
|
+
return (
|
|
10
|
+
<button
|
|
11
|
+
disabled
|
|
12
|
+
className="rounded-md bg-zinc-100 px-4 py-2 text-sm font-medium text-zinc-900 dark:bg-zinc-800 dark:text-zinc-50"
|
|
13
|
+
>
|
|
14
|
+
Loading...
|
|
15
|
+
</button>
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (session) {
|
|
20
|
+
return (
|
|
21
|
+
<div className="flex items-center gap-4">
|
|
22
|
+
<span className="text-sm text-zinc-600 dark:text-zinc-400">
|
|
23
|
+
{session.user?.email}
|
|
24
|
+
</span>
|
|
25
|
+
<button
|
|
26
|
+
onClick={() => signOut()}
|
|
27
|
+
className="rounded-md bg-zinc-900 px-4 py-2 text-sm font-medium text-white hover:bg-zinc-700 dark:bg-zinc-50 dark:text-zinc-900 dark:hover:bg-zinc-200"
|
|
28
|
+
>
|
|
29
|
+
Sign out
|
|
30
|
+
</button>
|
|
31
|
+
</div>
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<button
|
|
37
|
+
onClick={() => signIn()}
|
|
38
|
+
className="rounded-md bg-zinc-900 px-4 py-2 text-sm font-medium text-white hover:bg-zinc-700 dark:bg-zinc-50 dark:text-zinc-900 dark:hover:bg-zinc-200"
|
|
39
|
+
>
|
|
40
|
+
Sign in
|
|
41
|
+
</button>
|
|
42
|
+
);
|
|
43
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import React from "react";
|
|
4
|
+
import { useSession, signOut } from "next-auth/react";
|
|
5
|
+
import Link from "next/link";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Auth Navbar Component (Demo/Example)
|
|
9
|
+
*
|
|
10
|
+
* Displays a navigation bar with session status and sign in/out button.
|
|
11
|
+
* This is a demo component - rename or customize it to fit your needs.
|
|
12
|
+
*
|
|
13
|
+
* Usage:
|
|
14
|
+
* ```tsx
|
|
15
|
+
* import { AuthNavbar } from "@/components/auth-navbar";
|
|
16
|
+
*
|
|
17
|
+
* export default function Layout({ children }) {
|
|
18
|
+
* return (
|
|
19
|
+
* <>
|
|
20
|
+
* <AuthNavbar />
|
|
21
|
+
* {children}
|
|
22
|
+
* </>
|
|
23
|
+
* );
|
|
24
|
+
* }
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export function AuthNavbar() {
|
|
28
|
+
const { data: session, status } = useSession();
|
|
29
|
+
|
|
30
|
+
const handleSignOut = async () => {
|
|
31
|
+
await signOut({ callbackUrl: "/" });
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
return (
|
|
35
|
+
<nav className="border-b border-zinc-200 bg-white dark:border-zinc-800 dark:bg-zinc-900">
|
|
36
|
+
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
|
|
37
|
+
<div className="flex h-16 items-center justify-between">
|
|
38
|
+
{/* Logo/Brand */}
|
|
39
|
+
<div className="flex items-center">
|
|
40
|
+
<Link
|
|
41
|
+
href="/"
|
|
42
|
+
className="text-xl font-bold text-zinc-900 hover:text-zinc-700 dark:text-zinc-50 dark:hover:text-zinc-200"
|
|
43
|
+
>
|
|
44
|
+
Your App
|
|
45
|
+
</Link>
|
|
46
|
+
</div>
|
|
47
|
+
|
|
48
|
+
{/* Navigation Links */}
|
|
49
|
+
<div className="hidden md:flex md:items-center md:space-x-6">
|
|
50
|
+
<Link
|
|
51
|
+
href="/"
|
|
52
|
+
className="text-sm font-medium text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-50"
|
|
53
|
+
>
|
|
54
|
+
Home
|
|
55
|
+
</Link>
|
|
56
|
+
{session && (
|
|
57
|
+
<Link
|
|
58
|
+
href="/dashboard"
|
|
59
|
+
className="text-sm font-medium text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-50"
|
|
60
|
+
>
|
|
61
|
+
Dashboard
|
|
62
|
+
</Link>
|
|
63
|
+
)}
|
|
64
|
+
</div>
|
|
65
|
+
|
|
66
|
+
{/* Auth Section */}
|
|
67
|
+
<div className="flex items-center space-x-4">
|
|
68
|
+
{status === "loading" ? (
|
|
69
|
+
<div className="h-8 w-8 animate-spin rounded-full border-2 border-zinc-300 border-t-zinc-600 dark:border-zinc-700 dark:border-t-zinc-400"></div>
|
|
70
|
+
) : session ? (
|
|
71
|
+
<div className="flex items-center space-x-4">
|
|
72
|
+
{/* User Info */}
|
|
73
|
+
<div className="hidden sm:flex sm:flex-col sm:items-end">
|
|
74
|
+
<span className="text-sm font-medium text-zinc-900 dark:text-zinc-50">
|
|
75
|
+
{session.user?.name || session.user?.email}
|
|
76
|
+
</span>
|
|
77
|
+
<span className="text-xs text-zinc-500 dark:text-zinc-400">
|
|
78
|
+
{session.user?.email}
|
|
79
|
+
</span>
|
|
80
|
+
</div>
|
|
81
|
+
|
|
82
|
+
{/* User Avatar */}
|
|
83
|
+
{session.user?.image ? (
|
|
84
|
+
<img
|
|
85
|
+
src={session.user.image}
|
|
86
|
+
alt={session.user.name || "User"}
|
|
87
|
+
className="h-8 w-8 rounded-full"
|
|
88
|
+
/>
|
|
89
|
+
) : (
|
|
90
|
+
<div className="flex h-8 w-8 items-center justify-center rounded-full bg-zinc-600 text-sm font-medium text-white dark:bg-zinc-700">
|
|
91
|
+
{session.user?.name?.charAt(0).toUpperCase() ||
|
|
92
|
+
session.user?.email?.charAt(0).toUpperCase() ||
|
|
93
|
+
"U"}
|
|
94
|
+
</div>
|
|
95
|
+
)}
|
|
96
|
+
|
|
97
|
+
{/* Sign Out Button */}
|
|
98
|
+
<button
|
|
99
|
+
onClick={handleSignOut}
|
|
100
|
+
className="rounded-md bg-zinc-900 px-4 py-2 text-sm font-semibold text-white hover:bg-zinc-700 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-zinc-600 dark:bg-zinc-50 dark:text-zinc-900 dark:hover:bg-zinc-200"
|
|
101
|
+
>
|
|
102
|
+
Sign Out
|
|
103
|
+
</button>
|
|
104
|
+
</div>
|
|
105
|
+
) : (
|
|
106
|
+
<Link
|
|
107
|
+
href="/auth/login"
|
|
108
|
+
className="rounded-md bg-zinc-900 px-4 py-2 text-sm font-semibold text-white hover:bg-zinc-700 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-zinc-600 dark:bg-zinc-50 dark:text-zinc-900 dark:hover:bg-zinc-200"
|
|
109
|
+
>
|
|
110
|
+
Sign In
|
|
111
|
+
</Link>
|
|
112
|
+
)}
|
|
113
|
+
</div>
|
|
114
|
+
</div>
|
|
115
|
+
</div>
|
|
116
|
+
</nav>
|
|
117
|
+
);
|
|
118
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useSession } from "next-auth/react";
|
|
4
|
+
import { useRouter } from "next/navigation";
|
|
5
|
+
import { useEffect } from "react";
|
|
6
|
+
|
|
7
|
+
interface ProtectedRouteProps {
|
|
8
|
+
children: React.ReactNode;
|
|
9
|
+
redirectTo?: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* ProtectedRoute Component
|
|
14
|
+
*
|
|
15
|
+
* Wrap any component or page with this to protect it from unauthorized access.
|
|
16
|
+
*
|
|
17
|
+
* Usage:
|
|
18
|
+
* ```tsx
|
|
19
|
+
* import { ProtectedRoute } from "@/components/protected-route";
|
|
20
|
+
*
|
|
21
|
+
* export default function DashboardPage() {
|
|
22
|
+
* return (
|
|
23
|
+
* <ProtectedRoute>
|
|
24
|
+
* <div>Your protected content here</div>
|
|
25
|
+
* </ProtectedRoute>
|
|
26
|
+
* );
|
|
27
|
+
* }
|
|
28
|
+
* ```
|
|
29
|
+
*
|
|
30
|
+
* Or protect an entire page:
|
|
31
|
+
* ```tsx
|
|
32
|
+
* // app/dashboard/page.tsx
|
|
33
|
+
* import { ProtectedRoute } from "@/components/protected-route";
|
|
34
|
+
*
|
|
35
|
+
* export default function Dashboard() {
|
|
36
|
+
* return (
|
|
37
|
+
* <ProtectedRoute>
|
|
38
|
+
* <h1>Dashboard</h1>
|
|
39
|
+
* <p>This page is protected</p>
|
|
40
|
+
* </ProtectedRoute>
|
|
41
|
+
* );
|
|
42
|
+
* }
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
export function ProtectedRoute({
|
|
46
|
+
children,
|
|
47
|
+
redirectTo = "/auth/login"
|
|
48
|
+
}: ProtectedRouteProps) {
|
|
49
|
+
const { data: session, status } = useSession();
|
|
50
|
+
const router = useRouter();
|
|
51
|
+
|
|
52
|
+
useEffect(() => {
|
|
53
|
+
if (status === "unauthenticated") {
|
|
54
|
+
router.push(redirectTo);
|
|
55
|
+
}
|
|
56
|
+
}, [status, router, redirectTo]);
|
|
57
|
+
|
|
58
|
+
if (status === "loading") {
|
|
59
|
+
return (
|
|
60
|
+
<div className="flex min-h-screen items-center justify-center">
|
|
61
|
+
<div className="text-center">
|
|
62
|
+
<div className="inline-block h-8 w-8 animate-spin rounded-full border-4 border-solid border-current border-r-transparent align-[-0.125em] motion-reduce:animate-[spin_1.5s_linear_infinite]"></div>
|
|
63
|
+
<p className="mt-4 text-sm text-zinc-600 dark:text-zinc-400">Loading...</p>
|
|
64
|
+
</div>
|
|
65
|
+
</div>
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (status === "unauthenticated") {
|
|
70
|
+
return null; // Will redirect
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return <>{children}</>;
|
|
74
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { withAuth } from "next-auth/middleware";
|
|
2
|
+
import { NextResponse } from "next/server";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Middleware for Protected Routes
|
|
6
|
+
*
|
|
7
|
+
* This middleware protects routes at the file system level.
|
|
8
|
+
*
|
|
9
|
+
* To protect a route, add it to the matcher array below.
|
|
10
|
+
*
|
|
11
|
+
* Example:
|
|
12
|
+
* - To protect all routes under /dashboard: matcher: ["/dashboard/:path*"]
|
|
13
|
+
* - To protect specific routes: matcher: ["/dashboard", "/profile", "/settings"]
|
|
14
|
+
* - To protect all routes except public ones: matcher: ["/((?!api|auth|_next/static|_next/image|favicon.ico).*)"]
|
|
15
|
+
*
|
|
16
|
+
* Protected routes will automatically redirect to /auth/login if user is not authenticated.
|
|
17
|
+
*
|
|
18
|
+
* Usage:
|
|
19
|
+
* 1. Add your protected route paths to the matcher array
|
|
20
|
+
* 2. Users accessing these routes will be redirected to login if not authenticated
|
|
21
|
+
* 3. Authenticated users can access the routes normally
|
|
22
|
+
*/
|
|
23
|
+
export default withAuth(
|
|
24
|
+
function middleware(req) {
|
|
25
|
+
// You can add additional logic here if needed
|
|
26
|
+
// For example, role-based access control
|
|
27
|
+
return NextResponse.next();
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
callbacks: {
|
|
31
|
+
authorized: ({ token }) => !!token, // User must be authenticated
|
|
32
|
+
},
|
|
33
|
+
pages: {
|
|
34
|
+
signIn: "/auth/login", // Redirect to login page
|
|
35
|
+
},
|
|
36
|
+
}
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
// Configure which routes to protect
|
|
40
|
+
// Add your protected routes here
|
|
41
|
+
export const config = {
|
|
42
|
+
matcher: [
|
|
43
|
+
// Example: Protect dashboard routes
|
|
44
|
+
// "/dashboard/:path*",
|
|
45
|
+
// "/profile/:path*",
|
|
46
|
+
// "/settings/:path*",
|
|
47
|
+
|
|
48
|
+
// To protect all routes except public ones, uncomment:
|
|
49
|
+
// "/((?!api|auth|_next/static|_next/image|favicon.ico).*)",
|
|
50
|
+
],
|
|
51
|
+
};
|
package/package.json
CHANGED
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "stackpatch",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.6",
|
|
4
4
|
"description": "Composable frontend features for modern React & Next.js apps - Add authentication, UI components, and more with zero configuration",
|
|
5
5
|
"main": "bin/stackpatch.ts",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"bin": {
|
|
8
|
-
"stackpatch": "bin/stackpatch.
|
|
9
|
-
"create-stackpatch": "bin/stackpatch.
|
|
8
|
+
"stackpatch": "bin/stackpatch.js",
|
|
9
|
+
"create-stackpatch": "bin/stackpatch.js"
|
|
10
10
|
},
|
|
11
11
|
"files": [
|
|
12
12
|
"bin",
|
|
13
|
-
"src",
|
|
14
13
|
"boilerplate",
|
|
15
14
|
"README.md"
|
|
16
15
|
],
|
|
@@ -48,14 +47,14 @@
|
|
|
48
47
|
},
|
|
49
48
|
"homepage": "https://github.com/Darshh09/StackPatch#readme",
|
|
50
49
|
"engines": {
|
|
50
|
+
"node": ">=18.0.0",
|
|
51
51
|
"bun": ">=1.0.0"
|
|
52
52
|
},
|
|
53
53
|
"packageManager": "pnpm@10.28.0",
|
|
54
54
|
"dependencies": {
|
|
55
|
-
"@inquirer/select": "^5.0.4",
|
|
56
55
|
"chalk": "^5.6.2",
|
|
57
56
|
"fs-extra": "^11.3.3",
|
|
58
|
-
"inquirer": "^13.
|
|
57
|
+
"inquirer": "^13.1.0",
|
|
59
58
|
"jimp": "^0.22.10",
|
|
60
59
|
"tsx": "^4.19.2"
|
|
61
60
|
},
|
|
@@ -1,269 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import React from "react";
|
|
4
|
-
import { authClient } from "@/lib/auth-client";
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* StackPatch Landing Page
|
|
8
|
-
*
|
|
9
|
-
* Landing page with ProductHunt, GitHub links, user session info, and sign out button
|
|
10
|
-
*
|
|
11
|
-
* 📝 TO CHANGE THIS ROUTE:
|
|
12
|
-
* 1. Rename this file/folder: app/stackpatch/page.tsx → app/YOUR_ROUTE/page.tsx
|
|
13
|
-
* 2. Update redirects in:
|
|
14
|
-
* - app/page.tsx (line 21)
|
|
15
|
-
* - app/auth/login/page.tsx (line 19, 40)
|
|
16
|
-
* - app/auth/signup/page.tsx (line 21, 69)
|
|
17
|
-
* - middleware.ts (if protecting this route)
|
|
18
|
-
*/
|
|
19
|
-
export default function StackPatchPage() {
|
|
20
|
-
const { data: session, isPending } = authClient.useSession();
|
|
21
|
-
|
|
22
|
-
const handleSignOut = async () => {
|
|
23
|
-
await authClient.signOut({ callbackUrl: "/" });
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
if (isPending) {
|
|
27
|
-
return (
|
|
28
|
-
<div className="flex min-h-screen items-center justify-center bg-gradient-to-b from-zinc-50 to-white dark:from-black dark:to-zinc-900">
|
|
29
|
-
<div className="text-center">
|
|
30
|
-
<div className="inline-block h-8 w-8 animate-spin rounded-full border-4 border-solid border-current border-r-transparent align-[-0.125em] motion-reduce:animate-[spin_1.5s_linear_infinite]"></div>
|
|
31
|
-
<p className="mt-4 text-sm text-zinc-600 dark:text-zinc-400">Loading session...</p>
|
|
32
|
-
</div>
|
|
33
|
-
</div>
|
|
34
|
-
);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
if (!session?.user) {
|
|
38
|
-
return (
|
|
39
|
-
<div className="min-h-screen bg-gradient-to-b from-zinc-50 to-white dark:from-black dark:to-zinc-900">
|
|
40
|
-
<div className="flex min-h-screen flex-col items-center justify-center px-4 py-16 sm:px-6 lg:px-8">
|
|
41
|
-
<div className="mx-auto max-w-2xl text-center">
|
|
42
|
-
{/* Logo/Brand */}
|
|
43
|
-
<div className="mb-8">
|
|
44
|
-
<h1 className="text-6xl font-bold tracking-tight text-zinc-900 dark:text-zinc-50 sm:text-7xl">
|
|
45
|
-
StackPatch
|
|
46
|
-
</h1>
|
|
47
|
-
<p className="mt-4 text-xl leading-8 text-zinc-600 dark:text-zinc-400">
|
|
48
|
-
Composable frontend features for modern React & Next.js apps
|
|
49
|
-
</p>
|
|
50
|
-
</div>
|
|
51
|
-
|
|
52
|
-
{/* Authentication Status Card */}
|
|
53
|
-
<div className="mx-auto mt-8 max-w-md rounded-lg border border-zinc-200 bg-white p-8 shadow-lg dark:border-zinc-800 dark:bg-zinc-900">
|
|
54
|
-
<div className="mb-4">
|
|
55
|
-
<div className="mx-auto flex h-16 w-16 items-center justify-center rounded-full bg-zinc-100 dark:bg-zinc-800">
|
|
56
|
-
<svg
|
|
57
|
-
className="h-8 w-8 text-zinc-600 dark:text-zinc-400"
|
|
58
|
-
fill="none"
|
|
59
|
-
viewBox="0 0 24 24"
|
|
60
|
-
stroke="currentColor"
|
|
61
|
-
>
|
|
62
|
-
<path
|
|
63
|
-
strokeLinecap="round"
|
|
64
|
-
strokeLinejoin="round"
|
|
65
|
-
strokeWidth={2}
|
|
66
|
-
d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z"
|
|
67
|
-
/>
|
|
68
|
-
</svg>
|
|
69
|
-
</div>
|
|
70
|
-
</div>
|
|
71
|
-
<h2 className="text-2xl font-semibold text-zinc-900 dark:text-zinc-50">
|
|
72
|
-
Authentication Required
|
|
73
|
-
</h2>
|
|
74
|
-
<p className="mt-2 text-sm text-zinc-600 dark:text-zinc-400">
|
|
75
|
-
Please sign in to access the StackPatch dashboard and manage your account.
|
|
76
|
-
</p>
|
|
77
|
-
<div className="mt-6">
|
|
78
|
-
<a
|
|
79
|
-
href="/auth/login"
|
|
80
|
-
className="inline-flex w-full items-center justify-center rounded-md bg-zinc-900 px-6 py-3 text-sm font-semibold text-white shadow-sm hover:bg-zinc-700 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-zinc-600 dark:bg-zinc-50 dark:text-zinc-900 dark:hover:bg-zinc-200"
|
|
81
|
-
>
|
|
82
|
-
Sign In
|
|
83
|
-
</a>
|
|
84
|
-
</div>
|
|
85
|
-
<p className="mt-4 text-xs text-zinc-500 dark:text-zinc-500">
|
|
86
|
-
Don't have an account?{" "}
|
|
87
|
-
<a
|
|
88
|
-
href="/auth/signup"
|
|
89
|
-
className="font-medium text-zinc-900 hover:underline dark:text-zinc-50"
|
|
90
|
-
>
|
|
91
|
-
Sign up
|
|
92
|
-
</a>
|
|
93
|
-
</p>
|
|
94
|
-
</div>
|
|
95
|
-
|
|
96
|
-
{/* Additional Info */}
|
|
97
|
-
<div className="mt-12 flex flex-col items-center gap-6 sm:flex-row sm:justify-center">
|
|
98
|
-
<a
|
|
99
|
-
href="https://www.producthunt.com/posts/stackpatch"
|
|
100
|
-
target="_blank"
|
|
101
|
-
rel="noopener noreferrer"
|
|
102
|
-
className="inline-flex items-center gap-2 rounded-md bg-orange-500 px-6 py-3 text-sm font-semibold text-white shadow-sm hover:bg-orange-600 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-orange-600"
|
|
103
|
-
>
|
|
104
|
-
🚀 Support us on ProductHunt
|
|
105
|
-
</a>
|
|
106
|
-
<a
|
|
107
|
-
href="https://github.com/Darshh09/StackPatch"
|
|
108
|
-
target="_blank"
|
|
109
|
-
rel="noopener noreferrer"
|
|
110
|
-
className="inline-flex items-center gap-2 rounded-md bg-zinc-900 px-6 py-3 text-sm font-semibold text-white shadow-sm hover:bg-zinc-700 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-zinc-600 dark:bg-zinc-50 dark:text-zinc-900 dark:hover:bg-zinc-200"
|
|
111
|
-
>
|
|
112
|
-
<svg className="h-5 w-5" fill="currentColor" viewBox="0 0 24 24">
|
|
113
|
-
<path
|
|
114
|
-
fillRule="evenodd"
|
|
115
|
-
d="M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482C19.138 20.197 22 16.425 22 12.017 22 6.484 17.522 2 12 2z"
|
|
116
|
-
clipRule="evenodd"
|
|
117
|
-
/>
|
|
118
|
-
</svg>
|
|
119
|
-
⭐ Star on GitHub
|
|
120
|
-
</a>
|
|
121
|
-
</div>
|
|
122
|
-
</div>
|
|
123
|
-
</div>
|
|
124
|
-
</div>
|
|
125
|
-
);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
return (
|
|
129
|
-
<div className="min-h-screen bg-gradient-to-b from-zinc-50 to-white dark:from-black dark:to-zinc-900">
|
|
130
|
-
{/* Header with Sign Out */}
|
|
131
|
-
<header className="border-b border-zinc-200 bg-white/80 backdrop-blur-sm dark:border-zinc-800 dark:bg-zinc-900/80">
|
|
132
|
-
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
|
|
133
|
-
<div className="flex h-16 items-center justify-between">
|
|
134
|
-
<h1 className="text-xl font-bold text-zinc-900 dark:text-zinc-50">StackPatch</h1>
|
|
135
|
-
{session?.user && (
|
|
136
|
-
<div className="flex items-center gap-4">
|
|
137
|
-
<div className="hidden sm:flex sm:flex-col sm:items-end">
|
|
138
|
-
<span className="text-sm font-medium text-zinc-900 dark:text-zinc-50">
|
|
139
|
-
{session.user.name || session.user.email}
|
|
140
|
-
</span>
|
|
141
|
-
<span className="text-xs text-zinc-500 dark:text-zinc-400">
|
|
142
|
-
{session.user.email}
|
|
143
|
-
</span>
|
|
144
|
-
</div>
|
|
145
|
-
<button
|
|
146
|
-
onClick={handleSignOut}
|
|
147
|
-
className="rounded-md bg-zinc-900 px-4 py-2 text-sm font-semibold text-white hover:bg-zinc-700 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-zinc-600 dark:bg-zinc-50 dark:text-zinc-900 dark:hover:bg-zinc-200"
|
|
148
|
-
>
|
|
149
|
-
Sign Out
|
|
150
|
-
</button>
|
|
151
|
-
</div>
|
|
152
|
-
)}
|
|
153
|
-
</div>
|
|
154
|
-
</div>
|
|
155
|
-
</header>
|
|
156
|
-
|
|
157
|
-
<main className="mx-auto max-w-7xl px-4 py-16 sm:px-6 lg:px-8">
|
|
158
|
-
<div className="text-center">
|
|
159
|
-
<h1 className="text-5xl font-bold tracking-tight text-zinc-900 dark:text-zinc-50 sm:text-7xl">
|
|
160
|
-
StackPatch
|
|
161
|
-
</h1>
|
|
162
|
-
<p className="mt-6 text-xl leading-8 text-zinc-600 dark:text-zinc-400">
|
|
163
|
-
Composable frontend features for modern React & Next.js apps
|
|
164
|
-
</p>
|
|
165
|
-
|
|
166
|
-
{/* User Session Info */}
|
|
167
|
-
{session?.user && (
|
|
168
|
-
<div className="mx-auto mt-8 max-w-md rounded-lg bg-white p-6 shadow-sm dark:bg-zinc-800">
|
|
169
|
-
<h2 className="text-lg font-semibold text-zinc-900 dark:text-zinc-50">
|
|
170
|
-
Welcome back! 👋
|
|
171
|
-
</h2>
|
|
172
|
-
<div className="mt-4 space-y-2 text-left text-sm text-zinc-600 dark:text-zinc-400">
|
|
173
|
-
<p>
|
|
174
|
-
<span className="font-medium">Name:</span> {session.user.name || "Not provided"}
|
|
175
|
-
</p>
|
|
176
|
-
<p>
|
|
177
|
-
<span className="font-medium">Email:</span> {session.user.email}
|
|
178
|
-
</p>
|
|
179
|
-
{session.user.image && (
|
|
180
|
-
<div className="mt-3">
|
|
181
|
-
<img
|
|
182
|
-
src={session.user.image}
|
|
183
|
-
alt={session.user.name || "User"}
|
|
184
|
-
className="mx-auto h-16 w-16 rounded-full"
|
|
185
|
-
/>
|
|
186
|
-
</div>
|
|
187
|
-
)}
|
|
188
|
-
</div>
|
|
189
|
-
</div>
|
|
190
|
-
)}
|
|
191
|
-
|
|
192
|
-
{/* CTA Buttons */}
|
|
193
|
-
<div className="mt-10 flex items-center justify-center gap-x-6">
|
|
194
|
-
<a
|
|
195
|
-
href="https://www.producthunt.com/posts/stackpatch"
|
|
196
|
-
target="_blank"
|
|
197
|
-
rel="noopener noreferrer"
|
|
198
|
-
className="rounded-md bg-orange-500 px-6 py-3 text-sm font-semibold text-white shadow-sm hover:bg-orange-600 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-orange-600"
|
|
199
|
-
>
|
|
200
|
-
🚀 Support us on ProductHunt
|
|
201
|
-
</a>
|
|
202
|
-
<a
|
|
203
|
-
href="https://github.com/Darshh09/StackPatch"
|
|
204
|
-
target="_blank"
|
|
205
|
-
rel="noopener noreferrer"
|
|
206
|
-
className="flex items-center gap-2 rounded-md bg-zinc-900 px-6 py-3 text-sm font-semibold text-white shadow-sm hover:bg-zinc-700 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-zinc-600 dark:bg-zinc-50 dark:text-zinc-900 dark:hover:bg-zinc-200"
|
|
207
|
-
>
|
|
208
|
-
<svg className="h-5 w-5" fill="currentColor" viewBox="0 0 24 24">
|
|
209
|
-
<path
|
|
210
|
-
fillRule="evenodd"
|
|
211
|
-
d="M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482C19.138 20.197 22 16.425 22 12.017 22 6.484 17.522 2 12 2z"
|
|
212
|
-
clipRule="evenodd"
|
|
213
|
-
/>
|
|
214
|
-
</svg>
|
|
215
|
-
⭐ Star on GitHub
|
|
216
|
-
</a>
|
|
217
|
-
</div>
|
|
218
|
-
|
|
219
|
-
{/* Setup Instructions */}
|
|
220
|
-
{session?.user && (
|
|
221
|
-
<div className="mx-auto mt-12 max-w-2xl rounded-lg border border-zinc-200 bg-zinc-50 p-6 dark:border-zinc-800 dark:bg-zinc-900">
|
|
222
|
-
<h2 className="text-lg font-semibold text-zinc-900 dark:text-zinc-50">
|
|
223
|
-
🎉 Authentication Setup Complete!
|
|
224
|
-
</h2>
|
|
225
|
-
<div className="mt-4 space-y-3 text-left text-sm text-zinc-600 dark:text-zinc-400">
|
|
226
|
-
<div>
|
|
227
|
-
<p className="font-medium text-zinc-900 dark:text-zinc-50">Next Steps:</p>
|
|
228
|
-
<ol className="mt-2 ml-4 list-decimal space-y-2">
|
|
229
|
-
<li>Create <code className="rounded bg-zinc-200 px-1.5 py-0.5 text-xs dark:bg-zinc-800">.env.local</code> from <code className="rounded bg-zinc-200 px-1.5 py-0.5 text-xs dark:bg-zinc-800">.env.example</code></li>
|
|
230
|
-
<li>Add your OAuth credentials (Google/GitHub) to <code className="rounded bg-zinc-200 px-1.5 py-0.5 text-xs dark:bg-zinc-800">.env.local</code></li>
|
|
231
|
-
<li>Configure your database (if using database mode)</li>
|
|
232
|
-
<li>Start building your app!</li>
|
|
233
|
-
</ol>
|
|
234
|
-
</div>
|
|
235
|
-
<div className="mt-4 pt-4 border-t border-zinc-300 dark:border-zinc-700">
|
|
236
|
-
<p className="font-medium text-zinc-900 dark:text-zinc-50 mb-2">Protected Routes:</p>
|
|
237
|
-
<div className="text-xs space-y-1 text-zinc-600 dark:text-zinc-400">
|
|
238
|
-
<p>Routes are automatically protected. Use <code className="rounded bg-zinc-200 px-1 py-0.5 dark:bg-zinc-800">/*</code> to protect all sub-routes:</p>
|
|
239
|
-
<ul className="ml-4 mt-1 space-y-0.5 list-disc">
|
|
240
|
-
<li><code className="rounded bg-zinc-200 px-1 py-0.5 dark:bg-zinc-800">/dashboard</code> → Protects only /dashboard</li>
|
|
241
|
-
<li><code className="rounded bg-zinc-200 px-1 py-0.5 dark:bg-zinc-800">/dashboard/*</code> → Protects /dashboard and all sub-routes</li>
|
|
242
|
-
<li><code className="rounded bg-zinc-200 px-1 py-0.5 dark:bg-zinc-800">/admin/*</code> → Protects /admin and all sub-routes</li>
|
|
243
|
-
</ul>
|
|
244
|
-
<p className="mt-2">Edit <code className="rounded bg-zinc-200 px-1 py-0.5 dark:bg-zinc-800">lib/protected-routes.ts</code> to modify protected routes.</p>
|
|
245
|
-
</div>
|
|
246
|
-
</div>
|
|
247
|
-
<div className="mt-4 pt-4 border-t border-zinc-300 dark:border-zinc-700">
|
|
248
|
-
<p className="font-medium text-zinc-900 dark:text-zinc-50">Documentation:</p>
|
|
249
|
-
<ul className="mt-2 space-y-1">
|
|
250
|
-
<li>
|
|
251
|
-
<a href="https://better-auth.com/docs" target="_blank" rel="noopener noreferrer" className="text-blue-600 hover:underline dark:text-blue-400">
|
|
252
|
-
Better Auth Docs
|
|
253
|
-
</a>
|
|
254
|
-
</li>
|
|
255
|
-
<li>
|
|
256
|
-
<a href="https://stackpatch.darshitdev.in/docs" target="_blank" rel="noopener noreferrer" className="text-blue-600 hover:underline dark:text-blue-400">
|
|
257
|
-
StackPatch Auth Guide
|
|
258
|
-
</a>
|
|
259
|
-
</li>
|
|
260
|
-
</ul>
|
|
261
|
-
</div>
|
|
262
|
-
</div>
|
|
263
|
-
</div>
|
|
264
|
-
)}
|
|
265
|
-
</div>
|
|
266
|
-
</main>
|
|
267
|
-
</div>
|
|
268
|
-
);
|
|
269
|
-
}
|