From b95cebc7992550a82652845a351402e7042e6cb5 Mon Sep 17 00:00:00 2001 From: Gabriel Kaszewski Date: Thu, 14 May 2026 17:28:35 +0200 Subject: [PATCH] fix: await searchParams and params for Next.js 15 async API, compute totalPages in all-users page --- .env | 29 +++++++++++++++---- thoughts-frontend/app/page.tsx | 5 ++-- thoughts-frontend/app/search/page.tsx | 5 ++-- thoughts-frontend/app/tags/[tagName]/page.tsx | 4 +-- .../app/thoughts/[thoughtId]/page.tsx | 4 +-- .../app/users/[username]/followers/page.tsx | 4 +-- .../app/users/[username]/following/page.tsx | 4 +-- .../app/users/[username]/page.tsx | 4 +-- thoughts-frontend/app/users/all/page.tsx | 8 +++-- 9 files changed, 44 insertions(+), 23 deletions(-) diff --git a/.env b/.env index 358ba6c..19fd8e3 100644 --- a/.env +++ b/.env @@ -1,10 +1,27 @@ -POSTGRES_USER=thoughts_user +POSTGRES_USER=postgres POSTGRES_PASSWORD=postgres -POSTGRES_DB=thoughts_db +POSTGRES_DB=thoughts HOST=0.0.0.0 PORT=8000 -DATABASE_URL="postgresql://thoughts_user:postgres@database/thoughts_db" -PREFORK=1 -AUTH_SECRET=secret -BASE_URL=http://0.0.0.0 \ No newline at end of file +DATABASE_URL="postgresql://postgres:postgres@localhost:5432/thoughts" +JWT_SECRET=secret + +# Public base URL — used for ActivityPub actor URLs and canonical links +BASE_URL=http://localhost:8000 + +# CORS — comma-separated allowed origins, or * for permissive (default: *) +CORS_ORIGINS=* +# CORS_ORIGINS=https://your-nextjs-app.example.com + +# Rate limiting — max requests per minute per IP (disabled by default) +# RATE_LIMIT=60 +ALLOW_REGISTRATION=true # set to false to disable new sign-ups +RUST_ENV=development # set to "production" to disable AP debug mode + +# NATS event bus (optional — federation and notifications still work without it, +# but events will not be delivered to the worker) +NATS_URL=nats://localhost:4222 + +# Logging +RUST_LOG=info \ No newline at end of file diff --git a/thoughts-frontend/app/page.tsx b/thoughts-frontend/app/page.tsx index 39a3dea..039cd02 100644 --- a/thoughts-frontend/app/page.tsx +++ b/thoughts-frontend/app/page.tsx @@ -29,12 +29,13 @@ import { redirect } from "next/navigation"; export default async function Home({ searchParams, }: { - searchParams: { page?: string }; + searchParams: Promise<{ page?: string }>; }) { const token = (await cookies()).get("auth_token")?.value ?? null; + const resolvedSearchParams = await searchParams; if (token) { - return ; + return ; } else { return ; } diff --git a/thoughts-frontend/app/search/page.tsx b/thoughts-frontend/app/search/page.tsx index 50d1270..c794bbd 100644 --- a/thoughts-frontend/app/search/page.tsx +++ b/thoughts-frontend/app/search/page.tsx @@ -5,11 +5,12 @@ import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { ThoughtList } from "@/components/thought-list"; interface SearchPageProps { - searchParams: { q?: string }; + searchParams: Promise<{ q?: string }>; } export default async function SearchPage({ searchParams }: SearchPageProps) { - const query = searchParams.q || ""; + const { q } = await searchParams; + const query = q || ""; const token = (await cookies()).get("auth_token")?.value ?? null; if (!query) { diff --git a/thoughts-frontend/app/tags/[tagName]/page.tsx b/thoughts-frontend/app/tags/[tagName]/page.tsx index 6d38a90..5626551 100644 --- a/thoughts-frontend/app/tags/[tagName]/page.tsx +++ b/thoughts-frontend/app/tags/[tagName]/page.tsx @@ -7,11 +7,11 @@ import { notFound } from "next/navigation"; import { Hash } from "lucide-react"; interface TagPageProps { - params: { tagName: string }; + params: Promise<{ tagName: string }>; } export default async function TagPage({ params }: TagPageProps) { - const { tagName } = params; + const { tagName } = await params; const token = (await cookies()).get("auth_token")?.value ?? null; const [thoughtsResult, meResult] = await Promise.allSettled([ diff --git a/thoughts-frontend/app/thoughts/[thoughtId]/page.tsx b/thoughts-frontend/app/thoughts/[thoughtId]/page.tsx index 779ad7b..b9ca875 100644 --- a/thoughts-frontend/app/thoughts/[thoughtId]/page.tsx +++ b/thoughts-frontend/app/thoughts/[thoughtId]/page.tsx @@ -11,7 +11,7 @@ import { ThoughtThread } from "@/components/thought-thread"; import { notFound } from "next/navigation"; interface ThoughtPageProps { - params: { thoughtId: string }; + params: Promise<{ thoughtId: string }>; } function collectAuthors(thread: ThoughtThreadType): string[] { @@ -23,7 +23,7 @@ function collectAuthors(thread: ThoughtThreadType): string[] { } export default async function ThoughtPage({ params }: ThoughtPageProps) { - const { thoughtId } = params; + const { thoughtId } = await params; const token = (await cookies()).get("auth_token")?.value ?? null; const [threadResult, meResult] = await Promise.allSettled([ diff --git a/thoughts-frontend/app/users/[username]/followers/page.tsx b/thoughts-frontend/app/users/[username]/followers/page.tsx index cbcefb5..02be5d6 100644 --- a/thoughts-frontend/app/users/[username]/followers/page.tsx +++ b/thoughts-frontend/app/users/[username]/followers/page.tsx @@ -4,11 +4,11 @@ import { getFollowersList } from "@/lib/api"; import { UserListCard } from "@/components/user-list-card"; interface FollowersPageProps { - params: { username: string }; + params: Promise<{ username: string }>; } export default async function FollowersPage({ params }: FollowersPageProps) { - const { username } = params; + const { username } = await params; const token = (await cookies()).get("auth_token")?.value ?? null; const followersData = await getFollowersList(username, token).catch( diff --git a/thoughts-frontend/app/users/[username]/following/page.tsx b/thoughts-frontend/app/users/[username]/following/page.tsx index c59d0d6..00a05ed 100644 --- a/thoughts-frontend/app/users/[username]/following/page.tsx +++ b/thoughts-frontend/app/users/[username]/following/page.tsx @@ -4,11 +4,11 @@ import { getFollowingList } from "@/lib/api"; import { UserListCard } from "@/components/user-list-card"; interface FollowingPageProps { - params: { username: string }; + params: Promise<{ username: string }>; } export default async function FollowingPage({ params }: FollowingPageProps) { - const { username } = params; + const { username } = await params; const token = (await cookies()).get("auth_token")?.value ?? null; const followingData = await getFollowingList(username, token).catch( diff --git a/thoughts-frontend/app/users/[username]/page.tsx b/thoughts-frontend/app/users/[username]/page.tsx index b0b87cf..8820fd2 100644 --- a/thoughts-frontend/app/users/[username]/page.tsx +++ b/thoughts-frontend/app/users/[username]/page.tsx @@ -21,11 +21,11 @@ import { Button } from "@/components/ui/button"; import Link from "next/link"; interface ProfilePageProps { - params: { username: string }; + params: Promise<{ username: string }>; } export default async function ProfilePage({ params }: ProfilePageProps) { - const { username } = params; + const { username } = await params; const token = (await cookies()).get("auth_token")?.value ?? null; const userProfilePromise = getUserProfile(username, token); diff --git a/thoughts-frontend/app/users/all/page.tsx b/thoughts-frontend/app/users/all/page.tsx index 077b3ca..24d8fbe 100644 --- a/thoughts-frontend/app/users/all/page.tsx +++ b/thoughts-frontend/app/users/all/page.tsx @@ -11,9 +11,10 @@ import { export default async function AllUsersPage({ searchParams, }: { - searchParams: { page?: string }; + searchParams: Promise<{ page?: string }>; }) { - const page = parseInt(searchParams.page ?? "1", 10); + const { page: pageStr } = await searchParams; + const page = parseInt(pageStr ?? "1", 10); const usersData = await getAllUsers(page).catch(() => null); if (!usersData) { @@ -27,7 +28,8 @@ export default async function AllUsersPage({ ); } - const { items, totalPages } = usersData; + const { items, total, perPage } = usersData; + const totalPages = Math.ceil(total / perPage); return (