From efa50fd3e8610ec2a1c67e4cf71ba2d7bcb00767 Mon Sep 17 00:00:00 2001 From: Nabil Akbarazzima Fatih Date: Thu, 9 Apr 2026 21:56:10 +0200 Subject: [PATCH 01/20] Refactor locale loading and defer client widgets Replace setRequestLocale and client-side use(params) across many pages with server-side next-intl APIs (getLocale/getTranslations) and update the internationalization getRequestConfig to resolve locale from root params and return 404 for invalid locales Add DeferredAiSheetOpen and DeferredComments dynamic client components and minimal Loading placeholders. Rename not-found to global-not-found and add metadata. Move providers into app shell, enable cacheComponents, and add cacheLife imports. Bump next in internationalization package and update pnpm lock --- .../(app)/(dynamic)/(core)/chat/[id]/page.tsx | 15 +- .../(app)/(dynamic)/(core)/chat/layout.tsx | 16 +- .../(app)/(dynamic)/(core)/chat/page.tsx | 14 +- .../(app)/(dynamic)/(core)/layout.tsx | 15 +- .../(app)/(dynamic)/(core)/search/page.tsx | 2 - .../[locale]/(app)/(dynamic)/auth/page.tsx | 15 +- .../app/[locale]/(app)/(dynamic)/layout.tsx | 20 +- .../app/[locale]/(app)/(dynamic)/loading.tsx | 3 + .../try-out/[product]/[slug]/page.tsx | 3 +- .../[product]/[slug]/part/[partKey]/page.tsx | 3 +- .../(dynamic)/try-out/[product]/page.tsx | 4 +- .../articles/[category]/[slug]/layout.tsx | 3 - .../articles/[category]/[slug]/page.tsx | 120 +++++++----- .../(learn)/articles/[category]/page.tsx | 13 +- .../[type]/[material]/[...slug]/page.tsx | 79 +++++--- .../[category]/[type]/[material]/page.tsx | 2 - .../exercises/[category]/[type]/page.tsx | 2 - .../(app)/(static)/(learn)/layout.tsx | 3 - .../(static)/(learn)/quran/[surah]/page.tsx | 102 ++++++---- .../(app)/(static)/(learn)/quran/page.tsx | 2 - .../[grade]/[material]/[...slug]/page.tsx | 177 ++++++++++-------- .../[category]/[grade]/[material]/page.tsx | 2 - .../subject/[category]/[grade]/page.tsx | 2 - .../(app)/(static)/(learn)/subject/page.tsx | 2 - .../(site)/(legal)/privacy-policy/page.tsx | 3 - .../(site)/(legal)/security-policy/page.tsx | 3 - .../(site)/(legal)/terms-of-service/page.tsx | 3 - .../(app)/(static)/(site)/about/page.tsx | 3 - .../(app)/(static)/(site)/ask/[slug]/page.tsx | 3 - .../(static)/(site)/contributor/page.tsx | 3 - .../(app)/(static)/(site)/events/page.tsx | 3 - .../[locale]/(app)/(static)/(site)/layout.tsx | 22 +-- .../app/[locale]/(app)/(static)/layout.tsx | 3 - apps/www/app/[locale]/(app)/layout.tsx | 3 - apps/www/app/[locale]/(app)/loading.tsx | 3 + apps/www/app/[locale]/[...rest]/page.tsx | 15 +- apps/www/app/[locale]/layout.tsx | 33 +--- apps/www/app/[locale]/og/[...slug]/route.tsx | 3 - apps/www/app/api/chat/route.ts | 2 +- .../{not-found.tsx => global-not-found.tsx} | 8 +- apps/www/app/layout.tsx | 8 - apps/www/app/llms.mdx/[...slug]/route.ts | 3 - apps/www/app/llms.txt/route.ts | 2 - apps/www/app/og/[...slug]/route.tsx | 3 - apps/www/app/rss.xml/route.ts | 2 - .../www/components/ai/deferred-sheet-open.tsx | 12 ++ apps/www/components/comments/deferred.tsx | 11 ++ apps/www/components/sidebar/app-shell.tsx | 27 +-- apps/www/components/tryout/hub-page.tsx | 4 +- apps/www/lib/utils/seo/generator.ts | 5 + apps/www/next.config.ts | 6 + packages/internationalization/package.json | 1 + packages/internationalization/src/request.ts | 24 ++- pnpm-lock.yaml | 13 +- 54 files changed, 443 insertions(+), 410 deletions(-) create mode 100644 apps/www/app/[locale]/(app)/(dynamic)/loading.tsx create mode 100644 apps/www/app/[locale]/(app)/loading.tsx rename apps/www/app/{not-found.tsx => global-not-found.tsx} (91%) delete mode 100644 apps/www/app/layout.tsx create mode 100644 apps/www/components/ai/deferred-sheet-open.tsx create mode 100644 apps/www/components/comments/deferred.tsx diff --git a/apps/www/app/[locale]/(app)/(dynamic)/(core)/chat/[id]/page.tsx b/apps/www/app/[locale]/(app)/(dynamic)/(core)/chat/[id]/page.tsx index 708828918..8642175e6 100644 --- a/apps/www/app/[locale]/(app)/(dynamic)/(core)/chat/[id]/page.tsx +++ b/apps/www/app/[locale]/(app)/(dynamic)/(core)/chat/[id]/page.tsx @@ -2,11 +2,9 @@ import { api } from "@repo/backend/convex/_generated/api"; import type { Id } from "@repo/backend/convex/_generated/dataModel"; import { fetchQuery } from "convex/nextjs"; import type { Metadata } from "next"; -import { setRequestLocale } from "next-intl/server"; -import { cache, use } from "react"; +import { cache } from "react"; import { AiChatPage } from "@/components/ai/chat-page"; import { getToken } from "@/lib/auth/server"; -import { getLocaleOrThrow } from "@/lib/i18n/params"; const getChatTitle = cache(async (id: Id<"chats">) => { const token = await getToken(); @@ -41,13 +39,10 @@ export async function generateMetadata({ } } -export default function Page(props: PageProps<"/[locale]/chat/[id]">) { - const { params } = props; - const { locale: rawLocale, id } = use(params); - const locale = getLocaleOrThrow(rawLocale); - - // Enable static rendering - setRequestLocale(locale); +export default async function Page({ + params, +}: PageProps<"/[locale]/chat/[id]">) { + const { id } = await params; return } />; } diff --git a/apps/www/app/[locale]/(app)/(dynamic)/(core)/chat/layout.tsx b/apps/www/app/[locale]/(app)/(dynamic)/(core)/chat/layout.tsx index f563aeaf2..8e8cffa44 100644 --- a/apps/www/app/[locale]/(app)/(dynamic)/(core)/chat/layout.tsx +++ b/apps/www/app/[locale]/(app)/(dynamic)/(core)/chat/layout.tsx @@ -1,22 +1,8 @@ import { ErrorBoundary } from "@repo/design-system/components/ui/error-boundary"; -import { routing } from "@repo/internationalization/src/routing"; -import { notFound } from "next/navigation"; -import { hasLocale } from "next-intl"; -import { setRequestLocale } from "next-intl/server"; -import { use } from "react"; import { AiChatSidebar } from "@/components/ai/chat-sidebar"; export default function Layout(props: LayoutProps<"/[locale]/chat">) { - const { children, params } = props; - const { locale } = use(params); - if (!hasLocale(routing.locales, locale)) { - // Ensure that the incoming `locale` is valid - notFound(); - } - - // Enable static rendering - setRequestLocale(locale); - + const { children } = props; return (
diff --git a/apps/www/app/[locale]/(app)/(dynamic)/(core)/chat/page.tsx b/apps/www/app/[locale]/(app)/(dynamic)/(core)/chat/page.tsx index 1fd4bb3ec..662ed7da5 100644 --- a/apps/www/app/[locale]/(app)/(dynamic)/(core)/chat/page.tsx +++ b/apps/www/app/[locale]/(app)/(dynamic)/(core)/chat/page.tsx @@ -1,22 +1,10 @@ import { Particles } from "@repo/design-system/components/ui/particles"; -import { setRequestLocale } from "next-intl/server"; -import { use } from "react"; import { ChatNew } from "@/components/ai/chat-new"; import { HomeTitle } from "@/components/ai/title"; import { Videos } from "@/components/ai/videos"; import { Weather } from "@/components/ai/weather"; -import { getLocaleOrThrow } from "@/lib/i18n/params"; - -export const revalidate = false; - -export default function Page(props: PageProps<"/[locale]/chat">) { - const { params } = props; - const { locale: rawLocale } = use(params); - const locale = getLocaleOrThrow(rawLocale); - - // Enable static rendering - setRequestLocale(locale); +export default function Page() { return (
) { - const { children, params } = props; - const { locale } = use(params); - - if (!hasLocale(routing.locales, locale)) { - notFound(); - } - - setRequestLocale(locale); - + const { children } = props; return {children}; } diff --git a/apps/www/app/[locale]/(app)/(dynamic)/(core)/search/page.tsx b/apps/www/app/[locale]/(app)/(dynamic)/(core)/search/page.tsx index 480870c40..84c2f949e 100644 --- a/apps/www/app/[locale]/(app)/(dynamic)/(core)/search/page.tsx +++ b/apps/www/app/[locale]/(app)/(dynamic)/(core)/search/page.tsx @@ -7,8 +7,6 @@ import { SearchListItems } from "@/components/search/results"; import { BackButton } from "@/components/shared/back-button"; import { getLocaleOrThrow } from "@/lib/i18n/params"; -export const revalidate = false; - export async function generateMetadata({ params, }: { diff --git a/apps/www/app/[locale]/(app)/(dynamic)/auth/page.tsx b/apps/www/app/[locale]/(app)/(dynamic)/auth/page.tsx index 2427b6908..963c8d476 100644 --- a/apps/www/app/[locale]/(app)/(dynamic)/auth/page.tsx +++ b/apps/www/app/[locale]/(app)/(dynamic)/auth/page.tsx @@ -1,22 +1,13 @@ import { Button } from "@repo/design-system/components/ui/button"; import { type Locale, useTranslations } from "next-intl"; -import { setRequestLocale } from "next-intl/server"; -import { use } from "react"; +import { getLocale } from "next-intl/server"; import { Auth } from "@/components/auth"; import { FeaturesDithering } from "@/components/marketing/about/features.client"; import { Theme } from "@/components/marketing/shared/footer-action"; import { BackButton } from "@/components/shared/back-button"; -import { getLocaleOrThrow } from "@/lib/i18n/params"; -export const revalidate = false; - -export default function Page(props: PageProps<"/[locale]/auth">) { - const { params } = props; - const { locale: rawLocale } = use(params); - const locale = getLocaleOrThrow(rawLocale); - - // Enable static rendering - setRequestLocale(locale); +export default async function Page() { + const locale = await getLocale(); return (
diff --git a/apps/www/app/[locale]/(app)/(dynamic)/layout.tsx b/apps/www/app/[locale]/(app)/(dynamic)/layout.tsx index 42763b17a..91812f5f4 100644 --- a/apps/www/app/[locale]/(app)/(dynamic)/layout.tsx +++ b/apps/www/app/[locale]/(app)/(dynamic)/layout.tsx @@ -1,7 +1,4 @@ -import { routing } from "@repo/internationalization/src/routing"; -import { notFound } from "next/navigation"; -import { hasLocale } from "next-intl"; -import { setRequestLocale } from "next-intl/server"; +import { Suspense } from "react"; import { ConvexAppProviders } from "@/components/providers"; import { getToken } from "@/lib/auth/server"; @@ -16,15 +13,16 @@ import { getToken } from "@/lib/auth/server"; * @see https://labs.convex.dev/better-auth/migrations/migrate-to-0-10#pass-initial-token-to-convexbetterauthprovider */ export default async function Layout(props: LayoutProps<"/[locale]">) { - const { children, params } = props; - const { locale } = await params; + const { children } = props; - if (!hasLocale(routing.locales, locale)) { - notFound(); - } - - setRequestLocale(locale); + return ( + + {children} + + ); +} +async function AuthLayout({ children }: { children: React.ReactNode }) { const token = await getToken(); return ( diff --git a/apps/www/app/[locale]/(app)/(dynamic)/loading.tsx b/apps/www/app/[locale]/(app)/(dynamic)/loading.tsx new file mode 100644 index 000000000..4349ac3a6 --- /dev/null +++ b/apps/www/app/[locale]/(app)/(dynamic)/loading.tsx @@ -0,0 +1,3 @@ +export default function Loading() { + return null; +} diff --git a/apps/www/app/[locale]/(app)/(dynamic)/try-out/[product]/[slug]/page.tsx b/apps/www/app/[locale]/(app)/(dynamic)/try-out/[product]/[slug]/page.tsx index 6b2bc2976..c32b635b1 100644 --- a/apps/www/app/[locale]/(app)/(dynamic)/try-out/[product]/[slug]/page.tsx +++ b/apps/www/app/[locale]/(app)/(dynamic)/try-out/[product]/[slug]/page.tsx @@ -26,7 +26,6 @@ export default async function Page( ) { const { params, searchParams } = props; const { locale, product: productParam, slug } = await params; - const initialNowMs = Date.now(); if (!hasLocale(routing.locales, locale)) { notFound(); @@ -55,6 +54,8 @@ export default async function Page( notFound(); } + const initialNowMs = Date.now(); + const { attempt } = await loadTryoutSearchParams(searchParams); const preloadedSetView = token ? await preloadQuery( diff --git a/apps/www/app/[locale]/(app)/(dynamic)/try-out/[product]/[slug]/part/[partKey]/page.tsx b/apps/www/app/[locale]/(app)/(dynamic)/try-out/[product]/[slug]/part/[partKey]/page.tsx index 9adfe3cc7..abe1f5d46 100644 --- a/apps/www/app/[locale]/(app)/(dynamic)/try-out/[product]/[slug]/part/[partKey]/page.tsx +++ b/apps/www/app/[locale]/(app)/(dynamic)/try-out/[product]/[slug]/part/[partKey]/page.tsx @@ -32,7 +32,6 @@ export default async function Page( ) { const { params, searchParams } = props; const { locale, product: productParam, slug, partKey } = await params; - const initialNowMs = Date.now(); if (!hasLocale(routing.locales, locale)) { notFound(); @@ -59,6 +58,8 @@ export default async function Page( notFound(); } + const initialNowMs = Date.now(); + const { attempt } = await loadTryoutSearchParams(searchParams); const preloadedRuntime = token ? await preloadQuery( diff --git a/apps/www/app/[locale]/(app)/(dynamic)/try-out/[product]/page.tsx b/apps/www/app/[locale]/(app)/(dynamic)/try-out/[product]/page.tsx index ccf239272..8926a5a78 100644 --- a/apps/www/app/[locale]/(app)/(dynamic)/try-out/[product]/page.tsx +++ b/apps/www/app/[locale]/(app)/(dynamic)/try-out/[product]/page.tsx @@ -31,7 +31,6 @@ export default async function Page( ) { const { params } = props; const { locale, product: productParam } = await params; - const initialNowMs = Date.now(); if (!hasLocale(routing.locales, locale)) { notFound(); @@ -49,6 +48,9 @@ export default async function Page( getTranslations({ locale, namespace: "Tryouts" }), getToken(), ]); + + const initialNowMs = Date.now(); + const catalogSnapshot = await fetchQuery( api.tryouts.queries.tryouts.getActiveTryoutCatalogSnapshot, { diff --git a/apps/www/app/[locale]/(app)/(static)/(learn)/articles/[category]/[slug]/layout.tsx b/apps/www/app/[locale]/(app)/(static)/(learn)/articles/[category]/[slug]/layout.tsx index e35636dfa..2d2eaa293 100644 --- a/apps/www/app/[locale]/(app)/(static)/(learn)/articles/[category]/[slug]/layout.tsx +++ b/apps/www/app/[locale]/(app)/(static)/(learn)/articles/[category]/[slug]/layout.tsx @@ -2,7 +2,6 @@ import { parseArticleCategory } from "@repo/contents/_lib/articles/category"; import { getSlugPath } from "@repo/contents/_lib/articles/slug"; import { cleanSlug } from "@repo/utilities/helper"; import { notFound } from "next/navigation"; -import { setRequestLocale } from "next-intl/server"; import { use } from "react"; import { ContentViewTracker } from "@/components/tracking/content-view-tracker"; import { getLocaleOrThrow } from "@/lib/i18n/params"; @@ -19,8 +18,6 @@ export default function Layout( notFound(); } - setRequestLocale(locale); - const filePath = getSlugPath(category, slug); const cleanedSlug = cleanSlug(filePath); diff --git a/apps/www/app/[locale]/(app)/(static)/(learn)/articles/[category]/[slug]/page.tsx b/apps/www/app/[locale]/(app)/(static)/(learn)/articles/[category]/[slug]/page.tsx index e2f7baf04..118262670 100644 --- a/apps/www/app/[locale]/(app)/(static)/(learn)/articles/[category]/[slug]/page.tsx +++ b/apps/www/app/[locale]/(app)/(static)/(learn)/articles/[category]/[slug]/page.tsx @@ -8,12 +8,13 @@ import { BreadcrumbJsonLd } from "@repo/seo/json-ld/breadcrumb"; import { LearningResourceJsonLd } from "@repo/seo/json-ld/learning-resource"; import { Effect } from "effect"; import type { Metadata } from "next"; +import { cacheLife } from "next/cache"; import { notFound } from "next/navigation"; import type { Locale } from "next-intl"; -import { getTranslations, setRequestLocale } from "next-intl/server"; -import { use } from "react"; -import { AiSheetOpen } from "@/components/ai/sheet-open"; -import { Comments } from "@/components/comments"; +import { getTranslations } from "next-intl/server"; +import type { ReactNode } from "react"; +import { DeferredAiSheetOpen } from "@/components/ai/deferred-sheet-open"; +import { DeferredComments } from "@/components/comments/deferred"; import { ComingSoon } from "@/components/shared/coming-soon"; import { LayoutMaterial, @@ -34,8 +35,6 @@ import { generateSEOMetadata } from "@/lib/utils/seo/generator"; import type { SEOContext } from "@/lib/utils/seo/types"; import { getStaticParams } from "@/lib/utils/system"; -export const revalidate = false; - async function getResolvedParams( params: PageProps<"/[locale]/articles/[category]/[slug]">["params"] ) { @@ -58,22 +57,18 @@ export async function generateMetadata({ const { locale, category, slug } = await getResolvedParams(params); const t = await getTranslations({ locale, namespace: "Articles" }); - const { content, FilePath } = await Effect.runPromise( - Effect.match(fetchArticleMetadataContext({ locale, category, slug }), { - onFailure: () => ({ - content: null, - FilePath: getSlugPath(category, slug), - }), - onSuccess: (data) => data, - }) - ); + const { content, filePath } = await getArticleMetadataData({ + locale, + category, + slug, + }); - const path = `/${locale}${FilePath}`; + const path = `/${locale}${filePath}`; const alternates = { canonical: path, }; const image = { - url: getOgUrl(locale, FilePath), + url: getOgUrl(locale, filePath), width: 1200, height: 630, }; @@ -128,6 +123,33 @@ export async function generateMetadata({ }; } +async function getArticleMetadataData({ + locale, + category, + slug, +}: { + locale: Locale; + category: ArticleCategory; + slug: string; +}) { + "use cache"; + + cacheLife("max"); + + return Effect.runPromise( + Effect.match(fetchArticleMetadataContext({ locale, category, slug }), { + onFailure: () => ({ + content: null, + filePath: getSlugPath(category, slug), + }), + onSuccess: ({ content, FilePath }) => ({ + content, + filePath: FilePath, + }), + }) + ); +} + // Generate bottom-up static params export function generateStaticParams() { return getStaticParams({ @@ -136,36 +158,52 @@ export function generateStaticParams() { }); } -export default function Page( - props: PageProps<"/[locale]/articles/[category]/[slug]"> -) { - const { params } = props; - const { locale: rawLocale, category: rawCategory, slug } = use(params); - const locale = getLocaleOrThrow(rawLocale); - const category = parseArticleCategory(rawCategory); - - if (!category) { - notFound(); - } - - // Enable static rendering - setRequestLocale(locale); +export default async function Page({ + params, +}: PageProps<"/[locale]/articles/[category]/[slug]">) { + const { locale, category, slug } = await getResolvedParams(params); + const filePath = getSlugPath(category, slug); - return ; + return ( + } + locale={locale} + slug={slug} + toolbar={ + + } + /> + ); } -async function PageContent({ +async function CachedArticleShell({ locale, category, slug, + footer, + toolbar, }: { locale: Locale; category: ArticleCategory; slug: string; + footer: ReactNode; + toolbar: ReactNode; }) { + "use cache"; + + cacheLife("max"); + const [tCommon, tArticles] = await Promise.all([ - getTranslations({ locale, namespace: "Common" }), - getTranslations({ locale, namespace: "Articles" }), + getTranslations("Common"), + getTranslations("Articles"), ]); const FilePath = getSlugPath(category, slug); @@ -246,16 +284,8 @@ async function PageContent({ {headings.length === 0 && } {headings.length > 0 && Content} - - - - + {footer} + {toolbar} ["params"] ) { @@ -39,6 +38,14 @@ async function getResolvedParams( return { category, locale }; } +async function getCategoryArticles(category: ArticleCategory, locale: Locale) { + "use cache"; + + cacheLife("max"); + + return getArticleSummaries(category, locale); +} + export async function generateMetadata({ params, }: { @@ -127,7 +134,7 @@ async function PageArticles({ FilePath: string; header: React.ReactNode; }) { - const articles = await getArticleSummaries(category, locale); + const articles = await getCategoryArticles(category, locale); const t = await getTranslations({ locale, namespace: "Articles" }); return ( diff --git a/apps/www/app/[locale]/(app)/(static)/(learn)/exercises/[category]/[type]/[material]/[...slug]/page.tsx b/apps/www/app/[locale]/(app)/(static)/(learn)/exercises/[category]/[type]/[material]/[...slug]/page.tsx index 7460c5347..65bb0e6a3 100644 --- a/apps/www/app/[locale]/(app)/(static)/(learn)/exercises/[category]/[type]/[material]/[...slug]/page.tsx +++ b/apps/www/app/[locale]/(app)/(static)/(learn)/exercises/[category]/[type]/[material]/[...slug]/page.tsx @@ -36,12 +36,13 @@ import { FOUNDER } from "@repo/seo/json-ld/constants"; import { LearningResourceJsonLd } from "@repo/seo/json-ld/learning-resource"; import { Effect, Option } from "effect"; import type { Metadata } from "next"; +import { cacheLife } from "next/cache"; import { notFound, permanentRedirect } from "next/navigation"; import type { Locale } from "next-intl"; import { getTranslations, setRequestLocale } from "next-intl/server"; import { use } from "react"; -import { AiSheetOpen } from "@/components/ai/sheet-open"; -import { Comments } from "@/components/comments"; +import { DeferredAiSheetOpen } from "@/components/ai/deferred-sheet-open"; +import { DeferredComments } from "@/components/comments/deferred"; import { CardMaterial } from "@/components/shared/card-material"; import { ComingSoon } from "@/components/shared/coming-soon"; import { ContainerList } from "@/components/shared/container-list"; @@ -70,8 +71,6 @@ import { QuestionAnalytics } from "./analytics"; import { ExerciseArticle } from "./article"; import { ExerciseAttempt } from "./attempt"; -export const revalidate = false; - async function getResolvedParams( params: PageProps<"/[locale]/exercises/[category]/[type]/[material]/[...slug]">["params"] ) { @@ -109,22 +108,7 @@ export async function generateMetadata({ FilePath, currentMaterial, currentMaterialItem, - } = await Effect.runPromise( - Effect.match( - fetchExerciseMetadataContext({ locale, category, type, material, slug }), - { - onFailure: () => ({ - isSpecificExercise: false, - exerciseTitle: undefined, - exerciseCount: 0, - FilePath: getSlugPath(category, type, material, slug), - currentMaterial: undefined, - currentMaterialItem: undefined, - }), - onSuccess: (data) => data, - } - ) - ); + } = await getExerciseMetadataData({ locale, category, type, material, slug }); const urlPath = `/${locale}${FilePath}`; const image = { @@ -192,6 +176,41 @@ export async function generateMetadata({ }; } +async function getExerciseMetadataData({ + locale, + category, + type, + material, + slug, +}: { + locale: Locale; + category: ExercisesCategory; + type: ExercisesType; + material: ExercisesMaterial; + slug: string[]; +}) { + "use cache"; + + cacheLife("max"); + + return Effect.runPromise( + Effect.match( + fetchExerciseMetadataContext({ locale, category, type, material, slug }), + { + onFailure: () => ({ + isSpecificExercise: false, + exerciseTitle: undefined, + exerciseCount: 0, + FilePath: getSlugPath(category, type, material, slug), + currentMaterial: undefined, + currentMaterialItem: undefined, + }), + onSuccess: (data) => data, + } + ) + ); +} + export function generateStaticParams() { return getStaticParams({ basePath: "exercises", @@ -290,6 +309,10 @@ async function YearGroupContent({ materialPath: string; type: ExercisesType; }) { + "use cache"; + + cacheLife("max"); + const t = await getTranslations({ locale, namespace: "Exercises" }); const headingId = slugify(currentMaterial.title); @@ -370,6 +393,10 @@ async function PageContent({ material: ExercisesMaterial; slug: string[]; }) { + "use cache"; + + cacheLife("max"); + const t = await getTranslations({ locale, namespace: "Exercises" }); const materialPath = getMaterialPath(category, type, material); @@ -487,9 +514,9 @@ async function PageContent({ - + - + - + - + ["params"] ) { diff --git a/apps/www/app/[locale]/(app)/(static)/(learn)/exercises/[category]/[type]/page.tsx b/apps/www/app/[locale]/(app)/(static)/(learn)/exercises/[category]/[type]/page.tsx index e8aa20db4..9b19d2e42 100644 --- a/apps/www/app/[locale]/(app)/(static)/(learn)/exercises/[category]/[type]/page.tsx +++ b/apps/www/app/[locale]/(app)/(static)/(learn)/exercises/[category]/[type]/page.tsx @@ -29,8 +29,6 @@ import { createSEODescription } from "@/lib/utils/seo/descriptions"; import { createSEOTitle } from "@/lib/utils/seo/titles"; import { getStaticParams } from "@/lib/utils/system"; -export const revalidate = false; - async function getResolvedParams( params: PageProps<"/[locale]/exercises/[category]/[type]">["params"] ) { diff --git a/apps/www/app/[locale]/(app)/(static)/(learn)/layout.tsx b/apps/www/app/[locale]/(app)/(static)/(learn)/layout.tsx index c6f527a28..517944dab 100644 --- a/apps/www/app/[locale]/(app)/(static)/(learn)/layout.tsx +++ b/apps/www/app/[locale]/(app)/(static)/(learn)/layout.tsx @@ -1,7 +1,6 @@ import { routing } from "@repo/internationalization/src/routing"; import { notFound } from "next/navigation"; import { hasLocale } from "next-intl"; -import { setRequestLocale } from "next-intl/server"; import { use } from "react"; import { AppShell } from "@/components/sidebar/app-shell"; @@ -14,7 +13,5 @@ export default function Layout(props: LayoutProps<"/[locale]">) { notFound(); } - setRequestLocale(locale); - return {children}; } diff --git a/apps/www/app/[locale]/(app)/(static)/(learn)/quran/[surah]/page.tsx b/apps/www/app/[locale]/(app)/(static)/(learn)/quran/[surah]/page.tsx index 554306e68..f8fded1df 100644 --- a/apps/www/app/[locale]/(app)/(static)/(learn)/quran/[surah]/page.tsx +++ b/apps/www/app/[locale]/(app)/(static)/(learn)/quran/[surah]/page.tsx @@ -4,11 +4,12 @@ import { cn, slugify } from "@repo/design-system/lib/utils"; import { BookJsonLd } from "@repo/seo/json-ld/book"; import { Effect } from "effect"; import type { Metadata } from "next"; +import { cacheLife } from "next/cache"; import { notFound } from "next/navigation"; -import { type Locale, useTranslations } from "next-intl"; -import { getTranslations, setRequestLocale } from "next-intl/server"; -import { use } from "react"; -import { AiSheetOpen } from "@/components/ai/sheet-open"; +import type { Locale } from "next-intl"; +import { getTranslations } from "next-intl/server"; +import type { ReactNode } from "react"; +import { DeferredAiSheetOpen } from "@/components/ai/deferred-sheet-open"; import { LayoutMaterial, LayoutMaterialContent, @@ -32,8 +33,6 @@ import { import { generateSEOMetadata } from "@/lib/utils/seo/generator"; import type { SEOContext } from "@/lib/utils/seo/types"; -export const revalidate = false; - export async function generateMetadata({ params, }: { @@ -42,7 +41,7 @@ export async function generateMetadata({ const { locale: rawLocale, surah } = await params; const locale = getLocaleOrThrow(rawLocale); - const t = await getTranslations({ locale, namespace: "Holy" }); + const t = await getTranslations("Holy"); const path = `/${locale}/quran/${surah}`; @@ -73,14 +72,7 @@ export async function generateMetadata({ }; } - const surahMetadataContext = await Effect.runPromise( - Effect.match(fetchSurahMetadataContext({ surah: surahNumber }), { - onFailure: () => null, - onSuccess: (data) => data, - }) - ); - - const surahData = surahMetadataContext?.surahData ?? null; + const surahData = await getSurahMetadataData({ surah: surahNumber }); if (!surahData) { return { alternates, @@ -119,18 +111,58 @@ export function generateStaticParams() { } export default function Page(props: PageProps<"/[locale]/quran/[surah]">) { - const { params } = props; - const { locale: rawLocale, surah } = use(params); + return ; +} + +async function ResolvedSurahPage({ + params, +}: { + params: PageProps<"/[locale]/quran/[surah]">["params"]; +}) { + const { locale: rawLocale, surah } = await params; const locale = getLocaleOrThrow(rawLocale); - // Enable static rendering - setRequestLocale(locale); + return ( + } + locale={locale} + surah={surah} + toolbar={} + /> + ); +} + +async function getSurahMetadataData({ surah }: { surah: number }) { + "use cache"; + + cacheLife("max"); + + const surahMetadataContext = await Effect.runPromise( + Effect.match(fetchSurahMetadataContext({ surah }), { + onFailure: () => null, + onSuccess: (data) => data, + }) + ); - return ; + return surahMetadataContext?.surahData ?? null; } -function PageContent({ locale, surah }: { locale: Locale; surah: string }) { - const t = useTranslations("Holy"); +async function CachedSurahShell({ + locale, + surah, + footer, + toolbar, +}: { + locale: Locale; + surah: string; + footer: ReactNode; + toolbar: ReactNode; +}) { + "use cache"; + + cacheLife("max"); + + const t = await getTranslations("Holy"); const surahNumber = Number(surah); @@ -138,17 +170,15 @@ function PageContent({ locale, surah }: { locale: Locale; surah: string }) { notFound(); } - const result = use( - Effect.runPromise( - Effect.match(fetchSurahContext({ surah: surahNumber }), { - onFailure: () => ({ - surahData: null, - prevSurah: null, - nextSurah: null, - }), - onSuccess: (data) => data, - }) - ) + const result = await Effect.runPromise( + Effect.match(fetchSurahContext({ surah: surahNumber }), { + onFailure: () => ({ + surahData: null, + prevSurah: null, + nextSurah: null, + }), + onSuccess: (data) => data, + }) ); const { surahData, prevSurah, nextSurah } = result; @@ -286,10 +316,8 @@ function PageContent({ locale, surah }: { locale: Locale; surah: string }) { - - - - + {footer} + {toolbar} ["params"] ) { @@ -83,43 +82,21 @@ export async function generateMetadata({ }): Promise { const { locale, category, grade, material, slug } = await getResolvedParams(params); - const t = await getTranslations({ locale, namespace: "Subject" }); - - const FilePath = getSlugPath(category, grade, material, slug); - const materialPath = getMaterialPath(category, grade, material); + const t = await getTranslations("Subject"); - // Fetch content and materials in parallel - const [{ content }, materials] = await Promise.all([ - Effect.runPromise( - Effect.match( - getContentMetadataContext({ locale, category, grade, material, slug }), - { - onFailure: () => ({ content: null, FilePath }), - onSuccess: (data) => data, - } - ) - ), - getMaterials(materialPath, locale).catch(() => []), - ]); - - const metadata = content?.metadata ?? null; - - // Get chapter title from materials using getCurrentMaterial - let chapter: string | undefined; - if (slug.length > 0 && materials.length > 0) { - const chapterPath = getSlugPath(category, grade, material, [ - slug.at(0) ?? "", - ]); - const { currentChapter } = getCurrentMaterial(chapterPath, materials); - chapter = currentChapter?.title; - } + const { chapter, filePath, metadata, path } = await getSubjectMetadataData({ + locale, + category, + grade, + material, + slug, + }); - const path = `/${locale}${FilePath}`; const alternates = { canonical: path, }; const image = { - url: getOgUrl(locale, FilePath), + url: getOgUrl(locale, filePath), width: 1200, height: 630, }; @@ -187,38 +164,46 @@ export function generateStaticParams() { export default function Page( props: PageProps<"/[locale]/subject/[category]/[grade]/[material]/[...slug]"> ) { - const { params } = props; - const { - locale: rawLocale, - category: rawCategory, - grade: rawGrade, - material: rawMaterial, - slug, - } = use(params); - const locale = getLocaleOrThrow(rawLocale); - const category = parseSubjectCategory(rawCategory); - const grade = parseGrade(rawGrade); - const material = parseMaterial(rawMaterial); + return ; +} - if (!(category && grade && material)) { - notFound(); +async function ResolvedPage({ + params, +}: { + params: PageProps<"/[locale]/subject/[category]/[grade]/[material]/[...slug]">["params"]; +}) { + const { locale, category, grade, material, slug } = + await getResolvedParams(params); + + if (slug.length === 1) { + redirect(getSlugPath(category, grade, material, [])); } - // Enable static rendering - setRequestLocale(locale); + const filePath = getSlugPath(category, grade, material, slug); return ( - } grade={grade} locale={locale} material={material} slug={slug} + toolbar={ + + } /> ); } -async function PageContent({ +async function getSubjectMetadataData({ locale, category, grade, @@ -231,18 +216,68 @@ async function PageContent({ material: Material; slug: string[]; }) { - const [tCommon, tSubject] = await Promise.all([ - getTranslations({ locale, namespace: "Common" }), - getTranslations({ locale, namespace: "Subject" }), + "use cache"; + + cacheLife("max"); + + const filePath = getSlugPath(category, grade, material, slug); + const materialPath = getMaterialPath(category, grade, material); + + const [{ content }, materials] = await Promise.all([ + Effect.runPromise( + Effect.match( + getContentMetadataContext({ locale, category, grade, material, slug }), + { + onFailure: () => ({ content: null, FilePath: filePath }), + onSuccess: (data) => data, + } + ) + ), + getMaterials(materialPath, locale).catch(() => []), ]); - if (slug.length === 1) { - // Means it only contains the chapter name, not the section name - // The slugs usually have 2 items, chapter and section - // In the future, we can add a new page specifically for the section - const materialPath = getSlugPath(category, grade, material, []); - redirect(materialPath); - } + const metadata = content?.metadata ?? null; + const chapterPath = getSlugPath(category, grade, material, [ + slug.at(0) ?? "", + ]); + const chapter = + slug.length > 0 && materials.length > 0 + ? getCurrentMaterial(chapterPath, materials).currentChapter?.title + : undefined; + + return { + metadata, + chapter, + filePath, + path: `/${locale}${filePath}`, + }; +} + +async function CachedSubjectShell({ + locale, + category, + grade, + material, + slug, + footer, + toolbar, +}: { + locale: Locale; + category: SubjectCategory; + grade: Grade; + material: Material; + slug: string[]; + footer: ReactNode; + toolbar: ReactNode; +}) { + "use cache"; + + cacheLife("max"); + + const [tCommon, tSubject] = await Promise.all([ + getTranslations("Common"), + getTranslations("Subject"), + ]); const FilePath = getSlugPath(category, grade, material, slug); const materialPath = getMaterialPath(category, grade, material); @@ -336,16 +371,8 @@ async function PageContent({ {headings.length > 0 && Content} - - - - + {footer} + {toolbar} ["params"] ) { diff --git a/apps/www/app/[locale]/(app)/(static)/(learn)/subject/[category]/[grade]/page.tsx b/apps/www/app/[locale]/(app)/(static)/(learn)/subject/[category]/[grade]/page.tsx index cf38f0075..5c2d46662 100644 --- a/apps/www/app/[locale]/(app)/(static)/(learn)/subject/[category]/[grade]/page.tsx +++ b/apps/www/app/[locale]/(app)/(static)/(learn)/subject/[category]/[grade]/page.tsx @@ -29,8 +29,6 @@ import { getOgUrl } from "@/lib/utils/metadata"; import { createSEOTitle } from "@/lib/utils/seo/titles"; import { getStaticParams } from "@/lib/utils/system"; -export const revalidate = false; - async function getResolvedParams( params: PageProps<"/[locale]/subject/[category]/[grade]">["params"] ) { diff --git a/apps/www/app/[locale]/(app)/(static)/(learn)/subject/page.tsx b/apps/www/app/[locale]/(app)/(static)/(learn)/subject/page.tsx index bd91003a5..720f2da31 100644 --- a/apps/www/app/[locale]/(app)/(static)/(learn)/subject/page.tsx +++ b/apps/www/app/[locale]/(app)/(static)/(learn)/subject/page.tsx @@ -16,8 +16,6 @@ import { LayoutContent } from "@/components/shared/layout-content"; import { getLocaleOrThrow } from "@/lib/i18n/params"; import { getGradeIcon } from "./icons"; -export const revalidate = false; - const CATEGORY_ORDER = ["middle-school", "high-school", "university"] as const; export async function generateMetadata({ diff --git a/apps/www/app/[locale]/(app)/(static)/(site)/(legal)/privacy-policy/page.tsx b/apps/www/app/[locale]/(app)/(static)/(site)/(legal)/privacy-policy/page.tsx index a2e5af92c..1d5a11fb5 100644 --- a/apps/www/app/[locale]/(app)/(static)/(site)/(legal)/privacy-policy/page.tsx +++ b/apps/www/app/[locale]/(app)/(static)/(site)/(legal)/privacy-policy/page.tsx @@ -5,9 +5,6 @@ import { getTranslations, setRequestLocale } from "next-intl/server"; import { use } from "react"; import { getLocaleOrThrow } from "@/lib/i18n/params"; -export const dynamic = "force-static"; -export const revalidate = false; - export async function generateMetadata({ params, }: { diff --git a/apps/www/app/[locale]/(app)/(static)/(site)/(legal)/security-policy/page.tsx b/apps/www/app/[locale]/(app)/(static)/(site)/(legal)/security-policy/page.tsx index b2e2fd8be..434003973 100644 --- a/apps/www/app/[locale]/(app)/(static)/(site)/(legal)/security-policy/page.tsx +++ b/apps/www/app/[locale]/(app)/(static)/(site)/(legal)/security-policy/page.tsx @@ -5,9 +5,6 @@ import { getTranslations, setRequestLocale } from "next-intl/server"; import { use } from "react"; import { getLocaleOrThrow } from "@/lib/i18n/params"; -export const dynamic = "force-static"; -export const revalidate = false; - export async function generateMetadata({ params, }: { diff --git a/apps/www/app/[locale]/(app)/(static)/(site)/(legal)/terms-of-service/page.tsx b/apps/www/app/[locale]/(app)/(static)/(site)/(legal)/terms-of-service/page.tsx index 556d3e01a..8a3f7a4a3 100644 --- a/apps/www/app/[locale]/(app)/(static)/(site)/(legal)/terms-of-service/page.tsx +++ b/apps/www/app/[locale]/(app)/(static)/(site)/(legal)/terms-of-service/page.tsx @@ -5,9 +5,6 @@ import { getTranslations, setRequestLocale } from "next-intl/server"; import { use } from "react"; import { getLocaleOrThrow } from "@/lib/i18n/params"; -export const dynamic = "force-static"; -export const revalidate = false; - export async function generateMetadata({ params, }: { diff --git a/apps/www/app/[locale]/(app)/(static)/(site)/about/page.tsx b/apps/www/app/[locale]/(app)/(static)/(site)/about/page.tsx index df9884667..62146ab1d 100644 --- a/apps/www/app/[locale]/(app)/(static)/(site)/about/page.tsx +++ b/apps/www/app/[locale]/(app)/(static)/(site)/about/page.tsx @@ -20,9 +20,6 @@ import { exercisesMenu } from "@/components/sidebar/_data/exercises"; import { subjectMenu } from "@/components/sidebar/_data/subject"; import { getLocaleOrThrow } from "@/lib/i18n/params"; -export const dynamic = "force-static"; -export const revalidate = false; - export async function generateMetadata({ params, }: { diff --git a/apps/www/app/[locale]/(app)/(static)/(site)/ask/[slug]/page.tsx b/apps/www/app/[locale]/(app)/(static)/(site)/ask/[slug]/page.tsx index 8ed724295..3ba24b0b6 100644 --- a/apps/www/app/[locale]/(app)/(static)/(site)/ask/[slug]/page.tsx +++ b/apps/www/app/[locale]/(app)/(static)/(site)/ask/[slug]/page.tsx @@ -13,9 +13,6 @@ import { import { getLocaleOrThrow } from "@/lib/i18n/params"; import { convertSlugToTitle } from "@/lib/utils/helper"; -export const dynamic = "force-static"; -export const revalidate = false; - const askData = askSeo(); export async function generateMetadata({ diff --git a/apps/www/app/[locale]/(app)/(static)/(site)/contributor/page.tsx b/apps/www/app/[locale]/(app)/(static)/(site)/contributor/page.tsx index bfb3a4c8a..21deacfac 100644 --- a/apps/www/app/[locale]/(app)/(static)/(site)/contributor/page.tsx +++ b/apps/www/app/[locale]/(app)/(static)/(site)/contributor/page.tsx @@ -9,9 +9,6 @@ import { LayoutContent } from "@/components/shared/layout-content"; import { contributors } from "@/lib/data/contributor"; import { getLocaleOrThrow } from "@/lib/i18n/params"; -export const dynamic = "force-static"; -export const revalidate = false; - export async function generateMetadata({ params, }: { diff --git a/apps/www/app/[locale]/(app)/(static)/(site)/events/page.tsx b/apps/www/app/[locale]/(app)/(static)/(site)/events/page.tsx index 0535cf30d..c72d52278 100644 --- a/apps/www/app/[locale]/(app)/(static)/(site)/events/page.tsx +++ b/apps/www/app/[locale]/(app)/(static)/(site)/events/page.tsx @@ -3,9 +3,6 @@ import { getTranslations, setRequestLocale } from "next-intl/server"; import { use } from "react"; import { getLocaleOrThrow } from "@/lib/i18n/params"; -export const dynamic = "force-static"; -export const revalidate = false; - export async function generateMetadata({ params, }: { diff --git a/apps/www/app/[locale]/(app)/(static)/(site)/layout.tsx b/apps/www/app/[locale]/(app)/(static)/(site)/layout.tsx index 8444aff03..2f7b0d827 100644 --- a/apps/www/app/[locale]/(app)/(static)/(site)/layout.tsx +++ b/apps/www/app/[locale]/(app)/(static)/(site)/layout.tsx @@ -1,10 +1,10 @@ import { routing } from "@repo/internationalization/src/routing"; import { notFound } from "next/navigation"; import { hasLocale } from "next-intl"; -import { setRequestLocale } from "next-intl/server"; import { use } from "react"; import { Footer } from "@/components/marketing/shared/footer"; import { Header } from "@/components/marketing/shared/header"; +import { AppProviders } from "@/components/providers"; /** Renders the marketing subtree inside its dedicated site shell. */ export default function Layout(props: LayoutProps<"/[locale]">) { @@ -14,16 +14,16 @@ export default function Layout(props: LayoutProps<"/[locale]">) { notFound(); } - setRequestLocale(locale); - return ( -
-
- {children} -
-
+ +
+
+ {children} +
+
+
); } diff --git a/apps/www/app/[locale]/(app)/(static)/layout.tsx b/apps/www/app/[locale]/(app)/(static)/layout.tsx index f02a3b66e..a886d8847 100644 --- a/apps/www/app/[locale]/(app)/(static)/layout.tsx +++ b/apps/www/app/[locale]/(app)/(static)/layout.tsx @@ -1,7 +1,6 @@ import { routing } from "@repo/internationalization/src/routing"; import { notFound } from "next/navigation"; import { hasLocale } from "next-intl"; -import { setRequestLocale } from "next-intl/server"; import { ConvexAppProviders } from "@/components/providers"; /** @@ -22,7 +21,5 @@ export default async function Layout(props: LayoutProps<"/[locale]">) { notFound(); } - setRequestLocale(locale); - return {children}; } diff --git a/apps/www/app/[locale]/(app)/layout.tsx b/apps/www/app/[locale]/(app)/layout.tsx index 47905b189..8e3c0f0b9 100644 --- a/apps/www/app/[locale]/(app)/layout.tsx +++ b/apps/www/app/[locale]/(app)/layout.tsx @@ -1,7 +1,6 @@ import { routing } from "@repo/internationalization/src/routing"; import { notFound } from "next/navigation"; import { hasLocale } from "next-intl"; -import { setRequestLocale } from "next-intl/server"; /** * Binds the validated locale to the full authenticated app subtree. @@ -18,7 +17,5 @@ export default async function Layout(props: LayoutProps<"/[locale]">) { notFound(); } - setRequestLocale(locale); - return children; } diff --git a/apps/www/app/[locale]/(app)/loading.tsx b/apps/www/app/[locale]/(app)/loading.tsx new file mode 100644 index 000000000..4349ac3a6 --- /dev/null +++ b/apps/www/app/[locale]/(app)/loading.tsx @@ -0,0 +1,3 @@ +export default function Loading() { + return null; +} diff --git a/apps/www/app/[locale]/[...rest]/page.tsx b/apps/www/app/[locale]/[...rest]/page.tsx index 064276c26..3b1d244b6 100644 --- a/apps/www/app/[locale]/[...rest]/page.tsx +++ b/apps/www/app/[locale]/[...rest]/page.tsx @@ -1,17 +1,4 @@ -import { routing } from "@repo/internationalization/src/routing"; import { notFound } from "next/navigation"; -import { hasLocale } from "next-intl"; -import { setRequestLocale } from "next-intl/server"; - -export default async function Page(props: PageProps<"/[locale]/[...rest]">) { - const { params } = props; - const { locale } = await params; - - if (!hasLocale(routing.locales, locale)) { - notFound(); - } - - setRequestLocale(locale); - +export default function Page() { notFound(); } diff --git a/apps/www/app/[locale]/layout.tsx b/apps/www/app/[locale]/layout.tsx index 2cc7db747..0afc5a2ef 100644 --- a/apps/www/app/[locale]/layout.tsx +++ b/apps/www/app/[locale]/layout.tsx @@ -11,25 +11,16 @@ import { WebsiteJsonLd } from "@repo/seo/json-ld/website"; import type { Metadata, Viewport } from "next"; import { notFound } from "next/navigation"; import { hasLocale, NextIntlClientProvider } from "next-intl"; -import { getTranslations, setRequestLocale } from "next-intl/server"; -import { use } from "react"; -import { AppProviders } from "@/components/providers"; +import { getLocale, getMessages, getTranslations } from "next-intl/server"; -export async function generateMetadata({ - params, -}: { - params: LayoutProps<"/[locale]">["params"]; -}): Promise { - const { locale } = await params; +export async function generateMetadata(): Promise { + const locale = await getLocale(); if (!hasLocale(routing.locales, locale)) { notFound(); } - const t = await getTranslations({ - locale, - namespace: "Metadata", - }); + const t = await getTranslations("Metadata"); return { title: { @@ -146,20 +137,18 @@ export function generateStaticParams() { return routing.locales.map((locale) => ({ locale })); } -export default function Layout(props: LayoutProps<"/[locale]">) { - const { children, params } = props; - const { locale } = use(params); - // Ensure that the incoming `locale` is valid +export default async function Layout({ children }: LayoutProps<"/[locale]">) { + const locale = await getLocale(); + if (!hasLocale(routing.locales, locale)) { notFound(); } - // Enable static rendering - setRequestLocale(locale); + const messages = await getMessages(); return ( - + {/* Add JSON-LD structured data using the JsonLd component */} @@ -168,9 +157,7 @@ export default function Layout(props: LayoutProps<"/[locale]">) {
- - {children} - + {children}
diff --git a/apps/www/app/[locale]/og/[...slug]/route.tsx b/apps/www/app/[locale]/og/[...slug]/route.tsx index d9f40c2c2..4b32bc0f3 100644 --- a/apps/www/app/[locale]/og/[...slug]/route.tsx +++ b/apps/www/app/[locale]/og/[...slug]/route.tsx @@ -5,9 +5,6 @@ import { hasLocale, type Locale } from "next-intl"; import { getMetadataFromSlug } from "@/lib/utils/system"; import { generateOGImage } from "./og"; -export const dynamic = "force-static"; -export const revalidate = false; - export function generateStaticParams() { return []; } diff --git a/apps/www/app/api/chat/route.ts b/apps/www/app/api/chat/route.ts index d738ca2c0..2232228f9 100644 --- a/apps/www/app/api/chat/route.ts +++ b/apps/www/app/api/chat/route.ts @@ -196,7 +196,7 @@ export async function POST(req: Request) { sessionLogger.info("Chat session started"); - const t = await getTranslations("Ai"); + const t = await getTranslations({ locale, namespace: "Ai" }); const stream = createUIMessageStream({ onError: (error) => { diff --git a/apps/www/app/not-found.tsx b/apps/www/app/global-not-found.tsx similarity index 91% rename from apps/www/app/not-found.tsx rename to apps/www/app/global-not-found.tsx index 0a9754e6a..962820de9 100644 --- a/apps/www/app/not-found.tsx +++ b/apps/www/app/global-not-found.tsx @@ -6,9 +6,15 @@ import { Particles } from "@repo/design-system/components/ui/particles"; import { buttonVariants } from "@repo/design-system/lib/button"; import { fonts } from "@repo/design-system/lib/fonts"; import { cn } from "@repo/design-system/lib/utils"; +import type { Metadata } from "next"; import Link from "next/link"; -export default function NotFound() { +export const metadata: Metadata = { + title: "404 - Page Not Found", + description: "The page you are looking for does not exist.", +}; + +export default function GlobalNotFound() { return ( diff --git a/apps/www/app/layout.tsx b/apps/www/app/layout.tsx deleted file mode 100644 index ca8429e4f..000000000 --- a/apps/www/app/layout.tsx +++ /dev/null @@ -1,8 +0,0 @@ -// Since we have a root `not-found.tsx` page, a layout file - -import type { ReactNode } from "react"; - -// is required, even if it's just passing children through. -export default function RootLayout({ children }: { children: ReactNode }) { - return children; -} diff --git a/apps/www/app/llms.mdx/[...slug]/route.ts b/apps/www/app/llms.mdx/[...slug]/route.ts index 1d41fe3fb..e60e1ca51 100644 --- a/apps/www/app/llms.mdx/[...slug]/route.ts +++ b/apps/www/app/llms.mdx/[...slug]/route.ts @@ -18,9 +18,6 @@ import { getRawGithubUrl } from "@/lib/utils/github"; const BASE_URL = "https://nakafa.com"; -export const dynamic = "force-static"; -export const revalidate = false; - export async function GET( _req: NextRequest, { params }: { params: Promise<{ slug: string[] }> } diff --git a/apps/www/app/llms.txt/route.ts b/apps/www/app/llms.txt/route.ts index 998dab3c6..1978eea6e 100644 --- a/apps/www/app/llms.txt/route.ts +++ b/apps/www/app/llms.txt/route.ts @@ -22,8 +22,6 @@ import { Effect } from "effect"; const BASE_URL = "https://nakafa.com"; -export const revalidate = false; - export async function GET() { const locales = routing.locales; const scanned: string[] = []; diff --git a/apps/www/app/og/[...slug]/route.tsx b/apps/www/app/og/[...slug]/route.tsx index bcba2ba6d..246f6c995 100644 --- a/apps/www/app/og/[...slug]/route.tsx +++ b/apps/www/app/og/[...slug]/route.tsx @@ -5,9 +5,6 @@ import { hasLocale, type Locale } from "next-intl"; import { generateOGImage } from "@/app/[locale]/og/[...slug]/og"; import { getMetadataFromSlug } from "@/lib/utils/system"; -export const dynamic = "force-static"; -export const revalidate = false; - export function generateStaticParams() { return []; } diff --git a/apps/www/app/rss.xml/route.ts b/apps/www/app/rss.xml/route.ts index 80798a06b..9cfd0f2dc 100644 --- a/apps/www/app/rss.xml/route.ts +++ b/apps/www/app/rss.xml/route.ts @@ -7,8 +7,6 @@ import { Feed, type Item } from "feed"; import { NextResponse } from "next/server"; import { getTranslations } from "next-intl/server"; -export const revalidate = false; - const baseUrl = "https://nakafa.com"; export async function GET() { diff --git a/apps/www/components/ai/deferred-sheet-open.tsx b/apps/www/components/ai/deferred-sheet-open.tsx new file mode 100644 index 000000000..568e281a9 --- /dev/null +++ b/apps/www/components/ai/deferred-sheet-open.tsx @@ -0,0 +1,12 @@ +"use client"; + +import dynamic from "next/dynamic"; + +export const DeferredAiSheetOpen = dynamic( + () => + import("@/components/ai/sheet-open").then((module) => module.AiSheetOpen), + { + ssr: false, + loading: () => null, + } +); diff --git a/apps/www/components/comments/deferred.tsx b/apps/www/components/comments/deferred.tsx new file mode 100644 index 000000000..a18f16b57 --- /dev/null +++ b/apps/www/components/comments/deferred.tsx @@ -0,0 +1,11 @@ +"use client"; + +import dynamic from "next/dynamic"; + +export const DeferredComments = dynamic( + () => import("@/components/comments").then((module) => module.Comments), + { + ssr: false, + loading: () => null, + } +); diff --git a/apps/www/components/sidebar/app-shell.tsx b/apps/www/components/sidebar/app-shell.tsx index 48afb1638..79c5c2baf 100644 --- a/apps/www/components/sidebar/app-shell.tsx +++ b/apps/www/components/sidebar/app-shell.tsx @@ -6,6 +6,7 @@ import { } from "@repo/design-system/components/ui/sidebar"; import type { ReactNode } from "react"; import { AiSheet } from "@/components/ai/sheet"; +import { AppProviders } from "@/components/providers"; import { Onboarding } from "@/components/shared/onboarding"; import { SearchCommand } from "@/components/shared/search-command"; import { AppSidebar } from "@/components/sidebar/app-sidebar"; @@ -22,17 +23,19 @@ export function AppShell({ locked?: boolean; }) { return ( - - - -
- - -
- {children} -
- - - + + + + +
+ + +
+ {children} +
+ + + + ); } diff --git a/apps/www/components/tryout/hub-page.tsx b/apps/www/components/tryout/hub-page.tsx index cd450adad..9ea453999 100644 --- a/apps/www/components/tryout/hub-page.tsx +++ b/apps/www/components/tryout/hub-page.tsx @@ -18,12 +18,14 @@ import { getToken } from "@/lib/auth/server"; /** Renders the server-backed tryout hub with an SSR first catalog page. */ export async function TryoutHubPage({ locale }: { locale: Locale }) { const product: TryoutProduct = "snbt"; - const initialNowMs = Date.now(); const [tHome, tTryouts, token] = await Promise.all([ getTranslations({ locale, namespace: "Home" }), getTranslations({ locale, namespace: "Tryouts" }), getToken(), ]); + + const initialNowMs = Date.now(); + const [catalogSnapshot, currentUser] = await Promise.all([ fetchQuery( api.tryouts.queries.tryouts.getActiveTryoutCatalogSnapshot, diff --git a/apps/www/lib/utils/seo/generator.ts b/apps/www/lib/utils/seo/generator.ts index 49e8cdb1d..d6aa6a68a 100644 --- a/apps/www/lib/utils/seo/generator.ts +++ b/apps/www/lib/utils/seo/generator.ts @@ -5,6 +5,7 @@ import type { ExercisesType } from "@repo/contents/_types/exercises/type"; import type { Grade } from "@repo/contents/_types/subject/grade"; import type { Material } from "@repo/contents/_types/subject/material"; import { Effect } from "effect"; +import { cacheLife } from "next/cache"; import type { Locale } from "next-intl"; import { getTranslations } from "next-intl/server"; import { createSEODescription } from "./descriptions"; @@ -322,6 +323,10 @@ export async function generateSEOMetadata( context: SEOContext, locale: Locale ): Promise { + "use cache"; + + cacheLife("max"); + const { type } = context; const effect = Effect.gen(function* () { diff --git a/apps/www/next.config.ts b/apps/www/next.config.ts index ac0b52c4f..dc5fef042 100644 --- a/apps/www/next.config.ts +++ b/apps/www/next.config.ts @@ -10,6 +10,7 @@ const withNextIntl = createNextIntlPlugin( let nextConfig: NextConfig = { ...config, + cacheComponents: true, // Next.js recommends outputFileTracingRoot in monorepos so files outside the // app folder are included in the production trace. // Docs: https://nextjs.org/docs/app/api-reference/config/next-config-js/output @@ -104,6 +105,11 @@ let nextConfig: NextConfig = { ]; }); }, + experimental: { + ...config.experimental, + globalNotFound: true, + rootParams: true, + }, }; if (env.ANALYZE === "true") { diff --git a/packages/internationalization/package.json b/packages/internationalization/package.json index 42e157b3d..b596e5f94 100644 --- a/packages/internationalization/package.json +++ b/packages/internationalization/package.json @@ -7,6 +7,7 @@ "typecheck": "tsc --noEmit --emitDeclarationOnly false" }, "dependencies": { + "next": "16.2.3", "next-intl": "^4.9.0" }, "devDependencies": { diff --git a/packages/internationalization/src/request.ts b/packages/internationalization/src/request.ts index bc67cc9af..c20892099 100644 --- a/packages/internationalization/src/request.ts +++ b/packages/internationalization/src/request.ts @@ -1,16 +1,24 @@ +import { notFound } from "next/navigation"; +import * as rootParams from "next/root-params"; import { hasLocale } from "next-intl"; import { getRequestConfig } from "next-intl/server"; import { routing } from "./routing"; -export default getRequestConfig(async ({ requestLocale }) => { - // Typically corresponds to the `[locale]` segment - const requested = await requestLocale; - const locale = hasLocale(routing.locales, requested) - ? requested - : routing.defaultLocale; +export default getRequestConfig(async ({ locale }) => { + let resolvedLocale = locale; + + if (!resolvedLocale) { + const paramValue = await rootParams.locale(); + + if (hasLocale(routing.locales, paramValue)) { + resolvedLocale = paramValue; + } else { + notFound(); + } + } return { - locale, - messages: (await import(`../dictionaries/${locale}.json`)).default, + locale: resolvedLocale, + messages: (await import(`../dictionaries/${resolvedLocale}.json`)).default, }; }); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 14c061b38..57e63c022 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1006,6 +1006,9 @@ importers: packages/internationalization: dependencies: + next: + specifier: 16.2.3 + version: 16.2.3(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(babel-plugin-macros@3.1.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) next-intl: specifier: ^4.9.0 version: 4.9.0(@swc/helpers@0.5.18)(next@16.2.3(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(babel-plugin-macros@3.1.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(react@19.2.5)(typescript@6.0.2) @@ -1855,9 +1858,6 @@ packages: '@emnapi/core@1.9.2': resolution: {integrity: sha512-UC+ZhH3XtczQYfOlu3lNEkdW/p4dsJ1r/bP7H8+rhao3TTTMO1ATq/4DdIi23XuGoFY+Cz0JmCbdVl0hz9jZcA==} - '@emnapi/runtime@1.9.1': - resolution: {integrity: sha512-VYi5+ZVLhpgK4hQ0TAjiQiZ6ol0oe4mBx7mVv7IflsiEp0OWoVsp/+f9Vc1hOhE0TtkORVrI1GvzyreqpgWtkA==} - '@emnapi/runtime@1.9.2': resolution: {integrity: sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw==} @@ -14695,11 +14695,6 @@ snapshots: tslib: 2.8.1 optional: true - '@emnapi/runtime@1.9.1': - dependencies: - tslib: 2.8.1 - optional: true - '@emnapi/runtime@1.9.2': dependencies: tslib: 2.8.1 @@ -15330,7 +15325,7 @@ snapshots: '@img/sharp-wasm32@0.34.5': dependencies: - '@emnapi/runtime': 1.9.1 + '@emnapi/runtime': 1.9.2 optional: true '@img/sharp-win32-arm64@0.34.5': From ac0aa051660bbb1a61b58ba19cb1826e66a2c2cd Mon Sep 17 00:00:00 2001 From: Nabil Akbarazzima Fatih Date: Thu, 9 Apr 2026 22:49:14 +0200 Subject: [PATCH 02/20] Remove setRequestLocale and clean up i18n usage Removed server-side setRequestLocale calls and related locale extraction (use(params)/getLocaleOrThrow) across many pages and layouts, simplifying next-intl imports to only what's needed. Moved the data-pagefind-body attribute into LayoutContent and removed the wrapper in AppShell. Provide a fallback VirtualContext in use-virtual to avoid undefined context and supply a stable virtualRef. --- .../(core)/event/try-out/[code]/page.tsx | 6 +- .../[locale]/(app)/(dynamic)/(core)/page.tsx | 4 +- .../(app)/(dynamic)/(core)/search/page.tsx | 13 +- .../(dynamic)/(core)/user/[id]/chat/page.tsx | 14 +- .../(dynamic)/(core)/user/[id]/layout.tsx | 3 +- .../(app)/(dynamic)/(core)/user/[id]/page.tsx | 12 +- .../(app)/(dynamic)/(core)/user/layout.tsx | 3 +- .../(dynamic)/(core)/user/settings/layout.tsx | 3 +- .../(dynamic)/(core)/user/settings/page.tsx | 12 +- .../user/settings/subscriptions/page.tsx | 14 +- .../[slug]/(main)/classes/[id]/forum/page.tsx | 13 +- .../[slug]/(main)/classes/[id]/layout.tsx | 3 +- .../(main)/classes/[id]/materials/page.tsx | 13 +- .../[slug]/(main)/classes/[id]/page.tsx | 3 - .../(main)/classes/[id]/people/page.tsx | 13 +- .../[slug]/(main)/classes/page.tsx | 13 +- .../[slug]/(main)/home/page.tsx | 11 +- .../(authenticated)/[slug]/(main)/layout.tsx | 3 +- .../[slug]/(main)/notifications/page.tsx | 13 +- .../school/(authenticated)/[slug]/layout.tsx | 3 +- .../school/(authenticated)/[slug]/page.tsx | 3 - .../school/(authenticated)/layout.tsx | 3 +- .../onboarding/create/page.tsx | 13 +- .../(authenticated)/onboarding/join/page.tsx | 13 +- .../(authenticated)/onboarding/layout.tsx | 3 +- .../(authenticated)/onboarding/page.tsx | 11 +- .../(app)/(dynamic)/school/auth/page.tsx | 11 +- .../(app)/(dynamic)/school/layout.tsx | 4 +- .../[locale]/(app)/(dynamic)/school/page.tsx | 13 +- .../try-out/[product]/[slug]/page.tsx | 4 +- .../[product]/[slug]/part/[partKey]/page.tsx | 4 +- .../(dynamic)/try-out/[product]/page.tsx | 4 +- .../[locale]/(app)/(dynamic)/try-out/page.tsx | 4 +- .../(learn)/articles/[category]/page.tsx | 3 +- .../(app)/(static)/(learn)/articles/page.tsx | 12 +- .../[type]/[material]/[...slug]/layout.tsx | 4 +- .../[type]/[material]/[...slug]/page.tsx | 3 +- .../[category]/[type]/[material]/page.tsx | 3 +- .../exercises/[category]/[type]/page.tsx | 3 +- .../(learn)/exercises/[category]/page.tsx | 7 +- .../(static)/(learn)/quran/[surah]/page.tsx | 192 +++++++++--------- .../(app)/(static)/(learn)/quran/page.tsx | 3 +- .../[grade]/[material]/[...slug]/layout.tsx | 4 +- .../[category]/[grade]/[material]/page.tsx | 4 +- .../subject/[category]/[grade]/page.tsx | 3 +- .../(learn)/subject/[category]/page.tsx | 7 +- .../(app)/(static)/(learn)/subject/page.tsx | 4 +- .../(site)/(legal)/privacy-policy/page.tsx | 3 +- .../(site)/(legal)/security-policy/page.tsx | 3 +- .../(site)/(legal)/terms-of-service/page.tsx | 3 +- .../(app)/(static)/(site)/about/page.tsx | 3 +- .../(app)/(static)/(site)/ask/[slug]/page.tsx | 3 +- .../(static)/(site)/contributor/page.tsx | 11 +- .../(app)/(static)/(site)/events/page.tsx | 11 +- .../(app)/(static)/(site)/home/page.tsx | 3 +- apps/www/components/shared/layout-content.tsx | 5 +- .../www/components/shared/layout-material.tsx | 7 +- apps/www/components/sidebar/app-shell.tsx | 4 +- apps/www/lib/context/use-virtual.tsx | 15 +- 59 files changed, 185 insertions(+), 400 deletions(-) diff --git a/apps/www/app/[locale]/(app)/(dynamic)/(core)/event/try-out/[code]/page.tsx b/apps/www/app/[locale]/(app)/(dynamic)/(core)/event/try-out/[code]/page.tsx index dc1fb934d..838eaddbc 100644 --- a/apps/www/app/[locale]/(app)/(dynamic)/(core)/event/try-out/[code]/page.tsx +++ b/apps/www/app/[locale]/(app)/(dynamic)/(core)/event/try-out/[code]/page.tsx @@ -1,17 +1,13 @@ -import { setRequestLocale } from "next-intl/server"; import { use } from "react"; import { EventAccessPage } from "@/components/event/access-page"; -import { getLocaleOrThrow } from "@/lib/i18n/params"; export default function Page( props: PageProps<"/[locale]/event/try-out/[code]"> ) { const { params } = props; - const { code, locale: rawLocale } = use(params); - const locale = getLocaleOrThrow(rawLocale); + const { code } = use(params); // Enable static rendering - setRequestLocale(locale); return ; } diff --git a/apps/www/app/[locale]/(app)/(dynamic)/(core)/page.tsx b/apps/www/app/[locale]/(app)/(dynamic)/(core)/page.tsx index 1df527399..c8f1e72ac 100644 --- a/apps/www/app/[locale]/(app)/(dynamic)/(core)/page.tsx +++ b/apps/www/app/[locale]/(app)/(dynamic)/(core)/page.tsx @@ -1,7 +1,7 @@ import { BreadcrumbJsonLd } from "@repo/seo/json-ld/breadcrumb"; import { redirect } from "next/navigation"; import { type Locale, useTranslations } from "next-intl"; -import { setRequestLocale } from "next-intl/server"; + import { Suspense, use } from "react"; import { HomeContinueLearning } from "@/components/home/continue-learning"; import { HomeExplore } from "@/components/home/explore"; @@ -15,8 +15,6 @@ export default function Page(props: PageProps<"/[locale]">) { const { locale: rawLocale } = use(params); const locale = getLocaleOrThrow(rawLocale); - setRequestLocale(locale); - return ( <> diff --git a/apps/www/app/[locale]/(app)/(dynamic)/(core)/search/page.tsx b/apps/www/app/[locale]/(app)/(dynamic)/(core)/search/page.tsx index 84c2f949e..84826e528 100644 --- a/apps/www/app/[locale]/(app)/(dynamic)/(core)/search/page.tsx +++ b/apps/www/app/[locale]/(app)/(dynamic)/(core)/search/page.tsx @@ -1,6 +1,6 @@ import type { Metadata } from "next"; -import { getTranslations, setRequestLocale } from "next-intl/server"; -import { Suspense, use } from "react"; +import { getTranslations } from "next-intl/server"; +import { Suspense } from "react"; import { HomeHeader } from "@/components/home/header"; import { InputSearch } from "@/components/search/input"; import { SearchListItems } from "@/components/search/results"; @@ -24,14 +24,7 @@ export async function generateMetadata({ }; } -export default function Page(props: PageProps<"/[locale]/search">) { - const { params } = props; - const { locale: rawLocale } = use(params); - const locale = getLocaleOrThrow(rawLocale); - - // Enable static rendering - setRequestLocale(locale); - +export default function Page() { return (
) { - const { params } = props; - const { locale: rawLocale, id } = use(params); - const locale = getLocaleOrThrow(rawLocale); - - // Enable static rendering - setRequestLocale(locale); - +export default function Page({ + params, +}: PageProps<"/[locale]/user/[id]/chat">) { + const { id } = use(params); return } />; } diff --git a/apps/www/app/[locale]/(app)/(dynamic)/(core)/user/[id]/layout.tsx b/apps/www/app/[locale]/(app)/(dynamic)/(core)/user/[id]/layout.tsx index 37b1962ff..8e2a95c58 100644 --- a/apps/www/app/[locale]/(app)/(dynamic)/(core)/user/[id]/layout.tsx +++ b/apps/www/app/[locale]/(app)/(dynamic)/(core)/user/[id]/layout.tsx @@ -3,7 +3,7 @@ import { ErrorBoundary } from "@repo/design-system/components/ui/error-boundary" import { routing } from "@repo/internationalization/src/routing"; import { notFound } from "next/navigation"; import { hasLocale } from "next-intl"; -import { setRequestLocale } from "next-intl/server"; + import { use } from "react"; import { UserHeader } from "@/components/user/header"; import { UserTabs } from "@/components/user/tabs"; @@ -18,7 +18,6 @@ export default function Layout(props: LayoutProps<"/[locale]/user/[id]">) { } // Enable static rendering - setRequestLocale(locale); const userId = id as Id<"users">; diff --git a/apps/www/app/[locale]/(app)/(dynamic)/(core)/user/[id]/page.tsx b/apps/www/app/[locale]/(app)/(dynamic)/(core)/user/[id]/page.tsx index ab471545e..26752248d 100644 --- a/apps/www/app/[locale]/(app)/(dynamic)/(core)/user/[id]/page.tsx +++ b/apps/www/app/[locale]/(app)/(dynamic)/(core)/user/[id]/page.tsx @@ -1,6 +1,6 @@ import type { Id } from "@repo/backend/convex/_generated/dataModel"; import type { Metadata } from "next"; -import { getTranslations, setRequestLocale } from "next-intl/server"; +import { getTranslations } from "next-intl/server"; import { use } from "react"; import { UserComments } from "@/components/user/comments"; import { getLocaleOrThrow } from "@/lib/i18n/params"; @@ -23,13 +23,7 @@ export async function generateMetadata({ }; } -export default function Page(props: PageProps<"/[locale]/user/[id]">) { - const { params } = props; - const { locale: rawLocale, id } = use(params); - const locale = getLocaleOrThrow(rawLocale); - - // Enable static rendering - setRequestLocale(locale); - +export default function Page({ params }: PageProps<"/[locale]/user/[id]">) { + const { id } = use(params); return } />; } diff --git a/apps/www/app/[locale]/(app)/(dynamic)/(core)/user/layout.tsx b/apps/www/app/[locale]/(app)/(dynamic)/(core)/user/layout.tsx index 9724dfdcc..efcc949f3 100644 --- a/apps/www/app/[locale]/(app)/(dynamic)/(core)/user/layout.tsx +++ b/apps/www/app/[locale]/(app)/(dynamic)/(core)/user/layout.tsx @@ -1,7 +1,7 @@ import { routing } from "@repo/internationalization/src/routing"; import { notFound } from "next/navigation"; import { hasLocale } from "next-intl"; -import { setRequestLocale } from "next-intl/server"; + import { use } from "react"; export default function Layout(props: LayoutProps<"/[locale]/user">) { @@ -13,7 +13,6 @@ export default function Layout(props: LayoutProps<"/[locale]/user">) { } // Enable static rendering - setRequestLocale(locale); return (
) { } // Enable static rendering - setRequestLocale(locale); const t = useTranslations("Auth"); diff --git a/apps/www/app/[locale]/(app)/(dynamic)/(core)/user/settings/page.tsx b/apps/www/app/[locale]/(app)/(dynamic)/(core)/user/settings/page.tsx index 4d2c96601..c305151ea 100644 --- a/apps/www/app/[locale]/(app)/(dynamic)/(core)/user/settings/page.tsx +++ b/apps/www/app/[locale]/(app)/(dynamic)/(core)/user/settings/page.tsx @@ -1,6 +1,5 @@ import type { Metadata } from "next"; -import { getTranslations, setRequestLocale } from "next-intl/server"; -import { use } from "react"; +import { getTranslations } from "next-intl/server"; import { UserSettingsProfilePage } from "@/components/user/settings/profile-page"; import { getLocaleOrThrow } from "@/lib/i18n/params"; @@ -18,13 +17,6 @@ export async function generateMetadata({ }; } -export default function Page(props: PageProps<"/[locale]/user/settings">) { - const { params } = props; - const { locale: rawLocale } = use(params); - const locale = getLocaleOrThrow(rawLocale); - - // Enable static rendering - setRequestLocale(locale); - +export default function Page() { return ; } diff --git a/apps/www/app/[locale]/(app)/(dynamic)/(core)/user/settings/subscriptions/page.tsx b/apps/www/app/[locale]/(app)/(dynamic)/(core)/user/settings/subscriptions/page.tsx index 194ffa491..0a81e135e 100644 --- a/apps/www/app/[locale]/(app)/(dynamic)/(core)/user/settings/subscriptions/page.tsx +++ b/apps/www/app/[locale]/(app)/(dynamic)/(core)/user/settings/subscriptions/page.tsx @@ -1,6 +1,5 @@ import type { Metadata } from "next"; -import { getTranslations, setRequestLocale } from "next-intl/server"; -import { use } from "react"; +import { getTranslations } from "next-intl/server"; import { UserSettingsSubscriptionsPage } from "@/components/user/settings/subscriptions-page"; import { getLocaleOrThrow } from "@/lib/i18n/params"; @@ -18,15 +17,6 @@ export async function generateMetadata({ }; } -export default function Page( - props: PageProps<"/[locale]/user/settings/subscriptions"> -) { - const { params } = props; - const { locale: rawLocale } = use(params); - const locale = getLocaleOrThrow(rawLocale); - - // Enable static rendering - setRequestLocale(locale); - +export default function Page() { return ; } diff --git a/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/[slug]/(main)/classes/[id]/forum/page.tsx b/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/[slug]/(main)/classes/[id]/forum/page.tsx index a2b3eff78..e688b1a7c 100644 --- a/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/[slug]/(main)/classes/[id]/forum/page.tsx +++ b/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/[slug]/(main)/classes/[id]/forum/page.tsx @@ -1,19 +1,8 @@ -import { setRequestLocale } from "next-intl/server"; -import { use } from "react"; import { SchoolClassesForumHeader } from "@/components/school/classes/forum/header"; import { SchoolClassesForumList } from "@/components/school/classes/forum/list"; import { SchoolLayoutContent } from "@/components/school/layout-content"; -import { getLocaleOrThrow } from "@/lib/i18n/params"; - -export default function Page( - props: PageProps<"/[locale]/school/[slug]/classes/[id]/forum"> -) { - const { params } = props; - const { locale: rawLocale } = use(params); - const locale = getLocaleOrThrow(rawLocale); - - setRequestLocale(locale); +export default function Page() { return ( diff --git a/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/[slug]/(main)/classes/[id]/layout.tsx b/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/[slug]/(main)/classes/[id]/layout.tsx index b0646e20a..eb0fbfec7 100644 --- a/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/[slug]/(main)/classes/[id]/layout.tsx +++ b/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/[slug]/(main)/classes/[id]/layout.tsx @@ -3,7 +3,7 @@ import { ErrorBoundary } from "@repo/design-system/components/ui/error-boundary" import { routing } from "@repo/internationalization/src/routing"; import { notFound } from "next/navigation"; import { hasLocale } from "next-intl"; -import { setRequestLocale } from "next-intl/server"; + import { use } from "react"; import { SchoolClassesForumPostSheet } from "@/components/school/classes/forum/post-sheet"; import { SchoolClassesHeaderInfo } from "@/components/school/classes/info"; @@ -24,7 +24,6 @@ export default function Layout( } // Enable static rendering - setRequestLocale(locale); const classId = id as Id<"schoolClasses">; diff --git a/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/[slug]/(main)/classes/[id]/materials/page.tsx b/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/[slug]/(main)/classes/[id]/materials/page.tsx index fdac1fe4d..b79eec939 100644 --- a/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/[slug]/(main)/classes/[id]/materials/page.tsx +++ b/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/[slug]/(main)/classes/[id]/materials/page.tsx @@ -1,19 +1,8 @@ -import { setRequestLocale } from "next-intl/server"; -import { use } from "react"; import { SchoolClassesMaterialsHeader } from "@/components/school/classes/materials/header"; import { SchoolClassesMaterialsList } from "@/components/school/classes/materials/list"; import { SchoolLayoutContent } from "@/components/school/layout-content"; -import { getLocaleOrThrow } from "@/lib/i18n/params"; - -export default function Page( - props: PageProps<"/[locale]/school/[slug]/classes/[id]/materials"> -) { - const { params } = props; - const { locale: rawLocale } = use(params); - const locale = getLocaleOrThrow(rawLocale); - - setRequestLocale(locale); +export default function Page() { return ( diff --git a/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/[slug]/(main)/classes/[id]/page.tsx b/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/[slug]/(main)/classes/[id]/page.tsx index 21477f429..b6d2296ed 100644 --- a/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/[slug]/(main)/classes/[id]/page.tsx +++ b/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/[slug]/(main)/classes/[id]/page.tsx @@ -1,7 +1,6 @@ import { routing } from "@repo/internationalization/src/routing"; import { notFound, redirect } from "next/navigation"; import { hasLocale } from "next-intl"; -import { setRequestLocale } from "next-intl/server"; export default async function Page( props: PageProps<"/[locale]/school/[slug]/classes/[id]"> @@ -13,7 +12,5 @@ export default async function Page( notFound(); } - setRequestLocale(locale); - redirect(`/${locale}/school/${slug}/classes/${id}/forum`); } diff --git a/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/[slug]/(main)/classes/[id]/people/page.tsx b/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/[slug]/(main)/classes/[id]/people/page.tsx index c4830ccfb..b9070ba65 100644 --- a/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/[slug]/(main)/classes/[id]/people/page.tsx +++ b/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/[slug]/(main)/classes/[id]/people/page.tsx @@ -1,19 +1,8 @@ -import { setRequestLocale } from "next-intl/server"; -import { use } from "react"; import { SchoolClassesPeopleHeader } from "@/components/school/classes/people/header"; import { SchoolClassesPeopleList } from "@/components/school/classes/people/list"; import { SchoolLayoutContent } from "@/components/school/layout-content"; -import { getLocaleOrThrow } from "@/lib/i18n/params"; - -export default function Page( - props: PageProps<"/[locale]/school/[slug]/classes/[id]/people"> -) { - const { params } = props; - const { locale: rawLocale } = use(params); - const locale = getLocaleOrThrow(rawLocale); - - setRequestLocale(locale); +export default function Page() { return ( diff --git a/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/[slug]/(main)/classes/page.tsx b/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/[slug]/(main)/classes/page.tsx index 29b3f2a0b..409566dca 100644 --- a/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/[slug]/(main)/classes/page.tsx +++ b/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/[slug]/(main)/classes/page.tsx @@ -1,6 +1,5 @@ import type { Metadata } from "next"; -import { getTranslations, setRequestLocale } from "next-intl/server"; -import { use } from "react"; +import { getTranslations } from "next-intl/server"; import { SchoolClassesHeader } from "@/components/school/classes/header"; import { SchoolClassesList } from "@/components/school/classes/list"; import { SchoolLayoutContent } from "@/components/school/layout-content"; @@ -19,15 +18,7 @@ export async function generateMetadata({ }; } -export default function Page( - props: PageProps<"/[locale]/school/[slug]/classes"> -) { - const { params } = props; - const { locale: rawLocale } = use(params); - const locale = getLocaleOrThrow(rawLocale); - - setRequestLocale(locale); - +export default function Page() { return (
diff --git a/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/[slug]/(main)/home/page.tsx b/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/[slug]/(main)/home/page.tsx index 52ea97cb1..734bc8211 100644 --- a/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/[slug]/(main)/home/page.tsx +++ b/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/[slug]/(main)/home/page.tsx @@ -1,6 +1,5 @@ import type { Metadata } from "next"; -import { getTranslations, setRequestLocale } from "next-intl/server"; -import { use } from "react"; +import { getTranslations } from "next-intl/server"; import { SchoolLayoutContent } from "@/components/school/layout-content"; import { getLocaleOrThrow } from "@/lib/i18n/params"; @@ -17,12 +16,6 @@ export async function generateMetadata({ }; } -export default function Page(props: PageProps<"/[locale]/school/[slug]/home">) { - const { params } = props; - const { locale: rawLocale } = use(params); - const locale = getLocaleOrThrow(rawLocale); - - setRequestLocale(locale); - +export default function Page() { return ; } diff --git a/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/[slug]/(main)/layout.tsx b/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/[slug]/(main)/layout.tsx index c9253ea1f..4f8fbe256 100644 --- a/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/[slug]/(main)/layout.tsx +++ b/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/[slug]/(main)/layout.tsx @@ -5,7 +5,7 @@ import { import { routing } from "@repo/internationalization/src/routing"; import { notFound } from "next/navigation"; import { hasLocale } from "next-intl"; -import { setRequestLocale } from "next-intl/server"; + import { use } from "react"; import { SchoolSidebar } from "@/components/school/sidebar"; @@ -18,7 +18,6 @@ export default function Layout(props: LayoutProps<"/[locale]/school/[slug]">) { } // Enable static rendering - setRequestLocale(locale); return ( diff --git a/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/[slug]/(main)/notifications/page.tsx b/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/[slug]/(main)/notifications/page.tsx index ccbcf0404..856ef7d2b 100644 --- a/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/[slug]/(main)/notifications/page.tsx +++ b/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/[slug]/(main)/notifications/page.tsx @@ -1,6 +1,5 @@ import type { Metadata } from "next"; -import { getTranslations, setRequestLocale } from "next-intl/server"; -import { use } from "react"; +import { getTranslations } from "next-intl/server"; import { SchoolLayoutContent } from "@/components/school/layout-content"; import { getLocaleOrThrow } from "@/lib/i18n/params"; @@ -17,14 +16,6 @@ export async function generateMetadata({ }; } -export default function Page( - props: PageProps<"/[locale]/school/[slug]/notifications"> -) { - const { params } = props; - const { locale: rawLocale } = use(params); - const locale = getLocaleOrThrow(rawLocale); - - setRequestLocale(locale); - +export default function Page() { return ; } diff --git a/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/[slug]/layout.tsx b/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/[slug]/layout.tsx index 8a3601ee3..760150e80 100644 --- a/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/[slug]/layout.tsx +++ b/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/[slug]/layout.tsx @@ -5,7 +5,7 @@ import { fetchQuery } from "convex/nextjs"; import type { Metadata } from "next"; import { notFound } from "next/navigation"; import { hasLocale } from "next-intl"; -import { setRequestLocale } from "next-intl/server"; + import { cache, use } from "react"; import { SchoolNotFound } from "@/components/school/not-found"; import { SchoolContextProvider } from "@/lib/context/use-school"; @@ -46,7 +46,6 @@ export default function Layout(props: LayoutProps<"/[locale]/school/[slug]">) { } // Enable static rendering - setRequestLocale(locale); return ( }> diff --git a/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/[slug]/page.tsx b/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/[slug]/page.tsx index a3233873c..9f7c48ed9 100644 --- a/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/[slug]/page.tsx +++ b/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/[slug]/page.tsx @@ -1,7 +1,6 @@ import { routing } from "@repo/internationalization/src/routing"; import { notFound, redirect } from "next/navigation"; import { hasLocale } from "next-intl"; -import { setRequestLocale } from "next-intl/server"; export default async function Page( props: PageProps<"/[locale]/school/[slug]"> @@ -13,7 +12,5 @@ export default async function Page( notFound(); } - setRequestLocale(locale); - redirect(`/${locale}/school/${slug}/home`); } diff --git a/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/layout.tsx b/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/layout.tsx index a978e62a9..168484809 100644 --- a/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/layout.tsx +++ b/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/layout.tsx @@ -1,7 +1,7 @@ import { routing } from "@repo/internationalization/src/routing"; import { notFound } from "next/navigation"; import { hasLocale } from "next-intl"; -import { setRequestLocale } from "next-intl/server"; + import { use } from "react"; import { LayoutAuth } from "./auth"; @@ -14,7 +14,6 @@ export default function Layout(props: LayoutProps<"/[locale]/school">) { } // Enable static rendering - setRequestLocale(locale); return {children}; } diff --git a/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/onboarding/create/page.tsx b/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/onboarding/create/page.tsx index 299b6f5a3..be21922f5 100644 --- a/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/onboarding/create/page.tsx +++ b/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/onboarding/create/page.tsx @@ -2,20 +2,9 @@ import { ArrowLeft02Icon } from "@hugeicons/core-free-icons"; import { HugeIcons } from "@repo/design-system/components/ui/huge-icons"; import NavigationLink from "@repo/design-system/components/ui/navigation-link"; import { useTranslations } from "next-intl"; -import { setRequestLocale } from "next-intl/server"; -import { use } from "react"; -import { getLocaleOrThrow } from "@/lib/i18n/params"; import { SchoolOnboardingCreateForm } from "./form"; -export default function Page( - props: PageProps<"/[locale]/school/onboarding/create"> -) { - const { params } = props; - const { locale: rawLocale } = use(params); - const locale = getLocaleOrThrow(rawLocale); - - setRequestLocale(locale); - +export default function Page() { const t = useTranslations("School.Onboarding"); return ( diff --git a/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/onboarding/join/page.tsx b/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/onboarding/join/page.tsx index 072ebb6e4..eed54babd 100644 --- a/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/onboarding/join/page.tsx +++ b/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/onboarding/join/page.tsx @@ -2,20 +2,9 @@ import { ArrowLeft02Icon } from "@hugeicons/core-free-icons"; import { HugeIcons } from "@repo/design-system/components/ui/huge-icons"; import NavigationLink from "@repo/design-system/components/ui/navigation-link"; import { useTranslations } from "next-intl"; -import { setRequestLocale } from "next-intl/server"; -import { use } from "react"; -import { getLocaleOrThrow } from "@/lib/i18n/params"; import { SchoolOnboardingJoinForm } from "./form"; -export default function Page( - props: PageProps<"/[locale]/school/onboarding/join"> -) { - const { params } = props; - const { locale: rawLocale } = use(params); - const locale = getLocaleOrThrow(rawLocale); - - setRequestLocale(locale); - +export default function Page() { const t = useTranslations("School.Onboarding"); return ( diff --git a/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/onboarding/layout.tsx b/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/onboarding/layout.tsx index ed920c434..f0504beba 100644 --- a/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/onboarding/layout.tsx +++ b/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/onboarding/layout.tsx @@ -2,7 +2,7 @@ import { Particles } from "@repo/design-system/components/ui/particles"; import { routing } from "@repo/internationalization/src/routing"; import { notFound } from "next/navigation"; import { hasLocale } from "next-intl"; -import { setRequestLocale } from "next-intl/server"; + import { use } from "react"; export default function Layout( @@ -16,7 +16,6 @@ export default function Layout( } // Enable static rendering - setRequestLocale(locale); return (
diff --git a/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/onboarding/page.tsx b/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/onboarding/page.tsx index 076d32912..188e1c59e 100644 --- a/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/onboarding/page.tsx +++ b/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/onboarding/page.tsx @@ -1,22 +1,13 @@ import NavigationLink from "@repo/design-system/components/ui/navigation-link"; import Image from "next/image"; import { useTranslations } from "next-intl"; -import { setRequestLocale } from "next-intl/server"; -import { use } from "react"; -import { getLocaleOrThrow } from "@/lib/i18n/params"; import SchoolCreateImage from "@/public/school-create.png"; import SchoolJoinImage from "@/public/school-join.png"; const IMAGE_WIDTH = 238; const IMAGE_HEIGHT = 134; -export default function Page(props: PageProps<"/[locale]/school/onboarding">) { - const { params } = props; - const { locale: rawLocale } = use(params); - const locale = getLocaleOrThrow(rawLocale); - - setRequestLocale(locale); - +export default function Page() { const t = useTranslations("School.Onboarding"); return ( diff --git a/apps/www/app/[locale]/(app)/(dynamic)/school/auth/page.tsx b/apps/www/app/[locale]/(app)/(dynamic)/school/auth/page.tsx index b0b09face..62a9aec7d 100644 --- a/apps/www/app/[locale]/(app)/(dynamic)/school/auth/page.tsx +++ b/apps/www/app/[locale]/(app)/(dynamic)/school/auth/page.tsx @@ -1,16 +1,7 @@ import { Particles } from "@repo/design-system/components/ui/particles"; -import { setRequestLocale } from "next-intl/server"; -import { use } from "react"; import { ComingSoon } from "@/components/shared/coming-soon"; -import { getLocaleOrThrow } from "@/lib/i18n/params"; - -export default function Page(props: PageProps<"/[locale]/school/auth">) { - const { params } = props; - const { locale: rawLocale } = use(params); - const locale = getLocaleOrThrow(rawLocale); - - setRequestLocale(locale); +export default function Page() { return (
) { notFound(); } - setRequestLocale(locale); - return children; } diff --git a/apps/www/app/[locale]/(app)/(dynamic)/school/page.tsx b/apps/www/app/[locale]/(app)/(dynamic)/school/page.tsx index 0fe1e83d5..e08c295f0 100644 --- a/apps/www/app/[locale]/(app)/(dynamic)/school/page.tsx +++ b/apps/www/app/[locale]/(app)/(dynamic)/school/page.tsx @@ -1,18 +1,11 @@ import { Particles } from "@repo/design-system/components/ui/particles"; -import { setRequestLocale } from "next-intl/server"; -import { Suspense, use } from "react"; + +import { Suspense } from "react"; import { School } from "@/components/school"; import { SchoolLoader } from "@/components/school/loader"; import { ComingSoon } from "@/components/shared/coming-soon"; -import { getLocaleOrThrow } from "@/lib/i18n/params"; - -export default function Page(props: PageProps<"/[locale]/school">) { - const { params } = props; - const { locale: rawLocale } = use(params); - const locale = getLocaleOrThrow(rawLocale); - - setRequestLocale(locale); +export default function Page() { return ( }> diff --git a/apps/www/app/[locale]/(app)/(dynamic)/try-out/[product]/[slug]/page.tsx b/apps/www/app/[locale]/(app)/(dynamic)/try-out/[product]/[slug]/page.tsx index c32b635b1..6f45959bc 100644 --- a/apps/www/app/[locale]/(app)/(dynamic)/try-out/[product]/[slug]/page.tsx +++ b/apps/www/app/[locale]/(app)/(dynamic)/try-out/[product]/[slug]/page.tsx @@ -8,7 +8,7 @@ import { routing } from "@repo/internationalization/src/routing"; import { fetchQuery, preloadQuery } from "convex/nextjs"; import { notFound } from "next/navigation"; import { hasLocale } from "next-intl"; -import { getTranslations, setRequestLocale } from "next-intl/server"; +import { getTranslations } from "next-intl/server"; import { TryoutSetProvider } from "@/components/tryout/providers/set-provider"; import { TryoutSetParts } from "@/components/tryout/set-parts"; import { TryoutSetRouteShell } from "@/components/tryout/set-route-shell"; @@ -31,8 +31,6 @@ export default async function Page( notFound(); } - setRequestLocale(locale); - if (!isTryoutProduct(productParam)) { notFound(); } diff --git a/apps/www/app/[locale]/(app)/(dynamic)/try-out/[product]/[slug]/part/[partKey]/page.tsx b/apps/www/app/[locale]/(app)/(dynamic)/try-out/[product]/[slug]/part/[partKey]/page.tsx index abe1f5d46..f78ebc5da 100644 --- a/apps/www/app/[locale]/(app)/(dynamic)/try-out/[product]/[slug]/part/[partKey]/page.tsx +++ b/apps/www/app/[locale]/(app)/(dynamic)/try-out/[product]/[slug]/part/[partKey]/page.tsx @@ -13,7 +13,7 @@ import { fetchQuery, preloadedQueryResult, preloadQuery } from "convex/nextjs"; import { Effect } from "effect"; import { notFound, redirect } from "next/navigation"; import { hasLocale } from "next-intl"; -import { getTranslations, setRequestLocale } from "next-intl/server"; +import { getTranslations } from "next-intl/server"; import { QuestionAnalytics } from "@/app/[locale]/(app)/(static)/(learn)/exercises/[category]/[type]/[material]/[...slug]/analytics"; import { ExerciseArticle } from "@/app/[locale]/(app)/(static)/(learn)/exercises/[category]/[type]/[material]/[...slug]/article"; import { TryoutPartRouteShell } from "@/components/tryout/part-route-shell"; @@ -37,8 +37,6 @@ export default async function Page( notFound(); } - setRequestLocale(locale); - if (!isTryoutProduct(productParam)) { notFound(); } diff --git a/apps/www/app/[locale]/(app)/(dynamic)/try-out/[product]/page.tsx b/apps/www/app/[locale]/(app)/(dynamic)/try-out/[product]/page.tsx index 8926a5a78..2256a0584 100644 --- a/apps/www/app/[locale]/(app)/(dynamic)/try-out/[product]/page.tsx +++ b/apps/www/app/[locale]/(app)/(dynamic)/try-out/[product]/page.tsx @@ -11,7 +11,7 @@ import { routing } from "@repo/internationalization/src/routing"; import { fetchQuery } from "convex/nextjs"; import { notFound } from "next/navigation"; import { hasLocale } from "next-intl"; -import { getTranslations, setRequestLocale } from "next-intl/server"; +import { getTranslations } from "next-intl/server"; import { AppShell } from "@/components/sidebar/app-shell"; import { TryoutCatalogCard } from "@/components/tryout/catalog-card"; import { TryoutCatalogList } from "@/components/tryout/catalog-list"; @@ -36,8 +36,6 @@ export default async function Page( notFound(); } - setRequestLocale(locale); - if (!isTryoutProduct(productParam)) { notFound(); } diff --git a/apps/www/app/[locale]/(app)/(dynamic)/try-out/page.tsx b/apps/www/app/[locale]/(app)/(dynamic)/try-out/page.tsx index 0aedeb3f4..6e5669323 100644 --- a/apps/www/app/[locale]/(app)/(dynamic)/try-out/page.tsx +++ b/apps/www/app/[locale]/(app)/(dynamic)/try-out/page.tsx @@ -3,7 +3,7 @@ import { BreadcrumbJsonLd } from "@repo/seo/json-ld/breadcrumb"; import type { Metadata } from "next"; import { notFound } from "next/navigation"; import { hasLocale, useTranslations } from "next-intl"; -import { getTranslations, setRequestLocale } from "next-intl/server"; +import { getTranslations } from "next-intl/server"; import { use } from "react"; import { AppShell } from "@/components/sidebar/app-shell"; import { TryoutHubPage } from "@/components/tryout/hub-page"; @@ -53,8 +53,6 @@ export default function Page(props: PageProps<"/[locale]/try-out">) { notFound(); } - setRequestLocale(locale); - return ( diff --git a/apps/www/app/[locale]/(app)/(static)/(learn)/articles/[category]/page.tsx b/apps/www/app/[locale]/(app)/(static)/(learn)/articles/[category]/page.tsx index 417edf8b6..f0b21b1ee 100644 --- a/apps/www/app/[locale]/(app)/(static)/(learn)/articles/[category]/page.tsx +++ b/apps/www/app/[locale]/(app)/(static)/(learn)/articles/[category]/page.tsx @@ -11,7 +11,7 @@ import type { Metadata } from "next"; import { cacheLife } from "next/cache"; import { notFound } from "next/navigation"; import { type Locale, useTranslations } from "next-intl"; -import { getTranslations, setRequestLocale } from "next-intl/server"; +import { getTranslations } from "next-intl/server"; import { use } from "react"; import { CardArticle } from "@/components/shared/card-article"; import { ContainerList } from "@/components/shared/container-list"; @@ -101,7 +101,6 @@ export default function Page( } // Enable static rendering - setRequestLocale(locale); const FilePath = getCategoryPath(category); diff --git a/apps/www/app/[locale]/(app)/(static)/(learn)/articles/page.tsx b/apps/www/app/[locale]/(app)/(static)/(learn)/articles/page.tsx index 729d6e72e..148694851 100644 --- a/apps/www/app/[locale]/(app)/(static)/(learn)/articles/page.tsx +++ b/apps/www/app/[locale]/(app)/(static)/(learn)/articles/page.tsx @@ -1,16 +1,6 @@ import { notFound } from "next/navigation"; -import { setRequestLocale } from "next-intl/server"; -import { use } from "react"; -import { getLocaleOrThrow } from "@/lib/i18n/params"; - -export default function Page(props: PageProps<"/[locale]/articles">) { - const { params } = props; - const { locale: rawLocale } = use(params); - const locale = getLocaleOrThrow(rawLocale); - - // Enable static rendering - setRequestLocale(locale); +export default function Page() { // Return 404 for empty articles index page // This prevents soft 404s and tells Google this page doesn't exist // Source: https://developers.google.com/search/docs/crawling-indexing/soft-404s diff --git a/apps/www/app/[locale]/(app)/(static)/(learn)/exercises/[category]/[type]/[material]/[...slug]/layout.tsx b/apps/www/app/[locale]/(app)/(static)/(learn)/exercises/[category]/[type]/[material]/[...slug]/layout.tsx index f39ddf7d3..5dde0ef5f 100644 --- a/apps/www/app/[locale]/(app)/(static)/(learn)/exercises/[category]/[type]/[material]/[...slug]/layout.tsx +++ b/apps/www/app/[locale]/(app)/(static)/(learn)/exercises/[category]/[type]/[material]/[...slug]/layout.tsx @@ -4,7 +4,7 @@ import { getSlugPath } from "@repo/contents/_lib/exercises/slug"; import { parseExercisesType } from "@repo/contents/_lib/exercises/type"; import { cleanSlug } from "@repo/utilities/helper"; import { notFound } from "next/navigation"; -import { setRequestLocale } from "next-intl/server"; + import { use } from "react"; import { ContentViewTracker } from "@/components/tracking/content-view-tracker"; import { AttemptContextProvider } from "@/lib/context/use-attempt"; @@ -32,8 +32,6 @@ export default function Layout( notFound(); } - setRequestLocale(locale); - const lastSlug = slug.at(-1); const baseSlug = lastSlug && isNumber(lastSlug) ? slug.slice(0, -1) : slug; diff --git a/apps/www/app/[locale]/(app)/(static)/(learn)/exercises/[category]/[type]/[material]/[...slug]/page.tsx b/apps/www/app/[locale]/(app)/(static)/(learn)/exercises/[category]/[type]/[material]/[...slug]/page.tsx index 65bb0e6a3..c66d82803 100644 --- a/apps/www/app/[locale]/(app)/(static)/(learn)/exercises/[category]/[type]/[material]/[...slug]/page.tsx +++ b/apps/www/app/[locale]/(app)/(static)/(learn)/exercises/[category]/[type]/[material]/[...slug]/page.tsx @@ -39,7 +39,7 @@ import type { Metadata } from "next"; import { cacheLife } from "next/cache"; import { notFound, permanentRedirect } from "next/navigation"; import type { Locale } from "next-intl"; -import { getTranslations, setRequestLocale } from "next-intl/server"; +import { getTranslations } from "next-intl/server"; import { use } from "react"; import { DeferredAiSheetOpen } from "@/components/ai/deferred-sheet-open"; import { DeferredComments } from "@/components/comments/deferred"; @@ -248,7 +248,6 @@ export default function Page( } // Enable static rendering - setRequestLocale(locale); if (hasInvalidTryOutYearSlug(slug)) { const tryOutSuffixIndex = 1; diff --git a/apps/www/app/[locale]/(app)/(static)/(learn)/exercises/[category]/[type]/[material]/page.tsx b/apps/www/app/[locale]/(app)/(static)/(learn)/exercises/[category]/[type]/[material]/page.tsx index ac53a61c4..8e8ba5be5 100644 --- a/apps/www/app/[locale]/(app)/(static)/(learn)/exercises/[category]/[type]/[material]/page.tsx +++ b/apps/www/app/[locale]/(app)/(static)/(learn)/exercises/[category]/[type]/[material]/page.tsx @@ -21,7 +21,7 @@ import { CollectionPageJsonLd } from "@repo/seo/json-ld/collection-page"; import type { Metadata } from "next"; import { notFound } from "next/navigation"; import type { Locale } from "next-intl"; -import { getTranslations, setRequestLocale } from "next-intl/server"; +import { getTranslations } from "next-intl/server"; import { use } from "react"; import { CardMaterial } from "@/components/shared/card-material"; import { ComingSoon } from "@/components/shared/coming-soon"; @@ -148,7 +148,6 @@ export default function Page( } // Enable static rendering - setRequestLocale(locale); return ( ; } diff --git a/apps/www/app/[locale]/(app)/(static)/(learn)/exercises/[category]/page.tsx b/apps/www/app/[locale]/(app)/(static)/(learn)/exercises/[category]/page.tsx index 6f54a3d69..658a6ce60 100644 --- a/apps/www/app/[locale]/(app)/(static)/(learn)/exercises/[category]/page.tsx +++ b/apps/www/app/[locale]/(app)/(static)/(learn)/exercises/[category]/page.tsx @@ -1,8 +1,7 @@ import { parseExercisesCategory } from "@repo/contents/_lib/exercises/category"; import { notFound } from "next/navigation"; -import { setRequestLocale } from "next-intl/server"; + import { use } from "react"; -import { getLocaleOrThrow } from "@/lib/i18n/params"; import { getStaticParams } from "@/lib/utils/system"; export function generateStaticParams() { @@ -16,8 +15,7 @@ export default function Page( props: PageProps<"/[locale]/exercises/[category]"> ) { const { params } = props; - const { locale: rawLocale, category: rawCategory } = use(params); - const locale = getLocaleOrThrow(rawLocale); + const { category: rawCategory } = use(params); const category = parseExercisesCategory(rawCategory); if (!category) { @@ -25,7 +23,6 @@ export default function Page( } // Enable static rendering - setRequestLocale(locale); // Return 404 for empty exercise category pages // This prevents soft 404s and tells Google these pages don't exist diff --git a/apps/www/app/[locale]/(app)/(static)/(learn)/quran/[surah]/page.tsx b/apps/www/app/[locale]/(app)/(static)/(learn)/quran/[surah]/page.tsx index f8fded1df..aa4c59970 100644 --- a/apps/www/app/[locale]/(app)/(static)/(learn)/quran/[surah]/page.tsx +++ b/apps/www/app/[locale]/(app)/(static)/(learn)/quran/[surah]/page.tsx @@ -24,6 +24,7 @@ import { QuranInterpretation } from "@/components/shared/quran-interpretation"; import { QuranText } from "@/components/shared/quran-text"; import { RefContent } from "@/components/shared/ref-content"; import { WindowVirtualized } from "@/components/shared/window-virtualized"; +import { VirtualProvider } from "@/lib/context/use-virtual"; import { getLocaleOrThrow } from "@/lib/i18n/params"; import { fetchSurahContext, @@ -234,103 +235,108 @@ async function CachedSurahShell({ totalPages={surahData.verses.length} url={`https://nakafa.com/${locale}/quran/${surah}`} /> - - - - - {!!preBismillah && ( -
- {preBismillah.text.arab} -

- {preBismillah.translation[locale] ?? - preBismillah.translation.en} -

-
- )} - - - {surahData.verses.map((verse, index) => { - const transliteration = verse.text.transliteration.en; - const translate = - verse.translation[locale] ?? verse.translation.en; - - const id = slugify( - t("verse-count", { count: verse.number.inSurah }) - ); - - return ( -
-
- -
- - {verse.number.inSurah} - -

- {t("verse-count", { count: verse.number.inSurah })} -

+ + + + + + {!!preBismillah && ( +
+ {preBismillah.text.arab} +

+ {preBismillah.translation[locale] ?? + preBismillah.translation.en} +

+
+ )} + + + {surahData.verses.map((verse, index) => { + const transliteration = verse.text.transliteration.en; + const translate = + verse.translation[locale] ?? verse.translation.en; + + const id = slugify( + t("verse-count", { count: verse.number.inSurah }) + ); + + return ( +
+
+ +
+ + {verse.number.inSurah} + +

+ {t("verse-count", { + count: verse.number.inSurah, + })} +

+
+
+ +
+ + {locale === "id" && ( + + )}
- - -
- - {locale === "id" && ( - // Only available in Indonesian - - )} +
+ {verse.text.arab} +
+

+ {transliteration} +

+

+ {translate} +

- {verse.text.arab} -
-

- {transliteration} -

-

{translate}

-
-
- ); - })} - - - + + + {footer} + {toolbar} + + - {footer} - {toolbar} - - - + + ); } diff --git a/apps/www/app/[locale]/(app)/(static)/(learn)/quran/page.tsx b/apps/www/app/[locale]/(app)/(static)/(learn)/quran/page.tsx index 591a7bc07..3ea08eb65 100644 --- a/apps/www/app/[locale]/(app)/(static)/(learn)/quran/page.tsx +++ b/apps/www/app/[locale]/(app)/(static)/(learn)/quran/page.tsx @@ -4,7 +4,7 @@ import NavigationLink from "@repo/design-system/components/ui/navigation-link"; import { BreadcrumbJsonLd } from "@repo/seo/json-ld/breadcrumb"; import type { Metadata } from "next"; import { type Locale, useTranslations } from "next-intl"; -import { getTranslations, setRequestLocale } from "next-intl/server"; +import { getTranslations } from "next-intl/server"; import { use } from "react"; import { FooterContent } from "@/components/shared/footer-content"; import { HeaderContent } from "@/components/shared/header-content"; @@ -61,7 +61,6 @@ export default function Page(props: PageProps<"/[locale]/quran">) { const locale = getLocaleOrThrow(rawLocale); // Enable static rendering - setRequestLocale(locale); return ; } diff --git a/apps/www/app/[locale]/(app)/(static)/(learn)/subject/[category]/[grade]/[material]/[...slug]/layout.tsx b/apps/www/app/[locale]/(app)/(static)/(learn)/subject/[category]/[grade]/[material]/[...slug]/layout.tsx index c448c691f..6ffcdcf30 100644 --- a/apps/www/app/[locale]/(app)/(static)/(learn)/subject/[category]/[grade]/[material]/[...slug]/layout.tsx +++ b/apps/www/app/[locale]/(app)/(static)/(learn)/subject/[category]/[grade]/[material]/[...slug]/layout.tsx @@ -4,7 +4,7 @@ import { parseMaterial } from "@repo/contents/_lib/subject/material"; import { getSlugPath } from "@repo/contents/_lib/subject/slug"; import { cleanSlug } from "@repo/utilities/helper"; import { notFound } from "next/navigation"; -import { setRequestLocale } from "next-intl/server"; + import { use } from "react"; import { ContentViewTracker } from "@/components/tracking/content-view-tracker"; import { getLocaleOrThrow } from "@/lib/i18n/params"; @@ -29,8 +29,6 @@ export default function Layout( notFound(); } - setRequestLocale(locale); - const filePath = getSlugPath(category, grade, material, slug); const cleanedSlug = cleanSlug(filePath); diff --git a/apps/www/app/[locale]/(app)/(static)/(learn)/subject/[category]/[grade]/[material]/page.tsx b/apps/www/app/[locale]/(app)/(static)/(learn)/subject/[category]/[grade]/[material]/page.tsx index d29ddb4e5..59346b76b 100644 --- a/apps/www/app/[locale]/(app)/(static)/(learn)/subject/[category]/[grade]/[material]/page.tsx +++ b/apps/www/app/[locale]/(app)/(static)/(learn)/subject/[category]/[grade]/[material]/page.tsx @@ -22,7 +22,7 @@ import { CollectionPageJsonLd } from "@repo/seo/json-ld/collection-page"; import type { Metadata } from "next"; import { notFound } from "next/navigation"; import type { Locale } from "next-intl"; -import { getTranslations, setRequestLocale } from "next-intl/server"; +import { getTranslations } from "next-intl/server"; import { use } from "react"; import { CardMaterial } from "@/components/shared/card-material"; import { ComingSoon } from "@/components/shared/coming-soon"; @@ -142,8 +142,6 @@ export default function Page( notFound(); } - setRequestLocale(locale); - return ( ; } diff --git a/apps/www/app/[locale]/(app)/(static)/(learn)/subject/[category]/page.tsx b/apps/www/app/[locale]/(app)/(static)/(learn)/subject/[category]/page.tsx index bc4caad18..1306780de 100644 --- a/apps/www/app/[locale]/(app)/(static)/(learn)/subject/[category]/page.tsx +++ b/apps/www/app/[locale]/(app)/(static)/(learn)/subject/[category]/page.tsx @@ -1,8 +1,7 @@ import { parseSubjectCategory } from "@repo/contents/_lib/subject/category"; import { notFound } from "next/navigation"; -import { setRequestLocale } from "next-intl/server"; + import { use } from "react"; -import { getLocaleOrThrow } from "@/lib/i18n/params"; import { getStaticParams } from "@/lib/utils/system"; export function generateStaticParams() { @@ -14,8 +13,7 @@ export function generateStaticParams() { export default function Page(props: PageProps<"/[locale]/subject/[category]">) { const { params } = props; - const { locale: rawLocale, category: rawCategory } = use(params); - const locale = getLocaleOrThrow(rawLocale); + const { category: rawCategory } = use(params); const category = parseSubjectCategory(rawCategory); if (!category) { @@ -23,7 +21,6 @@ export default function Page(props: PageProps<"/[locale]/subject/[category]">) { } // Enable static rendering - setRequestLocale(locale); // Return 404 for empty category pages // This prevents soft 404s and tells Google these pages don't exist diff --git a/apps/www/app/[locale]/(app)/(static)/(learn)/subject/page.tsx b/apps/www/app/[locale]/(app)/(static)/(learn)/subject/page.tsx index 720f2da31..e23179125 100644 --- a/apps/www/app/[locale]/(app)/(static)/(learn)/subject/page.tsx +++ b/apps/www/app/[locale]/(app)/(static)/(learn)/subject/page.tsx @@ -9,7 +9,7 @@ import NavigationLink from "@repo/design-system/components/ui/navigation-link"; import { BreadcrumbJsonLd } from "@repo/seo/json-ld/breadcrumb"; import type { Metadata } from "next"; import type { Locale } from "next-intl"; -import { getTranslations, setRequestLocale } from "next-intl/server"; +import { getTranslations } from "next-intl/server"; import { use } from "react"; import { HeaderContent } from "@/components/shared/header-content"; import { LayoutContent } from "@/components/shared/layout-content"; @@ -55,8 +55,6 @@ export default function Page(props: PageProps<"/[locale]/subject">) { const { locale: rawLocale } = use(params); const locale = getLocaleOrThrow(rawLocale); - setRequestLocale(locale); - return ; } diff --git a/apps/www/app/[locale]/(app)/(static)/(site)/(legal)/privacy-policy/page.tsx b/apps/www/app/[locale]/(app)/(static)/(site)/(legal)/privacy-policy/page.tsx index 1d5a11fb5..fb3e795af 100644 --- a/apps/www/app/[locale]/(app)/(static)/(site)/(legal)/privacy-policy/page.tsx +++ b/apps/www/app/[locale]/(app)/(static)/(site)/(legal)/privacy-policy/page.tsx @@ -1,7 +1,7 @@ import type { Metadata } from "next"; import { notFound } from "next/navigation"; import type { Locale } from "next-intl"; -import { getTranslations, setRequestLocale } from "next-intl/server"; +import { getTranslations } from "next-intl/server"; import { use } from "react"; import { getLocaleOrThrow } from "@/lib/i18n/params"; @@ -27,7 +27,6 @@ export default function Page(props: PageProps<"/[locale]/privacy-policy">) { const locale = getLocaleOrThrow(use(params).locale); // Enable static rendering - setRequestLocale(locale); return ; } diff --git a/apps/www/app/[locale]/(app)/(static)/(site)/(legal)/security-policy/page.tsx b/apps/www/app/[locale]/(app)/(static)/(site)/(legal)/security-policy/page.tsx index 434003973..5dbaf27f8 100644 --- a/apps/www/app/[locale]/(app)/(static)/(site)/(legal)/security-policy/page.tsx +++ b/apps/www/app/[locale]/(app)/(static)/(site)/(legal)/security-policy/page.tsx @@ -1,7 +1,7 @@ import type { Metadata } from "next"; import { notFound } from "next/navigation"; import type { Locale } from "next-intl"; -import { getTranslations, setRequestLocale } from "next-intl/server"; +import { getTranslations } from "next-intl/server"; import { use } from "react"; import { getLocaleOrThrow } from "@/lib/i18n/params"; @@ -27,7 +27,6 @@ export default function Page(props: PageProps<"/[locale]/security-policy">) { const locale = getLocaleOrThrow(use(params).locale); // Enable static rendering - setRequestLocale(locale); return ; } diff --git a/apps/www/app/[locale]/(app)/(static)/(site)/(legal)/terms-of-service/page.tsx b/apps/www/app/[locale]/(app)/(static)/(site)/(legal)/terms-of-service/page.tsx index 8a3f7a4a3..d44db4897 100644 --- a/apps/www/app/[locale]/(app)/(static)/(site)/(legal)/terms-of-service/page.tsx +++ b/apps/www/app/[locale]/(app)/(static)/(site)/(legal)/terms-of-service/page.tsx @@ -1,7 +1,7 @@ import type { Metadata } from "next"; import { notFound } from "next/navigation"; import type { Locale } from "next-intl"; -import { getTranslations, setRequestLocale } from "next-intl/server"; +import { getTranslations } from "next-intl/server"; import { use } from "react"; import { getLocaleOrThrow } from "@/lib/i18n/params"; @@ -27,7 +27,6 @@ export default function Page(props: PageProps<"/[locale]/terms-of-service">) { const locale = getLocaleOrThrow(use(params).locale); // Enable static rendering - setRequestLocale(locale); return ; } diff --git a/apps/www/app/[locale]/(app)/(static)/(site)/about/page.tsx b/apps/www/app/[locale]/(app)/(static)/(site)/about/page.tsx index 62146ab1d..73aa27ace 100644 --- a/apps/www/app/[locale]/(app)/(static)/(site)/about/page.tsx +++ b/apps/www/app/[locale]/(app)/(static)/(site)/about/page.tsx @@ -5,7 +5,7 @@ import { FAQPageJsonLd } from "@repo/seo/json-ld/faq-page"; import type { ListItem } from "@repo/seo/types"; import type { Metadata } from "next"; import type { Locale } from "next-intl"; -import { getTranslations, setRequestLocale } from "next-intl/server"; +import { getTranslations } from "next-intl/server"; import { use } from "react"; import { Ai } from "@/components/marketing/about/ai"; import { Community } from "@/components/marketing/about/community"; @@ -76,7 +76,6 @@ export default function Page(props: PageProps<"/[locale]/about">) { const locale = getLocaleOrThrow(rawLocale); // Enable static rendering - setRequestLocale(locale); return ; } diff --git a/apps/www/app/[locale]/(app)/(static)/(site)/ask/[slug]/page.tsx b/apps/www/app/[locale]/(app)/(static)/(site)/ask/[slug]/page.tsx index 3ba24b0b6..9dfe20220 100644 --- a/apps/www/app/[locale]/(app)/(static)/(site)/ask/[slug]/page.tsx +++ b/apps/www/app/[locale]/(app)/(static)/(site)/ask/[slug]/page.tsx @@ -1,7 +1,7 @@ import { askSeo } from "@repo/seo/ask"; import { FAQPageJsonLd } from "@repo/seo/json-ld/faq-page"; import type { Metadata } from "next"; -import { setRequestLocale } from "next-intl/server"; + import { use } from "react"; import { AskCta } from "@/components/ask/cta"; import { AskListItems } from "@/components/ask/results"; @@ -59,7 +59,6 @@ export default function Page(props: PageProps<"/[locale]/ask/[slug]">) { const locale = getLocaleOrThrow(rawLocale); // Enable static rendering - setRequestLocale(locale); const seoData = askData.find((data) => data.slug === slug); diff --git a/apps/www/app/[locale]/(app)/(static)/(site)/contributor/page.tsx b/apps/www/app/[locale]/(app)/(static)/(site)/contributor/page.tsx index 21deacfac..7e70503d6 100644 --- a/apps/www/app/[locale]/(app)/(static)/(site)/contributor/page.tsx +++ b/apps/www/app/[locale]/(app)/(static)/(site)/contributor/page.tsx @@ -2,8 +2,7 @@ import { LoveKoreanFingerIcon } from "@hugeicons/core-free-icons"; import { Avatar } from "@repo/design-system/components/contributor/avatar"; import type { Metadata } from "next"; import { useTranslations } from "next-intl"; -import { getTranslations, setRequestLocale } from "next-intl/server"; -import { use } from "react"; +import { getTranslations } from "next-intl/server"; import { HeaderContent } from "@/components/shared/header-content"; import { LayoutContent } from "@/components/shared/layout-content"; import { contributors } from "@/lib/data/contributor"; @@ -26,13 +25,7 @@ export async function generateMetadata({ }; } -export default function Page(props: PageProps<"/[locale]/contributor">) { - const { params } = props; - const locale = getLocaleOrThrow(use(params).locale); - - // Enable static rendering - setRequestLocale(locale); - +export default function Page() { return ( <> diff --git a/apps/www/app/[locale]/(app)/(static)/(site)/events/page.tsx b/apps/www/app/[locale]/(app)/(static)/(site)/events/page.tsx index c72d52278..7b969b33e 100644 --- a/apps/www/app/[locale]/(app)/(static)/(site)/events/page.tsx +++ b/apps/www/app/[locale]/(app)/(static)/(site)/events/page.tsx @@ -1,6 +1,5 @@ import type { Metadata } from "next"; -import { getTranslations, setRequestLocale } from "next-intl/server"; -import { use } from "react"; +import { getTranslations } from "next-intl/server"; import { getLocaleOrThrow } from "@/lib/i18n/params"; export async function generateMetadata({ @@ -20,12 +19,6 @@ export async function generateMetadata({ }; } -export default function Page(props: PageProps<"/[locale]/events">) { - const { params } = props; - const locale = getLocaleOrThrow(use(params).locale); - - // Enable static rendering - setRequestLocale(locale); - +export default function Page() { return null; } diff --git a/apps/www/app/[locale]/(app)/(static)/(site)/home/page.tsx b/apps/www/app/[locale]/(app)/(static)/(site)/home/page.tsx index ab81c8b41..a4fac3536 100644 --- a/apps/www/app/[locale]/(app)/(static)/(site)/home/page.tsx +++ b/apps/www/app/[locale]/(app)/(static)/(site)/home/page.tsx @@ -1,5 +1,5 @@ import { redirect } from "@repo/internationalization/src/navigation"; -import { setRequestLocale } from "next-intl/server"; + import { use } from "react"; import { getLocaleOrThrow } from "@/lib/i18n/params"; @@ -8,7 +8,6 @@ export default function Page(props: PageProps<"/[locale]/home">) { const locale = getLocaleOrThrow(use(params).locale); // Enable static rendering - setRequestLocale(locale); // This is empty page, redirect to home page redirect({ href: "/about", locale }); diff --git a/apps/www/components/shared/layout-content.tsx b/apps/www/components/shared/layout-content.tsx index 27fd552b6..19be2a719 100644 --- a/apps/www/components/shared/layout-content.tsx +++ b/apps/www/components/shared/layout-content.tsx @@ -10,7 +10,10 @@ interface Props { export function LayoutContent({ children, className, as = "article" }: Props) { const Component = as || "article"; return ( - + {children} ); diff --git a/apps/www/components/shared/layout-material.tsx b/apps/www/components/shared/layout-material.tsx index d31b2be6a..b52bc7722 100644 --- a/apps/www/components/shared/layout-material.tsx +++ b/apps/www/components/shared/layout-material.tsx @@ -1,7 +1,6 @@ import type { ParsedHeading } from "@repo/contents/_types/toc"; import { cn } from "@repo/design-system/lib/utils"; import type { ComponentProps, ReactNode } from "react"; -import { VirtualProvider } from "@/lib/context/use-virtual"; import { FooterContent } from "./footer-content"; import { HeaderContent } from "./header-content"; import { LayoutContent } from "./layout-content"; @@ -81,9 +80,5 @@ export function LayoutMaterialToc({ } export function LayoutMaterial({ className, ...props }: ComponentProps<"div">) { - return ( - -
- - ); + return
; } diff --git a/apps/www/components/sidebar/app-shell.tsx b/apps/www/components/sidebar/app-shell.tsx index 79c5c2baf..8ad960fff 100644 --- a/apps/www/components/sidebar/app-shell.tsx +++ b/apps/www/components/sidebar/app-shell.tsx @@ -30,9 +30,7 @@ export function AppShell({
-
- {children} -
+
{children}
diff --git a/apps/www/lib/context/use-virtual.tsx b/apps/www/lib/context/use-virtual.tsx index 86a04af30..707e1abbc 100644 --- a/apps/www/lib/context/use-virtual.tsx +++ b/apps/www/lib/context/use-virtual.tsx @@ -9,7 +9,14 @@ interface VirtualContextType { virtualRef: RefObject; } -const VirtualContext = createContext(undefined); +const fallbackVirtualRef = { + current: null, +} satisfies RefObject; + +const VirtualContext = createContext({ + scrollToIndex: () => undefined, + virtualRef: fallbackVirtualRef, +}); export function VirtualProvider({ children }: { children: React.ReactNode }) { const virtualRef = useRef(null); @@ -34,9 +41,5 @@ export function VirtualProvider({ children }: { children: React.ReactNode }) { } export function useVirtual(selector: (context: VirtualContextType) => T): T { - const context = useContextSelector(VirtualContext, (value) => value); - if (context === undefined) { - throw new Error("useVirtual must be used within a VirtualProvider."); - } - return selector(context); + return useContextSelector(VirtualContext, selector); } From 013ca64bad356375532a75a469fc57a382e8a0d2 Mon Sep 17 00:00:00 2001 From: Nabil Akbarazzima Fatih Date: Fri, 10 Apr 2026 00:03:32 +0200 Subject: [PATCH 03/20] Add Pagefind indexer and enable indexing Add a Node script that builds a Pagefind index directly from MDX/content source (apps/www/scripts/pagefind.ts) and switch postbuild to run it. Remove data-pagefind-ignore attributes across pages and components so their content is included. Add remark + remark-mdx deps, fix MDX content types and rendering (call Content component, extract exercise Q/A), and remove stale "Enable static rendering" comments. --- .../(app)/(dynamic)/(core)/chat/layout.tsx | 2 +- .../(app)/(dynamic)/(core)/chat/page.tsx | 5 +- .../(core)/event/try-out/[code]/page.tsx | 2 - .../[locale]/(app)/(dynamic)/(core)/page.tsx | 5 +- .../(app)/(dynamic)/(core)/search/page.tsx | 5 +- .../(dynamic)/(core)/user/[id]/layout.tsx | 2 - .../(app)/(dynamic)/(core)/user/layout.tsx | 7 +- .../(dynamic)/(core)/user/settings/layout.tsx | 2 - .../[locale]/(app)/(dynamic)/auth/page.tsx | 2 +- .../[slug]/(main)/classes/[id]/layout.tsx | 2 - .../(authenticated)/[slug]/(main)/layout.tsx | 2 - .../school/(authenticated)/[slug]/layout.tsx | 2 - .../school/(authenticated)/layout.tsx | 2 - .../(authenticated)/onboarding/layout.tsx | 2 - .../(app)/(dynamic)/school/auth/page.tsx | 5 +- .../[locale]/(app)/(dynamic)/try-out/page.tsx | 2 +- .../articles/[category]/[slug]/page.tsx | 2 +- .../(learn)/articles/[category]/page.tsx | 2 - .../[type]/[material]/[...slug]/article.tsx | 7 +- .../[type]/[material]/[...slug]/page.tsx | 2 - .../[category]/[type]/[material]/page.tsx | 2 - .../exercises/[category]/[type]/page.tsx | 2 - .../(learn)/exercises/[category]/page.tsx | 2 - .../(app)/(static)/(learn)/quran/page.tsx | 2 - .../[grade]/[material]/[...slug]/page.tsx | 2 +- .../subject/[category]/[grade]/page.tsx | 2 - .../(learn)/subject/[category]/page.tsx | 2 - .../(site)/(legal)/privacy-policy/page.tsx | 4 +- .../(site)/(legal)/security-policy/page.tsx | 4 +- .../(site)/(legal)/terms-of-service/page.tsx | 4 +- .../(app)/(static)/(site)/about/page.tsx | 4 +- .../(app)/(static)/(site)/ask/[slug]/page.tsx | 4 +- .../(app)/(static)/(site)/home/page.tsx | 2 - apps/www/app/[locale]/(app)/error.tsx | 5 +- apps/www/app/[locale]/(app)/not-found.tsx | 5 +- apps/www/app/global-error.tsx | 5 +- apps/www/app/global-not-found.tsx | 5 +- apps/www/components/ai/chat-sidebar.tsx | 2 +- apps/www/components/shared/coming-soon.tsx | 2 +- apps/www/components/shared/footer-content.tsx | 2 +- apps/www/components/shared/header-content.tsx | 2 +- apps/www/components/shared/layout-content.tsx | 5 +- apps/www/components/shared/sidebar-right.tsx | 2 +- apps/www/package.json | 4 +- apps/www/scripts/pagefind.ts | 392 ++++++++++++++++++ packages/contents/_lib/content.ts | 3 +- packages/contents/_lib/exercises.ts | 21 +- packages/contents/_lib/scoped.ts | 4 +- packages/contents/_types/content.ts | 4 +- pnpm-lock.yaml | 18 + 50 files changed, 450 insertions(+), 129 deletions(-) create mode 100644 apps/www/scripts/pagefind.ts diff --git a/apps/www/app/[locale]/(app)/(dynamic)/(core)/chat/layout.tsx b/apps/www/app/[locale]/(app)/(dynamic)/(core)/chat/layout.tsx index 8e8cffa44..956eff4cc 100644 --- a/apps/www/app/[locale]/(app)/(dynamic)/(core)/chat/layout.tsx +++ b/apps/www/app/[locale]/(app)/(dynamic)/(core)/chat/layout.tsx @@ -4,7 +4,7 @@ import { AiChatSidebar } from "@/components/ai/chat-sidebar"; export default function Layout(props: LayoutProps<"/[locale]/chat">) { const { children } = props; return ( -
+
{children} diff --git a/apps/www/app/[locale]/(app)/(dynamic)/(core)/chat/page.tsx b/apps/www/app/[locale]/(app)/(dynamic)/(core)/chat/page.tsx index 662ed7da5..5d6dd9767 100644 --- a/apps/www/app/[locale]/(app)/(dynamic)/(core)/chat/page.tsx +++ b/apps/www/app/[locale]/(app)/(dynamic)/(core)/chat/page.tsx @@ -6,10 +6,7 @@ import { Weather } from "@/components/ai/weather"; export default function Page() { return ( -
+
diff --git a/apps/www/app/[locale]/(app)/(dynamic)/(core)/event/try-out/[code]/page.tsx b/apps/www/app/[locale]/(app)/(dynamic)/(core)/event/try-out/[code]/page.tsx index 838eaddbc..9efe97c92 100644 --- a/apps/www/app/[locale]/(app)/(dynamic)/(core)/event/try-out/[code]/page.tsx +++ b/apps/www/app/[locale]/(app)/(dynamic)/(core)/event/try-out/[code]/page.tsx @@ -7,7 +7,5 @@ export default function Page( const { params } = props; const { code } = use(params); - // Enable static rendering - return ; } diff --git a/apps/www/app/[locale]/(app)/(dynamic)/(core)/page.tsx b/apps/www/app/[locale]/(app)/(dynamic)/(core)/page.tsx index c8f1e72ac..ba46268b1 100644 --- a/apps/www/app/[locale]/(app)/(dynamic)/(core)/page.tsx +++ b/apps/www/app/[locale]/(app)/(dynamic)/(core)/page.tsx @@ -18,10 +18,7 @@ export default function Page(props: PageProps<"/[locale]">) { return ( <> -
+
diff --git a/apps/www/app/[locale]/(app)/(dynamic)/(core)/search/page.tsx b/apps/www/app/[locale]/(app)/(dynamic)/(core)/search/page.tsx index 84826e528..ffc04a42c 100644 --- a/apps/www/app/[locale]/(app)/(dynamic)/(core)/search/page.tsx +++ b/apps/www/app/[locale]/(app)/(dynamic)/(core)/search/page.tsx @@ -26,10 +26,7 @@ export async function generateMetadata({ export default function Page() { return ( -
+
diff --git a/apps/www/app/[locale]/(app)/(dynamic)/(core)/user/[id]/layout.tsx b/apps/www/app/[locale]/(app)/(dynamic)/(core)/user/[id]/layout.tsx index 8e2a95c58..23da9f741 100644 --- a/apps/www/app/[locale]/(app)/(dynamic)/(core)/user/[id]/layout.tsx +++ b/apps/www/app/[locale]/(app)/(dynamic)/(core)/user/[id]/layout.tsx @@ -17,8 +17,6 @@ export default function Layout(props: LayoutProps<"/[locale]/user/[id]">) { notFound(); } - // Enable static rendering - const userId = id as Id<"users">; return ( diff --git a/apps/www/app/[locale]/(app)/(dynamic)/(core)/user/layout.tsx b/apps/www/app/[locale]/(app)/(dynamic)/(core)/user/layout.tsx index efcc949f3..7561f7ebc 100644 --- a/apps/www/app/[locale]/(app)/(dynamic)/(core)/user/layout.tsx +++ b/apps/www/app/[locale]/(app)/(dynamic)/(core)/user/layout.tsx @@ -12,13 +12,8 @@ export default function Layout(props: LayoutProps<"/[locale]/user">) { notFound(); } - // Enable static rendering - return ( -
+
{children}
); diff --git a/apps/www/app/[locale]/(app)/(dynamic)/(core)/user/settings/layout.tsx b/apps/www/app/[locale]/(app)/(dynamic)/(core)/user/settings/layout.tsx index 557d7b18e..f2e685fdc 100644 --- a/apps/www/app/[locale]/(app)/(dynamic)/(core)/user/settings/layout.tsx +++ b/apps/www/app/[locale]/(app)/(dynamic)/(core)/user/settings/layout.tsx @@ -14,8 +14,6 @@ export default function Layout(props: LayoutProps<"/[locale]/user/settings">) { notFound(); } - // Enable static rendering - const t = useTranslations("Auth"); return ( diff --git a/apps/www/app/[locale]/(app)/(dynamic)/auth/page.tsx b/apps/www/app/[locale]/(app)/(dynamic)/auth/page.tsx index 963c8d476..108bb2491 100644 --- a/apps/www/app/[locale]/(app)/(dynamic)/auth/page.tsx +++ b/apps/www/app/[locale]/(app)/(dynamic)/auth/page.tsx @@ -10,7 +10,7 @@ export default async function Page() { const locale = await getLocale(); return ( -
+
diff --git a/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/[slug]/(main)/classes/[id]/layout.tsx b/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/[slug]/(main)/classes/[id]/layout.tsx index eb0fbfec7..1282407b5 100644 --- a/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/[slug]/(main)/classes/[id]/layout.tsx +++ b/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/[slug]/(main)/classes/[id]/layout.tsx @@ -23,8 +23,6 @@ export default function Layout( notFound(); } - // Enable static rendering - const classId = id as Id<"schoolClasses">; return ( diff --git a/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/[slug]/(main)/layout.tsx b/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/[slug]/(main)/layout.tsx index 4f8fbe256..b62fa1ba2 100644 --- a/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/[slug]/(main)/layout.tsx +++ b/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/[slug]/(main)/layout.tsx @@ -17,8 +17,6 @@ export default function Layout(props: LayoutProps<"/[locale]/school/[slug]">) { notFound(); } - // Enable static rendering - return ( diff --git a/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/[slug]/layout.tsx b/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/[slug]/layout.tsx index 760150e80..9c7160a57 100644 --- a/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/[slug]/layout.tsx +++ b/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/[slug]/layout.tsx @@ -45,8 +45,6 @@ export default function Layout(props: LayoutProps<"/[locale]/school/[slug]">) { notFound(); } - // Enable static rendering - return ( }> diff --git a/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/layout.tsx b/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/layout.tsx index 168484809..416e2555a 100644 --- a/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/layout.tsx +++ b/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/layout.tsx @@ -13,7 +13,5 @@ export default function Layout(props: LayoutProps<"/[locale]/school">) { notFound(); } - // Enable static rendering - return {children}; } diff --git a/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/onboarding/layout.tsx b/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/onboarding/layout.tsx index f0504beba..a25e5e028 100644 --- a/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/onboarding/layout.tsx +++ b/apps/www/app/[locale]/(app)/(dynamic)/school/(authenticated)/onboarding/layout.tsx @@ -15,8 +15,6 @@ export default function Layout( notFound(); } - // Enable static rendering - return (
diff --git a/apps/www/app/[locale]/(app)/(dynamic)/school/auth/page.tsx b/apps/www/app/[locale]/(app)/(dynamic)/school/auth/page.tsx index 62a9aec7d..56efe2e08 100644 --- a/apps/www/app/[locale]/(app)/(dynamic)/school/auth/page.tsx +++ b/apps/www/app/[locale]/(app)/(dynamic)/school/auth/page.tsx @@ -3,10 +3,7 @@ import { ComingSoon } from "@/components/shared/coming-soon"; export default function Page() { return ( -
+
diff --git a/apps/www/app/[locale]/(app)/(dynamic)/try-out/page.tsx b/apps/www/app/[locale]/(app)/(dynamic)/try-out/page.tsx index 6e5669323..d0a9b0e83 100644 --- a/apps/www/app/[locale]/(app)/(dynamic)/try-out/page.tsx +++ b/apps/www/app/[locale]/(app)/(dynamic)/try-out/page.tsx @@ -56,7 +56,7 @@ export default function Page(props: PageProps<"/[locale]/try-out">) { return ( -
+
diff --git a/apps/www/app/[locale]/(app)/(static)/(learn)/articles/[category]/[slug]/page.tsx b/apps/www/app/[locale]/(app)/(static)/(learn)/articles/[category]/[slug]/page.tsx index 118262670..cc2cd6b6b 100644 --- a/apps/www/app/[locale]/(app)/(static)/(learn)/articles/[category]/[slug]/page.tsx +++ b/apps/www/app/[locale]/(app)/(static)/(learn)/articles/[category]/[slug]/page.tsx @@ -282,7 +282,7 @@ async function CachedArticleShell({ /> {headings.length === 0 && } - {headings.length > 0 && Content} + {headings.length > 0 && Content ? : null} {footer} {toolbar} diff --git a/apps/www/app/[locale]/(app)/(static)/(learn)/articles/[category]/page.tsx b/apps/www/app/[locale]/(app)/(static)/(learn)/articles/[category]/page.tsx index f0b21b1ee..2b8c81af0 100644 --- a/apps/www/app/[locale]/(app)/(static)/(learn)/articles/[category]/page.tsx +++ b/apps/www/app/[locale]/(app)/(static)/(learn)/articles/[category]/page.tsx @@ -100,8 +100,6 @@ export default function Page( notFound(); } - // Enable static rendering - const FilePath = getCategoryPath(category); return ( diff --git a/apps/www/app/[locale]/(app)/(static)/(learn)/exercises/[category]/[type]/[material]/[...slug]/article.tsx b/apps/www/app/[locale]/(app)/(static)/(learn)/exercises/[category]/[type]/[material]/[...slug]/article.tsx index bb158803f..c4bbddc05 100644 --- a/apps/www/app/[locale]/(app)/(static)/(learn)/exercises/[category]/[type]/[material]/[...slug]/article.tsx +++ b/apps/www/app/[locale]/(app)/(static)/(learn)/exercises/[category]/[type]/[material]/[...slug]/article.tsx @@ -12,6 +12,9 @@ interface Props { } export function ExerciseArticle({ exercise, locale, id, srLabel }: Props) { + const Question = exercise.question.default; + const Answer = exercise.answer.default; + return (
@@ -32,7 +35,7 @@ export function ExerciseArticle({ exercise, locale, id, srLabel }: Props) {
-
{exercise.question.default}
+
{Question ? : null}
- {exercise.answer.default} + {Answer ? : null}
); diff --git a/apps/www/app/[locale]/(app)/(static)/(learn)/exercises/[category]/[type]/[material]/[...slug]/page.tsx b/apps/www/app/[locale]/(app)/(static)/(learn)/exercises/[category]/[type]/[material]/[...slug]/page.tsx index c66d82803..8b796ca4d 100644 --- a/apps/www/app/[locale]/(app)/(static)/(learn)/exercises/[category]/[type]/[material]/[...slug]/page.tsx +++ b/apps/www/app/[locale]/(app)/(static)/(learn)/exercises/[category]/[type]/[material]/[...slug]/page.tsx @@ -247,8 +247,6 @@ export default function Page( notFound(); } - // Enable static rendering - if (hasInvalidTryOutYearSlug(slug)) { const tryOutSuffixIndex = 1; const legacyTryOutSuffix = slug.slice(tryOutSuffixIndex); diff --git a/apps/www/app/[locale]/(app)/(static)/(learn)/exercises/[category]/[type]/[material]/page.tsx b/apps/www/app/[locale]/(app)/(static)/(learn)/exercises/[category]/[type]/[material]/page.tsx index 8e8ba5be5..42af0256c 100644 --- a/apps/www/app/[locale]/(app)/(static)/(learn)/exercises/[category]/[type]/[material]/page.tsx +++ b/apps/www/app/[locale]/(app)/(static)/(learn)/exercises/[category]/[type]/[material]/page.tsx @@ -147,8 +147,6 @@ export default function Page( notFound(); } - // Enable static rendering - return ( ; } diff --git a/apps/www/app/[locale]/(app)/(static)/(learn)/exercises/[category]/page.tsx b/apps/www/app/[locale]/(app)/(static)/(learn)/exercises/[category]/page.tsx index 658a6ce60..ad592f1d9 100644 --- a/apps/www/app/[locale]/(app)/(static)/(learn)/exercises/[category]/page.tsx +++ b/apps/www/app/[locale]/(app)/(static)/(learn)/exercises/[category]/page.tsx @@ -22,8 +22,6 @@ export default function Page( notFound(); } - // Enable static rendering - // Return 404 for empty exercise category pages // This prevents soft 404s and tells Google these pages don't exist // Source: https://developers.google.com/search/docs/crawling-indexing/soft-404s diff --git a/apps/www/app/[locale]/(app)/(static)/(learn)/quran/page.tsx b/apps/www/app/[locale]/(app)/(static)/(learn)/quran/page.tsx index 3ea08eb65..502e5f6db 100644 --- a/apps/www/app/[locale]/(app)/(static)/(learn)/quran/page.tsx +++ b/apps/www/app/[locale]/(app)/(static)/(learn)/quran/page.tsx @@ -60,8 +60,6 @@ export default function Page(props: PageProps<"/[locale]/quran">) { const { locale: rawLocale } = use(params); const locale = getLocaleOrThrow(rawLocale); - // Enable static rendering - return ; } diff --git a/apps/www/app/[locale]/(app)/(static)/(learn)/subject/[category]/[grade]/[material]/[...slug]/page.tsx b/apps/www/app/[locale]/(app)/(static)/(learn)/subject/[category]/[grade]/[material]/[...slug]/page.tsx index cc620b152..ac384e8f8 100644 --- a/apps/www/app/[locale]/(app)/(static)/(learn)/subject/[category]/[grade]/[material]/[...slug]/page.tsx +++ b/apps/www/app/[locale]/(app)/(static)/(learn)/subject/[category]/[grade]/[material]/[...slug]/page.tsx @@ -368,7 +368,7 @@ async function CachedSubjectShell({ /> {headings.length === 0 && } - {headings.length > 0 && Content} + {headings.length > 0 && Content ? : null} {footer} diff --git a/apps/www/app/[locale]/(app)/(static)/(learn)/subject/[category]/[grade]/page.tsx b/apps/www/app/[locale]/(app)/(static)/(learn)/subject/[category]/[grade]/page.tsx index 7784a322c..4ae163ce8 100644 --- a/apps/www/app/[locale]/(app)/(static)/(learn)/subject/[category]/[grade]/page.tsx +++ b/apps/www/app/[locale]/(app)/(static)/(learn)/subject/[category]/[grade]/page.tsx @@ -141,8 +141,6 @@ export default function Page( notFound(); } - // Enable static rendering - return ; } diff --git a/apps/www/app/[locale]/(app)/(static)/(learn)/subject/[category]/page.tsx b/apps/www/app/[locale]/(app)/(static)/(learn)/subject/[category]/page.tsx index 1306780de..8dbff0011 100644 --- a/apps/www/app/[locale]/(app)/(static)/(learn)/subject/[category]/page.tsx +++ b/apps/www/app/[locale]/(app)/(static)/(learn)/subject/[category]/page.tsx @@ -20,8 +20,6 @@ export default function Page(props: PageProps<"/[locale]/subject/[category]">) { notFound(); } - // Enable static rendering - // Return 404 for empty category pages // This prevents soft 404s and tells Google these pages don't exist // Source: https://developers.google.com/search/docs/crawling-indexing/soft-404s diff --git a/apps/www/app/[locale]/(app)/(static)/(site)/(legal)/privacy-policy/page.tsx b/apps/www/app/[locale]/(app)/(static)/(site)/(legal)/privacy-policy/page.tsx index fb3e795af..55b7e19ae 100644 --- a/apps/www/app/[locale]/(app)/(static)/(site)/(legal)/privacy-policy/page.tsx +++ b/apps/www/app/[locale]/(app)/(static)/(site)/(legal)/privacy-policy/page.tsx @@ -26,8 +26,6 @@ export default function Page(props: PageProps<"/[locale]/privacy-policy">) { const { params } = props; const locale = getLocaleOrThrow(use(params).locale); - // Enable static rendering - return ; } @@ -40,7 +38,7 @@ async function PageContent({ locale }: { locale: Locale }) { } return ( -
+
); diff --git a/apps/www/app/[locale]/(app)/(static)/(site)/(legal)/security-policy/page.tsx b/apps/www/app/[locale]/(app)/(static)/(site)/(legal)/security-policy/page.tsx index 5dbaf27f8..3cab20de9 100644 --- a/apps/www/app/[locale]/(app)/(static)/(site)/(legal)/security-policy/page.tsx +++ b/apps/www/app/[locale]/(app)/(static)/(site)/(legal)/security-policy/page.tsx @@ -26,8 +26,6 @@ export default function Page(props: PageProps<"/[locale]/security-policy">) { const { params } = props; const locale = getLocaleOrThrow(use(params).locale); - // Enable static rendering - return ; } @@ -40,7 +38,7 @@ async function PageContent({ locale }: { locale: Locale }) { } return ( -
+
); diff --git a/apps/www/app/[locale]/(app)/(static)/(site)/(legal)/terms-of-service/page.tsx b/apps/www/app/[locale]/(app)/(static)/(site)/(legal)/terms-of-service/page.tsx index d44db4897..bd61a2176 100644 --- a/apps/www/app/[locale]/(app)/(static)/(site)/(legal)/terms-of-service/page.tsx +++ b/apps/www/app/[locale]/(app)/(static)/(site)/(legal)/terms-of-service/page.tsx @@ -26,8 +26,6 @@ export default function Page(props: PageProps<"/[locale]/terms-of-service">) { const { params } = props; const locale = getLocaleOrThrow(use(params).locale); - // Enable static rendering - return ; } @@ -40,7 +38,7 @@ async function PageContent({ locale }: { locale: Locale }) { } return ( -
+
); diff --git a/apps/www/app/[locale]/(app)/(static)/(site)/about/page.tsx b/apps/www/app/[locale]/(app)/(static)/(site)/about/page.tsx index 73aa27ace..ea18e0066 100644 --- a/apps/www/app/[locale]/(app)/(static)/(site)/about/page.tsx +++ b/apps/www/app/[locale]/(app)/(static)/(site)/about/page.tsx @@ -75,8 +75,6 @@ export default function Page(props: PageProps<"/[locale]/about">) { const { locale: rawLocale } = use(params); const locale = getLocaleOrThrow(rawLocale); - // Enable static rendering - return ; } @@ -163,7 +161,7 @@ async function AboutPageContent({ locale }: { locale: Locale }) { }))} url={`https://nakafa.com/${locale}/about`} /> -
+
diff --git a/apps/www/app/[locale]/(app)/(static)/(site)/ask/[slug]/page.tsx b/apps/www/app/[locale]/(app)/(static)/(site)/ask/[slug]/page.tsx index 9dfe20220..a5da84cce 100644 --- a/apps/www/app/[locale]/(app)/(static)/(site)/ask/[slug]/page.tsx +++ b/apps/www/app/[locale]/(app)/(static)/(site)/ask/[slug]/page.tsx @@ -58,8 +58,6 @@ export default function Page(props: PageProps<"/[locale]/ask/[slug]">) { const { locale: rawLocale, slug } = use(params); const locale = getLocaleOrThrow(rawLocale); - // Enable static rendering - const seoData = askData.find((data) => data.slug === slug); const title = seoData?.locales[locale].title ?? convertSlugToTitle(slug); @@ -80,7 +78,7 @@ export default function Page(props: PageProps<"/[locale]/ask/[slug]">) { ]} url={`https://nakafa.com/${locale}/ask/${slug}`} /> -
+
diff --git a/apps/www/app/[locale]/(app)/(static)/(site)/home/page.tsx b/apps/www/app/[locale]/(app)/(static)/(site)/home/page.tsx index a4fac3536..e59c0e260 100644 --- a/apps/www/app/[locale]/(app)/(static)/(site)/home/page.tsx +++ b/apps/www/app/[locale]/(app)/(static)/(site)/home/page.tsx @@ -7,8 +7,6 @@ export default function Page(props: PageProps<"/[locale]/home">) { const { params } = props; const locale = getLocaleOrThrow(use(params).locale); - // Enable static rendering - // This is empty page, redirect to home page redirect({ href: "/about", locale }); } diff --git a/apps/www/app/[locale]/(app)/error.tsx b/apps/www/app/[locale]/(app)/error.tsx index 056120ad0..545c58fd1 100644 --- a/apps/www/app/[locale]/(app)/error.tsx +++ b/apps/www/app/[locale]/(app)/error.tsx @@ -22,10 +22,7 @@ export default function ErrorPage({ }, [error]); return ( -
+
diff --git a/apps/www/app/[locale]/(app)/not-found.tsx b/apps/www/app/[locale]/(app)/not-found.tsx index b2e49b2e0..3ae80da73 100644 --- a/apps/www/app/[locale]/(app)/not-found.tsx +++ b/apps/www/app/[locale]/(app)/not-found.tsx @@ -9,10 +9,7 @@ export default async function NotFound() { const t = await getTranslations("NotFound"); return ( -
+
diff --git a/apps/www/app/global-error.tsx b/apps/www/app/global-error.tsx index bf7c16dad..a7595a377 100644 --- a/apps/www/app/global-error.tsx +++ b/apps/www/app/global-error.tsx @@ -28,10 +28,7 @@ export default function GlobalError({
-
+
diff --git a/apps/www/app/global-not-found.tsx b/apps/www/app/global-not-found.tsx index 962820de9..c34af917f 100644 --- a/apps/www/app/global-not-found.tsx +++ b/apps/www/app/global-not-found.tsx @@ -24,10 +24,7 @@ export default function GlobalNotFound() { disableTransitionOnChange enableSystem > -
+
diff --git a/apps/www/components/ai/chat-sidebar.tsx b/apps/www/components/ai/chat-sidebar.tsx index 916539ec5..5660bc35f 100644 --- a/apps/www/components/ai/chat-sidebar.tsx +++ b/apps/www/components/ai/chat-sidebar.tsx @@ -38,7 +38,7 @@ type Props = ComponentProps; export function AiChatSidebar({ ...props }: Props) { return ( -
+
+
{t("title")} diff --git a/apps/www/components/shared/footer-content.tsx b/apps/www/components/shared/footer-content.tsx index 5a85003f7..fe3f2dc69 100644 --- a/apps/www/components/shared/footer-content.tsx +++ b/apps/www/components/shared/footer-content.tsx @@ -13,7 +13,7 @@ export function FooterContent({ childrenClassName, }: Props) { return ( -