From f6b52f7c2dce0e3a7be00eaeeaa438466154429b Mon Sep 17 00:00:00 2001 From: Ryan Salazar Date: Wed, 20 May 2026 12:56:56 +0000 Subject: [PATCH] forum: user profile pages + clickable bylines + neon pulse favicon MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit USER PROFILES (/forum/user/[username]): - New API at /api/forum/user-by-username/[username] resolves by username OR display_name (URL-encoded), since forum threads/replies store author_name = display_name. Returns the persona's profile, thread history (up to 50), and recent replies (up to 20). - New page renders the persona card with archetype badge (Audio Engineer / Colorist / etc.) + expertise level badge (beginner/intermediate/senior) + role title, company, location, years_experience, join date, and an expertise-tags chip row. - Two columns underneath: "Threads started" and "Recent replies" with proper deep-links into each thread. - Author names in /forum, /forum/[slug], and /forum/thread/[id] are now elements pointing to /forum/user/, with onClick=stopPropagation so the card-level click handler doesn't also fire. FAVICON: - Hand-built neon pulse waveform — emerald→cyan→purple gradient on dark navy background, designed to read at 16×16 to 256×256. - Multi-resolution favicon.ico (16/32/48/64) + SVG + PNGs at 16/32/48/64/96/192/256 under /static/favicons/. - layout.tsx icons block now references all sizes including the apple-touch sizes (192, 256). No env / DB changes here — pure deploy. --- public/favicon.ico | Bin 4158 -> 32038 bytes public/static/favicons/favicon-16.png | Bin 0 -> 483 bytes public/static/favicons/favicon-192.png | Bin 0 -> 12226 bytes public/static/favicons/favicon-256.png | Bin 0 -> 19041 bytes public/static/favicons/favicon-32.png | Bin 0 -> 1044 bytes public/static/favicons/favicon-48.png | Bin 0 -> 1720 bytes public/static/favicons/favicon-64.png | Bin 0 -> 2490 bytes public/static/favicons/favicon-96.png | Bin 0 -> 4476 bytes public/static/favicons/favicon.svg | 34 +++ .../user-by-username/[username]/route.ts | 94 +++++++ src/app/forum/[slug]/page.tsx | 4 +- src/app/forum/page.tsx | 4 +- src/app/forum/thread/[id]/page.tsx | 4 +- src/app/forum/user/[username]/page.tsx | 264 ++++++++++++++++++ src/app/layout.tsx | 11 +- 15 files changed, 407 insertions(+), 8 deletions(-) create mode 100644 public/static/favicons/favicon-16.png create mode 100644 public/static/favicons/favicon-192.png create mode 100644 public/static/favicons/favicon-256.png create mode 100644 public/static/favicons/favicon-32.png create mode 100644 public/static/favicons/favicon-48.png create mode 100644 public/static/favicons/favicon-64.png create mode 100644 public/static/favicons/favicon-96.png create mode 100644 public/static/favicons/favicon.svg create mode 100644 src/app/api/forum/user-by-username/[username]/route.ts create mode 100644 src/app/forum/user/[username]/page.tsx diff --git a/public/favicon.ico b/public/favicon.ico index 4eb44dd0bbb02aa4199dec871f72fa91ef239e5f..2744e3b7de14a3ba1e19adeee44c6093019799e1 100644 GIT binary patch literal 32038 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 literal 4158 zcmchaKaWgN7>Cc;uoMgugs`)r*+e0sXNYg0(ym0Iu|c7-w?#)(5`Q8RS_KNlbR_ry z1ldYMn1*a(-RpT~?a+Q8|Jo$useh> z2MuU~d6m>VL-}Q%#4R`vO*jZ!p$1h*AN}-gf_>~a4_6?AKkySiK@0A|RX77jVJ~cf zL2}-8$G|%4^=W~=ZLp91F2ezMk;mrBtdRQwAK(?-g#;GhLOvRsciwgG!Md_nH-66C zeozf~2Hm-sqkZgG)INfzkV1^!`s#0=UfMy>xC zb>nIZgPSnyz2`dDTUUh+Ve%1r?XjG5o$ITT-vsKi6vlu(? zx~jDiL(jxwuk!Ctn0H+aox`->d28P9^kco0gn gP+KLLN;7Fqud-B6vm)(AniW|-k!EF97Sk-}ANdH0x&QzG diff --git a/public/static/favicons/favicon-16.png b/public/static/favicons/favicon-16.png new file mode 100644 index 0000000000000000000000000000000000000000..f86d26cd5e4726bb91fd31011e6b2a6e81f84ee5 GIT binary patch literal 483 zcmV<90UZ8`P)9+!Pd1Czra2I2D}R!FH%y zU3BeVQCw6gZ52fq5iz>dF{L61R&bC~wNn)94SMnBejJCWpxk`)8Q+)R^StNb2vVsA zRdhZfcm*V>O$9V-u6gr8sJiF^g4Z>IkENLxDi*c=Bl(Gh6{!Y$tDo`KX3CwAlGQSF zS1U-j>^>4U^gmAG9&CY>5ceVOqT4bx8c0bnHUeou@Maj44bn!B_Sa_MPmPsQl}#`{ zR5DOk1cM!+2153BYj5K#s3I6ekPck`gJk4x=8!mcNuHY|tpqJrnp8eYI&ZQy_ZBHm zPKaz~(P>pGOM4j8t9W1DLsOj0Z-ZFwg68IS8uHI@a=-8|C560$b@3OWVo@D-nzuAX zYeye-`xbgVN7ukRj+bUR___GFve1VCjoBlfn=fJal)dF|*xNgtogG#$@m|I34_^GK z$KN{w2!#PEe&tN2vn+UrTZSQJH-et9wQZkQfC0^l5hT3th9}z)v;$^k;z0#8%dUAd ZaSM6WjAt3d6I}oR002ovPDHLkV1gPR&-4HQ literal 0 HcmV?d00001 diff --git a/public/static/favicons/favicon-192.png b/public/static/favicons/favicon-192.png new file mode 100644 index 0000000000000000000000000000000000000000..1f3b4cbe8b84c22938e0a6048a1d19201c4c7114 GIT binary patch literal 12226 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 literal 0 HcmV?d00001 diff --git a/public/static/favicons/favicon-256.png b/public/static/favicons/favicon-256.png new file mode 100644 index 0000000000000000000000000000000000000000..80e5881d20ef28ebd740ed9dc395ee1d7ab85d90 GIT binary patch literal 19041 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 D{#$?{ literal 0 HcmV?d00001 diff --git a/public/static/favicons/favicon-32.png b/public/static/favicons/favicon-32.png new file mode 100644 index 0000000000000000000000000000000000000000..df578f6a473bbe7c5fa5c826d5841d196120ab67 GIT binary patch literal 1044 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 Eg1@!Un*aa+ literal 0 HcmV?d00001 diff --git a/public/static/favicons/favicon-96.png b/public/static/favicons/favicon-96.png new file mode 100644 index 0000000000000000000000000000000000000000..ff49d1f37ae7bf21988256c50bc386a0bad1cf46 GIT binary patch literal 4476 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 O0000 + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/app/api/forum/user-by-username/[username]/route.ts b/src/app/api/forum/user-by-username/[username]/route.ts new file mode 100644 index 0000000..a70950a --- /dev/null +++ b/src/app/api/forum/user-by-username/[username]/route.ts @@ -0,0 +1,94 @@ +import { NextResponse } from "next/server"; +import { createClient } from "@supabase/supabase-js"; + +export const runtime = "nodejs"; +export const revalidate = 120; + +const SUPABASE_URL = process.env.NEXT_PUBLIC_SUPABASE_URL!; +const SUPABASE_ANON = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!; +const SCHEMA = process.env.NEXT_PUBLIC_SUPABASE_SCHEMA || "bb"; + +function client() { + return createClient(SUPABASE_URL, SUPABASE_ANON, { + db: { schema: SCHEMA as "public" }, + auth: { persistSession: false }, + }); +} + +export async function GET( + req: Request, + { params }: { params: Promise<{ username: string }> }, +) { + const { username } = await params; + const sb = client(); + + // 1) Profile — accept EITHER username OR display_name (URL-encoded). + // forum_threads/forum_replies store author_name = display_name, + // so the link in the UI uses the display name; we resolve it here. + const decoded = decodeURIComponent(username); + let { data: profile } = await sb + .from("forum_user_profiles") + .select("*") + .eq("username", decoded) + .maybeSingle(); + if (!profile) { + const r2 = await sb + .from("forum_user_profiles") + .select("*") + .eq("display_name", decoded) + .maybeSingle(); + profile = r2.data; + } + + if (!profile) { + return NextResponse.json({ error: "not found" }, { status: 404 }); + } + + // 2) Their threads (use display_name match since virtual users live + // outside the auth.users / bb.user_profiles graph and the + // forum_threads.author_id is NULL for them). + const displayName = (profile as any).display_name as string; + const { data: threads } = await sb + .from("forum_threads") + .select("id,title,reply_count,view_count,vote_score,created_at,category_id,forum_categories(name,slug)") + .eq("author_name", displayName) + .order("created_at", { ascending: false }) + .limit(50); + + // 3) Recent replies + const { data: replies } = await sb + .from("forum_replies") + .select("id,thread_id,body,vote_score,created_at,forum_threads(title)") + .eq("author_name", displayName) + .order("created_at", { ascending: false }) + .limit(20); + + // 4) Computed counts + const threadCount = (threads || []).length; + const replyCount = (replies || []).length; + + return NextResponse.json({ + profile: { + username: (profile as any).username, + display_name: (profile as any).display_name, + bio: (profile as any).bio || null, + avatar_url: (profile as any).avatar_url || null, + role_title: (profile as any).role_title || null, + company: (profile as any).company || null, + location_city: (profile as any).location_city || null, + location_country: (profile as any).location_country || null, + years_experience: (profile as any).years_experience || null, + ai_persona_archetype: (profile as any).ai_persona_archetype || null, + expertise_level: (profile as any).expertise_level || null, + expertise_tags: (profile as any).expertise_tags || [], + writing_voice: (profile as any).writing_voice || null, + signature: (profile as any).signature || null, + join_date: (profile as any).join_date || null, + last_seen_at: (profile as any).last_seen_at || null, + thread_count: threadCount, + reply_count: replyCount, + }, + threads: threads || [], + replies: replies || [], + }); +} diff --git a/src/app/forum/[slug]/page.tsx b/src/app/forum/[slug]/page.tsx index 0c5bc52..37ffd3d 100644 --- a/src/app/forum/[slug]/page.tsx +++ b/src/app/forum/[slug]/page.tsx @@ -144,7 +144,7 @@ function TopThreadsWidget({ categoryId }: { categoryId: string }) { {thread.title}

