From 54376ff66d36607761d3f369254e09f14102b9cc Mon Sep 17 00:00:00 2001 From: Cho Young-Hwi Date: Thu, 26 Mar 2026 08:56:31 +0000 Subject: [PATCH 1/3] [#558] Fix stale language filter by disabling Next.js Data Cache Supabase PostgREST queries go through fetch(), which Next.js caches via its Data Cache. With revalidate=120, filtered query results (e.g. ?lang=English) served stale data after DB migrations updated language values. Adding cache:'no-store' to the server Supabase client ensures queries always hit the DB. Co-Authored-By: Claude Opus 4.6 (1M context) --- lib/supabase.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/supabase.ts b/lib/supabase.ts index 8a7e7d62..a9d4adf0 100644 --- a/lib/supabase.ts +++ b/lib/supabase.ts @@ -25,6 +25,9 @@ export function createServiceRoleClient(): SupabaseClient | null { autoRefreshToken: false, persistSession: false, }, + global: { + fetch: (url, options) => fetch(url, { ...options, cache: "no-store" }), + }, }); } From a2599a7488c76021f9fd1f0a5cf3cc41b5246b1e Mon Sep 17 00:00:00 2001 From: Cho Young-Hwi Date: Thu, 26 Mar 2026 09:02:58 +0000 Subject: [PATCH 2/3] [#276] Narrow cache bypass to homepage only via connection() Revert global Supabase cache:'no-store' per T2a review. Instead use Next.js connection() in the homepage component to opt that route out of the Data Cache while leaving other routes (story pages, OG, etc.) unaffected. Co-Authored-By: Claude Opus 4.6 (1M context) --- lib/supabase.ts | 3 --- src/app/page.tsx | 6 ++++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/lib/supabase.ts b/lib/supabase.ts index a9d4adf0..8a7e7d62 100644 --- a/lib/supabase.ts +++ b/lib/supabase.ts @@ -25,9 +25,6 @@ export function createServiceRoleClient(): SupabaseClient | null { autoRefreshToken: false, persistSession: false, }, - global: { - fetch: (url, options) => fetch(url, { ...options, cache: "no-store" }), - }, }); } diff --git a/src/app/page.tsx b/src/app/page.tsx index 70f6717b..0f04ed20 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -4,10 +4,9 @@ import { getTrendingStorylines } from "../../lib/ranking"; import { StoryGrid } from "../components/StoryGrid"; import { FilterBar, type WriterFilterValue } from "../components/FilterBar"; import { GENRES, LANGUAGES } from "../../lib/genres"; +import { connection } from "next/server"; import Link from "next/link"; -export const revalidate = 120; - const TABS = ["new", "trending"] as const; type Tab = (typeof TABS)[number]; @@ -22,6 +21,9 @@ export default async function Home({ }: { searchParams: SearchParams; }) { + // Opt out of Next.js Data Cache so filtered queries always hit the DB + await connection(); + const { tab: rawTab, writer: rawWriter, page: rawPage, genre: rawGenre, lang: rawLang } = await searchParams; const tab: Tab = TABS.includes(rawTab as Tab) ? (rawTab as Tab) : "new"; const writer: WriterFilterValue = WRITER_VALUES.includes( From 63e9e1db904197194fb7004ed7d4219ba021546f Mon Sep 17 00:00:00 2001 From: Cho Young-Hwi Date: Thu, 26 Mar 2026 09:08:34 +0000 Subject: [PATCH 3/3] =?UTF-8?q?[#276]=20Remove=20redundant=20connection()?= =?UTF-8?q?=20=E2=80=94=20fix=20is=20removing=20revalidate?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per T2a review: connection() is redundant since searchParams already makes the page dynamic. The actual fix is removing revalidate=120 (done in the first commit), which caused ISR to cache each filter combo's rendered output including stale DB query results. Co-Authored-By: Claude Opus 4.6 (1M context) --- src/app/page.tsx | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/app/page.tsx b/src/app/page.tsx index 0f04ed20..47093e50 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -4,7 +4,6 @@ import { getTrendingStorylines } from "../../lib/ranking"; import { StoryGrid } from "../components/StoryGrid"; import { FilterBar, type WriterFilterValue } from "../components/FilterBar"; import { GENRES, LANGUAGES } from "../../lib/genres"; -import { connection } from "next/server"; import Link from "next/link"; const TABS = ["new", "trending"] as const; @@ -21,9 +20,6 @@ export default async function Home({ }: { searchParams: SearchParams; }) { - // Opt out of Next.js Data Cache so filtered queries always hit the DB - await connection(); - const { tab: rawTab, writer: rawWriter, page: rawPage, genre: rawGenre, lang: rawLang } = await searchParams; const tab: Tab = TABS.includes(rawTab as Tab) ? (rawTab as Tab) : "new"; const writer: WriterFilterValue = WRITER_VALUES.includes(