diff --git a/.example.env b/.example.env index 069982a..22563af 100644 --- a/.example.env +++ b/.example.env @@ -5,4 +5,7 @@ S3_UPLOAD_SECRET= S3_UPLOAD_BUCKET= S3_UPLOAD_REGION= -DATABASE_URL= \ No newline at end of file +DATABASE_URL= + +NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY= +CLERK_SECRET_KEY= \ No newline at end of file diff --git a/.gitignore b/.gitignore index f650315..490daf7 100644 --- a/.gitignore +++ b/.gitignore @@ -24,4 +24,6 @@ yarn-error.log* # typescript *.tsbuildinfo -next-env.d.ts \ No newline at end of file +next-env.d.ts +# clerk configuration (can include secrets) +/.clerk/ diff --git a/app/api/generate-comic/route.ts b/app/api/generate-comic/route.ts index 0394f28..45b95bd 100644 --- a/app/api/generate-comic/route.ts +++ b/app/api/generate-comic/route.ts @@ -1,5 +1,6 @@ import { type NextRequest, NextResponse } from "next/server"; import Together from "together-ai"; +import { auth } from "@clerk/nextjs/server"; import { updatePage, createStory, @@ -102,6 +103,15 @@ const STYLE_DESCRIPTIONS: Record = { export async function POST(request: NextRequest) { try { + const { userId } = await auth(); + + if (!userId) { + return NextResponse.json( + { error: "Authentication required" }, + { status: 401 } + ); + } + const { storyId, prompt, @@ -112,11 +122,7 @@ export async function POST(request: NextRequest) { previousContext = "", } = await request.json(); - console.log("Received request:", { - storyId, - prompt: prompt?.substring(0, 50), - characterImagesCount: characterImages.length, - }); + console.log("Received request:", { storyId, prompt: prompt?.substring(0, 50), characterImagesCount: characterImages.length, userId }); if (!prompt || !apiKey) { return NextResponse.json( @@ -129,7 +135,7 @@ export async function POST(request: NextRequest) { let story; if (storyId) { - // Create next page for existing story + // Create page for existing story console.log("Creating page for existing story:", storyId); const nextPageNumber = await getNextPageNumber(storyId); page = await createPage({ @@ -142,11 +148,11 @@ export async function POST(request: NextRequest) { console.log("Page created:", page.id); } else { // Create new story and first page - console.log("Creating new story"); + console.log("Creating new story for user:", userId); story = await createStory({ title: prompt.length > 50 ? prompt.substring(0, 50) + "..." : prompt, description: undefined, - userId: undefined, + userId: userId, }); console.log("Story created:", story.id); diff --git a/app/api/stories/[storySlug]/route.ts b/app/api/stories/[storySlug]/route.ts index 4de88b2..580d5f4 100644 --- a/app/api/stories/[storySlug]/route.ts +++ b/app/api/stories/[storySlug]/route.ts @@ -1,22 +1,33 @@ import { type NextRequest, NextResponse } from "next/server"; +import { auth } from "@clerk/nextjs/server"; import { getStoryWithPagesBySlug } from "@/lib/db-actions"; import { db } from "@/lib/db"; import { stories } from "@/lib/schema"; +import { eq } from "drizzle-orm"; export async function GET( request: NextRequest, { params }: { params: Promise<{ storySlug: string }> } ) { try { - const { storySlug: slug } = await params; - console.log("API: Fetching story with slug:", slug); + const { userId } = await auth(); - // Special case: if slug is "all", return all stories for debugging + if (!userId) { + return NextResponse.json( + { error: "Authentication required" }, + { status: 401 } + ); + } + + const { storySlug: slug } = await params; + console.log("API: Fetching story with slug:", slug, "for user:", userId); + + // Special case: if slug is "all", return user's stories for debugging if (slug === "all") { - const allStories = await db.select().from(stories); + const userStories = await db.select().from(stories).where(eq(stories.userId, userId)); return NextResponse.json({ - message: "All stories", - stories: allStories.map(s => ({ id: s.id, slug: s.slug, title: s.title })) + message: "User stories", + stories: userStories.map(s => ({ id: s.id, slug: s.slug, title: s.title })) }); } @@ -28,7 +39,6 @@ export async function GET( } const result = await getStoryWithPagesBySlug(slug); - console.log("API: Result found:", !!result); if (!result) { return NextResponse.json( @@ -37,6 +47,14 @@ export async function GET( ); } + // Check if the story belongs to the authenticated user + if (result.story.userId !== userId) { + return NextResponse.json( + { error: "Access denied" }, + { status: 403 } + ); + } + return NextResponse.json(result); } catch (error) { console.error("Error fetching story:", error); diff --git a/app/layout.tsx b/app/layout.tsx index ecaec3d..417b8f8 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -1,48 +1,50 @@ -import type React from "react" -import type { Metadata } from "next" -import { Inter, Atma, Space_Grotesk, Instrument_Serif } from "next/font/google" -import { Analytics } from "@vercel/analytics/next" -import { Toaster } from "@/components/ui/toaster" -import "./globals.css" +import type React from "react"; +import type { Metadata } from "next"; +import { Inter, Atma, Space_Grotesk, Instrument_Serif } from "next/font/google"; +import { Analytics } from "@vercel/analytics/next"; +import { Toaster } from "@/components/ui/toaster"; +import { ClerkProvider } from "@clerk/nextjs"; +import "./globals.css"; -const inter = Inter({ subsets: ["latin"], variable: "--font-inter" }) +const inter = Inter({ subsets: ["latin"], variable: "--font-inter" }); const atma = Atma({ weight: ["400", "500", "600", "700"], subsets: ["latin"], variable: "--font-atma", -}) +}); const spaceGrotesk = Space_Grotesk({ subsets: ["latin"], variable: "--font-space-grotesk", -}) +}); const instrumentSerif = Instrument_Serif({ weight: ["400"], subsets: ["latin"], variable: "--font-instrument-serif", -}) +}); export const metadata: Metadata = { title: "MakeComics - AI Comic Generator", description: "Create stunning AI-generated comics in seconds. Choose your style, describe your story, and watch the magic happen.", - generator: 'v0.app' -} +}; export default function RootLayout({ children, }: Readonly<{ - children: React.ReactNode + children: React.ReactNode; }>) { return ( - - - {children} - - - - - ) + + + + {children} + + + + + + ); } diff --git a/components/editor/comic-canvas.tsx b/components/editor/comic-canvas.tsx index e4ba353..ccd2956 100644 --- a/components/editor/comic-canvas.tsx +++ b/components/editor/comic-canvas.tsx @@ -24,12 +24,12 @@ export function ComicCanvas({ page }: ComicCanvasProps) {
-
+
{`Page
diff --git a/components/landing/navbar.tsx b/components/landing/navbar.tsx index b151d91..0a86f67 100644 --- a/components/landing/navbar.tsx +++ b/components/landing/navbar.tsx @@ -1,9 +1,16 @@ "use client"; import { useState } from "react"; -import { Github, Key } from "lucide-react"; +import { Github, Key, User } from "lucide-react"; import Link from "next/link"; import { ApiKeyModal } from "@/components/api-key-modal"; +import { + SignInButton, + SignUpButton, + SignedIn, + SignedOut, + UserButton, +} from "@clerk/nextjs"; export function Navbar() { const [showApiModal, setShowApiModal] = useState(false); @@ -32,7 +39,7 @@ export function Navbar() {
+ + + + +
diff --git a/package.json b/package.json index d085a61..4cad12f 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ "start": "next start" }, "dependencies": { + "@clerk/nextjs": "^6.36.5", "@hookform/resolvers": "^3.10.0", "@neondatabase/serverless": "^1.0.2", "@next/env": "^16.1.1", @@ -49,7 +50,7 @@ "embla-carousel-react": "8.5.1", "input-otp": "1.4.1", "lucide-react": "^0.454.0", - "next": "16.0.10", + "next": "16.1.1", "next-s3-upload": "^0.3.4", "next-themes": "^0.4.6", "react": "19.2.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index dc029bd..d740237 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,6 +8,9 @@ importers: .: dependencies: + '@clerk/nextjs': + specifier: ^6.36.5 + version: 6.36.5(next@16.1.1(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@hookform/resolvers': specifier: ^3.10.0 version: 3.10.0(react-hook-form@7.69.0(react@19.2.0)) @@ -100,7 +103,7 @@ importers: version: 1.1.6(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@vercel/analytics': specifier: 1.3.1 - version: 1.3.1(next@16.0.10(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react@19.2.0) + version: 1.3.1(next@16.1.1(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react@19.2.0) autoprefixer: specifier: ^10.4.20 version: 10.4.23(postcss@8.5.6) @@ -129,11 +132,11 @@ importers: specifier: ^0.454.0 version: 0.454.0(react@19.2.0) next: - specifier: 16.0.10 - version: 16.0.10(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + specifier: 16.1.1 + version: 16.1.1(react-dom@19.2.0(react@19.2.0))(react@19.2.0) next-s3-upload: specifier: ^0.3.4 - version: 0.3.4(next@16.0.10(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react@19.2.0) + version: 0.3.4(next@16.1.1(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react@19.2.0) next-themes: specifier: ^0.4.6 version: 0.4.6(react-dom@19.2.0(react@19.2.0))(react@19.2.0) @@ -393,6 +396,41 @@ packages: resolution: {integrity: sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==} engines: {node: '>=6.9.0'} + '@clerk/backend@2.29.0': + resolution: {integrity: sha512-cw4CK6ZHgeFROirlIOawelqRBxZAyH6v3GPSYZEEzYAL0WWUHx7cMXzoQcTMruH7w6UM7s3Ox+uUcINESWkQPA==} + engines: {node: '>=18.17.0'} + + '@clerk/clerk-react@5.59.2': + resolution: {integrity: sha512-vFZ4LWPenbNnui4GqGGkicH/3SL7KhS9egTMv/m0Dj/sS7mUgmLqAFpqWkhbzN8s8/rybuvJsMyIU7M0kx8+Cw==} + engines: {node: '>=18.17.0'} + peerDependencies: + react: ^18.0.0 || ~19.0.3 || ~19.1.4 || ~19.2.3 || ~19.3.0-0 + react-dom: ^18.0.0 || ~19.0.3 || ~19.1.4 || ~19.2.3 || ~19.3.0-0 + + '@clerk/nextjs@6.36.5': + resolution: {integrity: sha512-qHNNbxhAZMHanv47DKc08Xc+y0gbsoQBFVYA+WRzwii5OWOoWmLlydTGKaqukqNw9km9IN9b2KWSAvs1oklp2g==} + engines: {node: '>=18.17.0'} + peerDependencies: + next: ^13.5.7 || ^14.2.25 || ^15.2.3 || ^16 + react: ^18.0.0 || ~19.0.3 || ~19.1.4 || ~19.2.3 || ~19.3.0-0 + react-dom: ^18.0.0 || ~19.0.3 || ~19.1.4 || ~19.2.3 || ~19.3.0-0 + + '@clerk/shared@3.41.1': + resolution: {integrity: sha512-BCbT7Xodk2rndA2nV/lW8X5LMNTvFP5UG2wNN9cYuAcTaI6hYZP18/z2zef2gG4xIrK7WAEjGVzHscikqNtzFQ==} + engines: {node: '>=18.17.0'} + peerDependencies: + react: ^18.0.0 || ~19.0.3 || ~19.1.4 || ~19.2.3 || ~19.3.0-0 + react-dom: ^18.0.0 || ~19.0.3 || ~19.1.4 || ~19.2.3 || ~19.3.0-0 + peerDependenciesMeta: + react: + optional: true + react-dom: + optional: true + + '@clerk/types@4.101.9': + resolution: {integrity: sha512-RO00JqqmkIoI1o0XCtvudjaLpqEoe8PRDHlLS1r/aNZazUQCO0TT6nZOx1F3X+QJDjqYVY7YmYl3mtO2QVEk1g==} + engines: {node: '>=18.17.0'} + '@date-fns/tz@1.2.0': resolution: {integrity: sha512-LBrd7MiJZ9McsOgxqWX7AaxrDjcFVjWH/tIKJd7pnR7McaslGYOP1QmmiBXdJH/H/yLCT+rcQ7FaPBUxRGUtrg==} @@ -875,56 +913,53 @@ packages: resolution: {integrity: sha512-I5sbpSIAHiB+b6UttofhrN/UJXII+4tZPAq1qugzwCwLIL8EZLV7F/JyHUrEIiGgQpEXzpnjlJ+zwcEhheGvCw==} engines: {node: '>=19.0.0'} - '@next/env@16.0.10': - resolution: {integrity: sha512-8tuaQkyDVgeONQ1MeT9Mkk8pQmZapMKFh5B+OrFUlG3rVmYTXcXlBetBgTurKXGaIZvkoqRT9JL5K3phXcgang==} - '@next/env@16.1.1': resolution: {integrity: sha512-3oxyM97Sr2PqiVyMyrZUtrtM3jqqFxOQJVuKclDsgj/L728iZt/GyslkN4NwarledZATCenbk4Offjk1hQmaAA==} - '@next/swc-darwin-arm64@16.0.10': - resolution: {integrity: sha512-4XgdKtdVsaflErz+B5XeG0T5PeXKDdruDf3CRpnhN+8UebNa5N2H58+3GDgpn/9GBurrQ1uWW768FfscwYkJRg==} + '@next/swc-darwin-arm64@16.1.1': + resolution: {integrity: sha512-JS3m42ifsVSJjSTzh27nW+Igfha3NdBOFScr9C80hHGrWx55pTrVL23RJbqir7k7/15SKlrLHhh/MQzqBBYrQA==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] - '@next/swc-darwin-x64@16.0.10': - resolution: {integrity: sha512-spbEObMvRKkQ3CkYVOME+ocPDFo5UqHb8EMTS78/0mQ+O1nqE8toHJVioZo4TvebATxgA8XMTHHrScPrn68OGw==} + '@next/swc-darwin-x64@16.1.1': + resolution: {integrity: sha512-hbyKtrDGUkgkyQi1m1IyD3q4I/3m9ngr+V93z4oKHrPcmxwNL5iMWORvLSGAf2YujL+6HxgVvZuCYZfLfb4bGw==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] - '@next/swc-linux-arm64-gnu@16.0.10': - resolution: {integrity: sha512-uQtWE3X0iGB8apTIskOMi2w/MKONrPOUCi5yLO+v3O8Mb5c7K4Q5KD1jvTpTF5gJKa3VH/ijKjKUq9O9UhwOYw==} + '@next/swc-linux-arm64-gnu@16.1.1': + resolution: {integrity: sha512-/fvHet+EYckFvRLQ0jPHJCUI5/B56+2DpI1xDSvi80r/3Ez+Eaa2Yq4tJcRTaB1kqj/HrYKn8Yplm9bNoMJpwQ==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@next/swc-linux-arm64-musl@16.0.10': - resolution: {integrity: sha512-llA+hiDTrYvyWI21Z0L1GiXwjQaanPVQQwru5peOgtooeJ8qx3tlqRV2P7uH2pKQaUfHxI/WVarvI5oYgGxaTw==} + '@next/swc-linux-arm64-musl@16.1.1': + resolution: {integrity: sha512-MFHrgL4TXNQbBPzkKKur4Fb5ICEJa87HM7fczFs2+HWblM7mMLdco3dvyTI+QmLBU9xgns/EeeINSZD6Ar+oLg==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@next/swc-linux-x64-gnu@16.0.10': - resolution: {integrity: sha512-AK2q5H0+a9nsXbeZ3FZdMtbtu9jxW4R/NgzZ6+lrTm3d6Zb7jYrWcgjcpM1k8uuqlSy4xIyPR2YiuUr+wXsavA==} + '@next/swc-linux-x64-gnu@16.1.1': + resolution: {integrity: sha512-20bYDfgOQAPUkkKBnyP9PTuHiJGM7HzNBbuqmD0jiFVZ0aOldz+VnJhbxzjcSabYsnNjMPsE0cyzEudpYxsrUQ==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@next/swc-linux-x64-musl@16.0.10': - resolution: {integrity: sha512-1TDG9PDKivNw5550S111gsO4RGennLVl9cipPhtkXIFVwo31YZ73nEbLjNC8qG3SgTz/QZyYyaFYMeY4BKZR/g==} + '@next/swc-linux-x64-musl@16.1.1': + resolution: {integrity: sha512-9pRbK3M4asAHQRkwaXwu601oPZHghuSC8IXNENgbBSyImHv/zY4K5udBusgdHkvJ/Tcr96jJwQYOll0qU8+fPA==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@next/swc-win32-arm64-msvc@16.0.10': - resolution: {integrity: sha512-aEZIS4Hh32xdJQbHz121pyuVZniSNoqDVx1yIr2hy+ZwJGipeqnMZBJHyMxv2tiuAXGx6/xpTcQJ6btIiBjgmg==} + '@next/swc-win32-arm64-msvc@16.1.1': + resolution: {integrity: sha512-bdfQkggaLgnmYrFkSQfsHfOhk/mCYmjnrbRCGgkMcoOBZ4n+TRRSLmT/CU5SATzlBJ9TpioUyBW/vWFXTqQRiA==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] - '@next/swc-win32-x64-msvc@16.0.10': - resolution: {integrity: sha512-E+njfCoFLb01RAFEnGZn6ERoOqhK1Gl3Lfz1Kjnj0Ulfu7oJbuMyvBKNj/bw8XZnenHDASlygTjZICQW+rYW1Q==} + '@next/swc-win32-x64-msvc@16.1.1': + resolution: {integrity: sha512-Ncwbw2WJ57Al5OX0k4chM68DKhEPlrXBaSXDCi2kPi5f4d8b3ejr3RRJGfKBLrn2YJL5ezNS7w2TZLHSti8CMw==} engines: {node: '>= 10'} cpu: [x64] os: [win32] @@ -1824,6 +1859,9 @@ packages: resolution: {integrity: sha512-4aUIteuyxtBUhVdiQqcDhKFitwfd9hqoSDYY2KRXiWtgoWJ9Bmise+KfEPDiVHWeJepvF8xJO9/9+WDIciMFFw==} engines: {node: '>=18.0.0'} + '@stablelib/base64@1.0.1': + resolution: {integrity: sha512-1bnPQqSxSuc3Ii6MhBysoWCg58j97aUjuCSZrGSmDxNqtytIi0k8utUenAwTZN4V5mXXYGsVUI9zeBqy+jBOSQ==} + '@swc/helpers@0.5.15': resolution: {integrity: sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==} @@ -2018,6 +2056,13 @@ packages: react: ^18 || ^19 || ^19.0.0-rc react-dom: ^18 || ^19 || ^19.0.0-rc + cookie@1.0.2: + resolution: {integrity: sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==} + engines: {node: '>=18'} + + csstype@3.1.3: + resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} + csstype@3.2.3: resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} @@ -2083,6 +2128,10 @@ packages: decimal.js-light@2.5.1: resolution: {integrity: sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==} + dequal@2.0.3: + resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} + engines: {node: '>=6'} + detect-libc@2.1.2: resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} engines: {node: '>=8'} @@ -2239,6 +2288,9 @@ packages: resolution: {integrity: sha512-jt2DW/aNFNwke7AUd+Z+e6pz39KO5rzdbbFCg2sGafS4mk13MI7Z8O5z9cADNn5lhGODIgLwug6TZO2ctf7kcw==} engines: {node: '>=6.0.0'} + fast-sha256@1.3.0: + resolution: {integrity: sha512-n11RGP/lrWEFI/bWdygLxhI+pVeo1ZYIVwvvPkW7azl/rOy+F3HYRZ2K5zeE9mmkhQppyv9sQFx0JM9UabnpPQ==} + fast-xml-parser@5.2.5: resolution: {integrity: sha512-pfX9uG9Ki0yekDHx2SiuRIyFdyAr1kMIMitPvb0YBo8SUfKvia7w7FIyd/l6av85pFYRhZscS75MwMnbvY+hcQ==} hasBin: true @@ -2253,6 +2305,9 @@ packages: get-tsconfig@4.13.0: resolution: {integrity: sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==} + glob-to-regexp@0.4.1: + resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} + graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} @@ -2276,6 +2331,10 @@ packages: resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} hasBin: true + js-cookie@3.0.5: + resolution: {integrity: sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==} + engines: {node: '>=14'} + js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -2385,8 +2444,8 @@ packages: react: ^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc react-dom: ^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc - next@16.0.10: - resolution: {integrity: sha512-RtWh5PUgI+vxlV3HdR+IfWA1UUHu0+Ram/JBO4vWB54cVPentCD0e+lxyAYEsDTqGGMg7qpjhKh6dc6aW7W/sA==} + next@16.1.1: + resolution: {integrity: sha512-QI+T7xrxt1pF6SQ/JYFz95ro/mg/1Znk5vBebsWwbpejj1T0A23hO7GYEaVac9QUOT2BIMiuzm0L99ooq7k0/w==} engines: {node: '>=20.9.0'} hasBin: true peerDependencies: @@ -2584,6 +2643,12 @@ packages: resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} engines: {node: '>=0.10.0'} + standardwebhooks@1.0.0: + resolution: {integrity: sha512-BbHGOQK9olHPMvQNHWul6MYlrRTAOKn03rOe4A8O3CLWhNf4YHBqq2HJKKC+sfqpxiBY52pNeesD6jIiLDz8jg==} + + std-env@3.10.0: + resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==} + stream-browserify@3.0.0: resolution: {integrity: sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==} @@ -2606,6 +2671,11 @@ packages: babel-plugin-macros: optional: true + swr@2.3.4: + resolution: {integrity: sha512-bYd2lrhc+VarcpkgWclcUi92wYCpOgMws9Sd1hG1ntAu0NEy+14CbotuFjshBU2kt9rYj9TSmDcybpxpeTU1fg==} + peerDependencies: + react: ^16.11.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + tailwind-merge@3.4.0: resolution: {integrity: sha512-uSaO4gnW+b3Y2aWoWfFpX62vn2sR3skfhbjsEnaBI81WD1wBLlHZe5sWf0AqjksNdYTbGBEd0UasQMT3SNV15g==} @@ -3260,6 +3330,55 @@ snapshots: '@babel/runtime@7.28.4': {} + '@clerk/backend@2.29.0(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': + dependencies: + '@clerk/shared': 3.41.1(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@clerk/types': 4.101.9(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + cookie: 1.0.2 + standardwebhooks: 1.0.0 + tslib: 2.8.1 + transitivePeerDependencies: + - react + - react-dom + + '@clerk/clerk-react@5.59.2(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': + dependencies: + '@clerk/shared': 3.41.1(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) + tslib: 2.8.1 + + '@clerk/nextjs@6.36.5(next@16.1.1(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': + dependencies: + '@clerk/backend': 2.29.0(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@clerk/clerk-react': 5.59.2(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@clerk/shared': 3.41.1(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@clerk/types': 4.101.9(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + next: 16.1.1(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) + server-only: 0.0.1 + tslib: 2.8.1 + + '@clerk/shared@3.41.1(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': + dependencies: + csstype: 3.1.3 + dequal: 2.0.3 + glob-to-regexp: 0.4.1 + js-cookie: 3.0.5 + std-env: 3.10.0 + swr: 2.3.4(react@19.2.0) + optionalDependencies: + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) + + '@clerk/types@4.101.9(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': + dependencies: + '@clerk/shared': 3.41.1(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + transitivePeerDependencies: + - react + - react-dom + '@date-fns/tz@1.2.0': {} '@drizzle-team/brocli@0.10.2': {} @@ -3565,32 +3684,30 @@ snapshots: '@types/node': 22.19.3 '@types/pg': 8.16.0 - '@next/env@16.0.10': {} - '@next/env@16.1.1': {} - '@next/swc-darwin-arm64@16.0.10': + '@next/swc-darwin-arm64@16.1.1': optional: true - '@next/swc-darwin-x64@16.0.10': + '@next/swc-darwin-x64@16.1.1': optional: true - '@next/swc-linux-arm64-gnu@16.0.10': + '@next/swc-linux-arm64-gnu@16.1.1': optional: true - '@next/swc-linux-arm64-musl@16.0.10': + '@next/swc-linux-arm64-musl@16.1.1': optional: true - '@next/swc-linux-x64-gnu@16.0.10': + '@next/swc-linux-x64-gnu@16.1.1': optional: true - '@next/swc-linux-x64-musl@16.0.10': + '@next/swc-linux-x64-musl@16.1.1': optional: true - '@next/swc-win32-arm64-msvc@16.0.10': + '@next/swc-win32-arm64-msvc@16.1.1': optional: true - '@next/swc-win32-x64-msvc@16.0.10': + '@next/swc-win32-x64-msvc@16.1.1': optional: true '@radix-ui/number@1.1.0': {} @@ -4656,6 +4773,8 @@ snapshots: dependencies: tslib: 2.8.1 + '@stablelib/base64@1.0.1': {} + '@swc/helpers@0.5.15': dependencies: tslib: 2.8.1 @@ -4771,11 +4890,11 @@ snapshots: dependencies: csstype: 3.2.3 - '@vercel/analytics@1.3.1(next@16.0.10(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react@19.2.0)': + '@vercel/analytics@1.3.1(next@16.1.1(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react@19.2.0)': dependencies: server-only: 0.0.1 optionalDependencies: - next: 16.0.10(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + next: 16.1.1(react-dom@19.2.0(react@19.2.0))(react@19.2.0) react: 19.2.0 aria-hidden@1.2.6: @@ -4834,6 +4953,10 @@ snapshots: - '@types/react' - '@types/react-dom' + cookie@1.0.2: {} + + csstype@3.1.3: {} + csstype@3.2.3: {} d3-array@3.2.4: @@ -4884,6 +5007,8 @@ snapshots: decimal.js-light@2.5.1: {} + dequal@2.0.3: {} + detect-libc@2.1.2: {} detect-node-es@1.1.0: {} @@ -4995,6 +5120,8 @@ snapshots: fast-equals@5.4.0: {} + fast-sha256@1.3.0: {} + fast-xml-parser@5.2.5: dependencies: strnum: 2.1.2 @@ -5007,6 +5134,8 @@ snapshots: dependencies: resolve-pkg-maps: 1.0.0 + glob-to-regexp@0.4.1: {} + graceful-fs@4.2.11: {} ieee754@1.2.1: {} @@ -5022,6 +5151,8 @@ snapshots: jiti@2.6.1: {} + js-cookie@3.0.5: {} + js-tokens@4.0.0: {} lightningcss-android-arm64@1.30.2: @@ -5091,14 +5222,14 @@ snapshots: nanoid@3.3.11: {} - next-s3-upload@0.3.4(next@16.0.10(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react@19.2.0): + next-s3-upload@0.3.4(next@16.1.1(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react@19.2.0): dependencies: '@aws-sdk/client-s3': 3.957.0 '@aws-sdk/client-sts': 3.957.0 '@aws-sdk/lib-storage': 3.957.0(@aws-sdk/client-s3@3.957.0) '@aws-sdk/s3-request-presigner': 3.957.0 '@smithy/fetch-http-handler': 2.5.0 - next: 16.0.10(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + next: 16.1.1(react-dom@19.2.0(react@19.2.0))(react@19.2.0) react: 19.2.0 uuid: 8.3.2 transitivePeerDependencies: @@ -5109,24 +5240,25 @@ snapshots: react: 19.2.0 react-dom: 19.2.0(react@19.2.0) - next@16.0.10(react-dom@19.2.0(react@19.2.0))(react@19.2.0): + next@16.1.1(react-dom@19.2.0(react@19.2.0))(react@19.2.0): dependencies: - '@next/env': 16.0.10 + '@next/env': 16.1.1 '@swc/helpers': 0.5.15 + baseline-browser-mapping: 2.9.11 caniuse-lite: 1.0.30001761 postcss: 8.4.31 react: 19.2.0 react-dom: 19.2.0(react@19.2.0) styled-jsx: 5.1.6(react@19.2.0) optionalDependencies: - '@next/swc-darwin-arm64': 16.0.10 - '@next/swc-darwin-x64': 16.0.10 - '@next/swc-linux-arm64-gnu': 16.0.10 - '@next/swc-linux-arm64-musl': 16.0.10 - '@next/swc-linux-x64-gnu': 16.0.10 - '@next/swc-linux-x64-musl': 16.0.10 - '@next/swc-win32-arm64-msvc': 16.0.10 - '@next/swc-win32-x64-msvc': 16.0.10 + '@next/swc-darwin-arm64': 16.1.1 + '@next/swc-darwin-x64': 16.1.1 + '@next/swc-linux-arm64-gnu': 16.1.1 + '@next/swc-linux-arm64-musl': 16.1.1 + '@next/swc-linux-x64-gnu': 16.1.1 + '@next/swc-linux-x64-musl': 16.1.1 + '@next/swc-win32-arm64-msvc': 16.1.1 + '@next/swc-win32-x64-msvc': 16.1.1 sharp: 0.34.5 transitivePeerDependencies: - '@babel/core' @@ -5331,6 +5463,13 @@ snapshots: source-map@0.6.1: {} + standardwebhooks@1.0.0: + dependencies: + '@stablelib/base64': 1.0.1 + fast-sha256: 1.3.0 + + std-env@3.10.0: {} + stream-browserify@3.0.0: dependencies: inherits: 2.0.4 @@ -5347,6 +5486,12 @@ snapshots: client-only: 0.0.1 react: 19.2.0 + swr@2.3.4(react@19.2.0): + dependencies: + dequal: 2.0.3 + react: 19.2.0 + use-sync-external-store: 1.6.0(react@19.2.0) + tailwind-merge@3.4.0: {} tailwindcss-animate@1.0.7(tailwindcss@4.1.18): diff --git a/proxy.ts b/proxy.ts new file mode 100644 index 0000000..b102452 --- /dev/null +++ b/proxy.ts @@ -0,0 +1,12 @@ +import { clerkMiddleware } from "@clerk/nextjs/server"; + +export default clerkMiddleware(); + +export const config = { + matcher: [ + // Skip Next.js internals and all static files, unless found in search params + "/((?!_next|[^?]*\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).*)", + // Always run for API routes + "/(api|trpc)(.*)", + ], +}; \ No newline at end of file