- {thread.author_name} + e.stopPropagation()}>{thread.author_name} {' · '}{timeAgo(thread.created_at)}

@@ -441,7 +441,7 @@ export default function ForumCategoryPage() {

- by {thread.author_name} + by e.stopPropagation()}>{thread.author_name} {' · '}{timeAgo(thread.created_at)}

diff --git a/src/app/forum/page.tsx b/src/app/forum/page.tsx index 2a49009..bc41473 100644 --- a/src/app/forum/page.tsx +++ b/src/app/forum/page.tsx @@ -153,7 +153,7 @@ function TopThreadsWidget({ categoryId }: { categoryId?: string }) { {thread.title}

- {thread.author_name} + e.stopPropagation()}>{thread.author_name} {thread.forum_categories && ( <> · {thread.forum_categories.name} )} @@ -483,7 +483,7 @@ export default function ForumIndexPage() { {thread.title}

- by {thread.author_name} + by e.stopPropagation()}>{thread.author_name} {thread.forum_categories && ( <> · {thread.forum_categories.name} )} diff --git a/src/app/forum/thread/[id]/page.tsx b/src/app/forum/thread/[id]/page.tsx index 0316ab2..99ccf2a 100644 --- a/src/app/forum/thread/[id]/page.tsx +++ b/src/app/forum/thread/[id]/page.tsx @@ -354,7 +354,7 @@ export default function ForumThreadPage() {

- {thread.author_name} + {thread.author_name} · {timeAgo(thread.created_at)} · @@ -389,7 +389,7 @@ export default function ForumThreadPage() {
- {reply.author_name} + {reply.author_name} {reply.is_ai_response && ( AI Assistant diff --git a/src/app/forum/user/[username]/page.tsx b/src/app/forum/user/[username]/page.tsx new file mode 100644 index 0000000..ff364c8 --- /dev/null +++ b/src/app/forum/user/[username]/page.tsx @@ -0,0 +1,264 @@ +"use client"; + +import React, { useEffect, useState } from "react"; +import { useParams } from "next/navigation"; +import Link from "next/link"; +import Header from "@/components/Header"; +import Footer from "@/components/Footer"; +import AppImage from "@/components/ui/AppImage"; + +interface ForumUserProfile { + username: string; + display_name: string; + bio: string | null; + avatar_url: string | null; + role_title: string | null; + company: string | null; + location_city: string | null; + location_country: string | null; + years_experience: number | null; + ai_persona_archetype: string | null; + expertise_level: string | null; + expertise_tags: string[]; + writing_voice: string | null; + signature: string | null; + join_date: string | null; + last_seen_at: string | null; + thread_count: number; + reply_count: number; +} + +interface UserThread { + id: string; + title: string; + reply_count: number; + view_count: number; + vote_score: number; + created_at: string; + forum_categories?: { name: string; slug: string }; +} + +interface UserReply { + id: string; + thread_id: string; + body: string; + vote_score: number; + created_at: string; + forum_threads?: { title: string }; +} + +const ARCHETYPE_LABELS: Record = { + audio_engineer: "Audio Engineer", + motion_designer: "Motion Designer", + broadcast_engineer: "Broadcast Engineer", + colorist: "Colorist", + editor: "Editor", + vfx_artist: "VFX Artist", + camera_operator: "Camera Operator", + lighting_designer: "Lighting Designer", + post_supervisor: "Post Supervisor", + gear_specialist: "Gear Specialist", + livestream_producer: "Livestream Producer", + generalist: "Generalist", + video_editor: "Video Editor", +}; + +function fmtDate(iso: string | null): string { + if (!iso) return "—"; + try { + return new Date(iso).toLocaleDateString("en-US", { month: "long", year: "numeric" }); + } catch { return iso.slice(0, 10); } +} + +export default function ForumUserPage() { + const params = useParams(); + const username = params?.username as string; + const [data, setData] = useState<{ profile: ForumUserProfile; threads: UserThread[]; replies: UserReply[] } | null>(null); + const [loading, setLoading] = useState(true); + const [notFound, setNotFound] = useState(false); + + useEffect(() => { + if (!username) return; + setLoading(true); + fetch(`/api/forum/user-by-username/${encodeURIComponent(username)}`, { cache: "no-store" }) + .then(async (r) => { + if (r.status === 404) { setNotFound(true); return null; } + if (!r.ok) return null; + return r.json(); + }) + .then((d) => { if (d) setData(d); }) + .finally(() => setLoading(false)); + }, [username]); + + if (loading) { + return ( + <> +
+
+
+

Loading profile…

+
+
+