From 742e272ade620c024d9a105bad3ba9c81c8780da Mon Sep 17 00:00:00 2001 From: ZeroPointSix <229769386+ZeroPointSix@users.noreply.github.com> Date: Sun, 22 Mar 2026 18:12:49 +0800 Subject: [PATCH 1/4] fix: show error details in preview environments --- apps/site/app/[locale]/error.tsx | 25 +++++++++++++- apps/site/next.constants.mjs | 7 ++++ apps/site/tests/errorPage.test.jsx | 53 ++++++++++++++++++++++++++++++ 3 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 apps/site/tests/errorPage.test.jsx diff --git a/apps/site/app/[locale]/error.tsx b/apps/site/app/[locale]/error.tsx index 0c4bf7f827ec8..12a77c2af1be6 100644 --- a/apps/site/app/[locale]/error.tsx +++ b/apps/site/app/[locale]/error.tsx @@ -4,11 +4,22 @@ import { useTranslations } from 'next-intl'; import Button from '#site/components/Common/Button'; import GlowingBackdropLayout from '#site/layouts/GlowingBackdrop'; +import { SHOW_ERROR_DETAILS } from '#site/next.constants.mjs'; import type { FC } from 'react'; -const ErrorPage: FC<{ error: Error }> = () => { +type ErrorPageProps = { + error: Error & { digest?: string }; +}; + +const ErrorPage: FC = ({ error }) => { const t = useTranslations(); + const errorDetails = [ + error.message, + error.digest && `digest: ${error.digest}`, + ] + .filter(Boolean) + .join('\n'); return ( @@ -22,6 +33,18 @@ const ErrorPage: FC<{ error: Error }> = () => { {t('layouts.error.internalServerError.description')}

+ {SHOW_ERROR_DETAILS && errorDetails && ( +
+ + {t('components.downloadReleasesTable.details')} + + +
+            {errorDetails}
+          
+
+ )} +
); diff --git a/apps/site/next.constants.mjs b/apps/site/next.constants.mjs index c90c61711b7c6..cf9b0c3ad5207 100644 --- a/apps/site/next.constants.mjs +++ b/apps/site/next.constants.mjs @@ -14,6 +14,13 @@ export const IS_DEV_ENV = process.env.NODE_ENV === 'development'; */ export const VERCEL_ENV = process.env.VERCEL_ENV || undefined; +/** + * Error details should only be exposed in local development or Vercel preview + * deployments, never in production. + */ +export const SHOW_ERROR_DETAILS = + process.env.NODE_ENV === 'development' || VERCEL_ENV === 'preview'; + /** * This is used for telling Next.js to do a Static Export Build of the Website * diff --git a/apps/site/tests/errorPage.test.jsx b/apps/site/tests/errorPage.test.jsx new file mode 100644 index 0000000000000..035bc4e72f81a --- /dev/null +++ b/apps/site/tests/errorPage.test.jsx @@ -0,0 +1,53 @@ +import assert from 'node:assert/strict'; +import { describe, it } from 'node:test'; + +import { render, screen } from '@testing-library/react'; + +describe('ErrorPage', () => { + it('renders technical details in preview environments', async t => { + t.mock.module('#site/components/Common/Button', { + defaultExport: ({ children, href }) => {children}, + }); + + t.mock.module('#site/layouts/GlowingBackdrop', { + defaultExport: ({ children }) =>
{children}
, + }); + + t.mock.module('#site/next.constants.mjs', { + namedExports: { + SHOW_ERROR_DETAILS: true, + }, + }); + + const { default: ErrorPage } = await import('../app/[locale]/error.tsx'); + + render( + + ); + + assert.equal( + screen.getByRole('heading').textContent, + 'layouts.error.internalServerError.title' + ); + assert.equal( + screen.getByRole('link').textContent, + 'layouts.error.backToHome' + ); + assert.equal( + screen.getByText('components.downloadReleasesTable.details').textContent, + 'components.downloadReleasesTable.details' + ); + assert.match( + screen.getByText(/Preview deployment failed/).textContent, + /Preview deployment failed/ + ); + assert.match( + screen.getByText(/digest: abc123/i).textContent, + /digest: abc123/i + ); + }); +}); From f6f38e46eb16bcb7be998a16b19af471eea27a0b Mon Sep 17 00:00:00 2001 From: ZeroPointSix <229769386+ZeroPointSix@users.noreply.github.com> Date: Sun, 22 Mar 2026 19:16:25 +0800 Subject: [PATCH 2/4] fix: expose preview error details to clients --- apps/site/app/[locale]/error.tsx | 2 +- apps/site/next.config.mjs | 4 ++++ apps/site/next.constants.mjs | 9 ++++++-- apps/site/tests/errorPage.test.jsx | 34 ++++++++++++++++++++++++---- packages/i18n/src/locales/en.json | 1 + packages/i18n/src/locales/es.json | 1 + packages/i18n/src/locales/fr.json | 1 + packages/i18n/src/locales/id.json | 1 + packages/i18n/src/locales/ja.json | 1 + packages/i18n/src/locales/ko.json | 1 + packages/i18n/src/locales/pt-br.json | 1 + packages/i18n/src/locales/pt.json | 1 + packages/i18n/src/locales/ro.json | 1 + packages/i18n/src/locales/ta.json | 1 + packages/i18n/src/locales/tr.json | 1 + packages/i18n/src/locales/uk.json | 1 + packages/i18n/src/locales/zh-cn.json | 1 + packages/i18n/src/locales/zh-tw.json | 1 + 18 files changed, 55 insertions(+), 8 deletions(-) diff --git a/apps/site/app/[locale]/error.tsx b/apps/site/app/[locale]/error.tsx index 12a77c2af1be6..ce729f094e0cc 100644 --- a/apps/site/app/[locale]/error.tsx +++ b/apps/site/app/[locale]/error.tsx @@ -36,7 +36,7 @@ const ErrorPage: FC = ({ error }) => { {SHOW_ERROR_DETAILS && errorDetails && (
- {t('components.downloadReleasesTable.details')} + {t('layouts.error.details')}
diff --git a/apps/site/next.config.mjs b/apps/site/next.config.mjs
index 40d1f89e87cd3..30447adaa239e 100644
--- a/apps/site/next.config.mjs
+++ b/apps/site/next.config.mjs
@@ -29,6 +29,10 @@ const nextConfig = {
   basePath: BASE_PATH,
   // Vercel/Next.js Image Optimization Settings
   images: getImagesConfig(),
+  env: {
+    NEXT_PUBLIC_VERCEL_ENV:
+      process.env.NEXT_PUBLIC_VERCEL_ENV || process.env.VERCEL_ENV,
+  },
   serverExternalPackages: ['twoslash'],
   outputFileTracingIncludes: {
     // Twoslash needs TypeScript declarations to function, and, by default, Next.js
diff --git a/apps/site/next.constants.mjs b/apps/site/next.constants.mjs
index cf9b0c3ad5207..b960c103fdb00 100644
--- a/apps/site/next.constants.mjs
+++ b/apps/site/next.constants.mjs
@@ -14,12 +14,17 @@ export const IS_DEV_ENV = process.env.NODE_ENV === 'development';
  */
 export const VERCEL_ENV = process.env.VERCEL_ENV || undefined;
 
+/**
+ * Public-facing Vercel environment, safe to use in client-side code.
+ */
+export const PUBLIC_VERCEL_ENV =
+  process.env.NEXT_PUBLIC_VERCEL_ENV || VERCEL_ENV;
+
 /**
  * Error details should only be exposed in local development or Vercel preview
  * deployments, never in production.
  */
-export const SHOW_ERROR_DETAILS =
-  process.env.NODE_ENV === 'development' || VERCEL_ENV === 'preview';
+export const SHOW_ERROR_DETAILS = IS_DEV_ENV || PUBLIC_VERCEL_ENV === 'preview';
 
 /**
  * This is used for telling Next.js to do a Static Export Build of the Website
diff --git a/apps/site/tests/errorPage.test.jsx b/apps/site/tests/errorPage.test.jsx
index 035bc4e72f81a..6fd30ef5b0676 100644
--- a/apps/site/tests/errorPage.test.jsx
+++ b/apps/site/tests/errorPage.test.jsx
@@ -4,7 +4,7 @@ import { describe, it } from 'node:test';
 import { render, screen } from '@testing-library/react';
 
 describe('ErrorPage', () => {
-  it('renders technical details in preview environments', async t => {
+  const setupErrorPage = async (t, showErrorDetails, suffix = '') => {
     t.mock.module('#site/components/Common/Button', {
       defaultExport: ({ children, href }) => {children},
     });
@@ -15,11 +15,15 @@ describe('ErrorPage', () => {
 
     t.mock.module('#site/next.constants.mjs', {
       namedExports: {
-        SHOW_ERROR_DETAILS: true,
+        SHOW_ERROR_DETAILS: showErrorDetails,
       },
     });
 
-    const { default: ErrorPage } = await import('../app/[locale]/error.tsx');
+    return import(`../app/[locale]/error.tsx${suffix}`);
+  };
+
+  it('renders technical details in preview environments', async t => {
+    const { default: ErrorPage } = await setupErrorPage(t, true);
 
     render(
        {
       'layouts.error.backToHome'
     );
     assert.equal(
-      screen.getByText('components.downloadReleasesTable.details').textContent,
-      'components.downloadReleasesTable.details'
+      screen.getByText('layouts.error.details').textContent,
+      'layouts.error.details'
     );
     assert.match(
       screen.getByText(/Preview deployment failed/).textContent,
@@ -50,4 +54,24 @@ describe('ErrorPage', () => {
       /digest: abc123/i
     );
   });
+
+  it('hides technical details when the flag is disabled', async t => {
+    const { default: ErrorPage } = await setupErrorPage(
+      t,
+      false,
+      '?show-error-details-disabled'
+    );
+
+    render(
+      
+    );
+
+    assert.equal(screen.queryByText('layouts.error.details'), null);
+    assert.equal(screen.queryByText(/Production should stay generic/), null);
+    assert.equal(screen.queryByText(/digest: hidden123/i), null);
+  });
 });
diff --git a/packages/i18n/src/locales/en.json b/packages/i18n/src/locales/en.json
index a794c5f164efc..a267da0a71a79 100644
--- a/packages/i18n/src/locales/en.json
+++ b/packages/i18n/src/locales/en.json
@@ -370,6 +370,7 @@
         "title": "Internal Server Error",
         "description": "This page has thrown a non-recoverable error."
       },
+      "details": "Details",
       "backToHome": "Back to Home"
     },
     "download": {
diff --git a/packages/i18n/src/locales/es.json b/packages/i18n/src/locales/es.json
index dd15732fcecb6..0e682fd41276c 100644
--- a/packages/i18n/src/locales/es.json
+++ b/packages/i18n/src/locales/es.json
@@ -275,6 +275,7 @@
         "title": "Error interno del servidor",
         "description": "Esta página ha generado un error no recuperable."
       },
+      "details": "Detalles",
       "backToHome": "Volver al inicio"
     },
     "download": {
diff --git a/packages/i18n/src/locales/fr.json b/packages/i18n/src/locales/fr.json
index 851616fe1f311..feb232f960240 100644
--- a/packages/i18n/src/locales/fr.json
+++ b/packages/i18n/src/locales/fr.json
@@ -370,6 +370,7 @@
         "title": "Erreur interne du serveur",
         "description": "Cette page a généré une erreur irrécupérable."
       },
+      "details": "Détails",
       "backToHome": "Retourner à l'accueil"
     },
     "download": {
diff --git a/packages/i18n/src/locales/id.json b/packages/i18n/src/locales/id.json
index e5ceffe8aa3a4..f5cce098415a4 100644
--- a/packages/i18n/src/locales/id.json
+++ b/packages/i18n/src/locales/id.json
@@ -360,6 +360,7 @@
         "title": "Kesalahan Server Internal",
         "description": "Halaman ini mengalami error yang tidak dapat diperbaiki."
       },
+      "details": "Rincian",
       "backToHome": "Kembali ke Beranda"
     },
     "download": {
diff --git a/packages/i18n/src/locales/ja.json b/packages/i18n/src/locales/ja.json
index 6e6080d50e266..d2dafc34014f9 100644
--- a/packages/i18n/src/locales/ja.json
+++ b/packages/i18n/src/locales/ja.json
@@ -370,6 +370,7 @@
         "title": "内部サーバーエラー",
         "description": "このページで回復不可能なエラーが発生しました。"
       },
+      "details": "詳細",
       "backToHome": "ホームに戻る"
     },
     "download": {
diff --git a/packages/i18n/src/locales/ko.json b/packages/i18n/src/locales/ko.json
index 591a7b1422647..810deee83d034 100644
--- a/packages/i18n/src/locales/ko.json
+++ b/packages/i18n/src/locales/ko.json
@@ -249,6 +249,7 @@
         "title": "Internal Server Error",
         "description": "이 페이지에서 복구할 수 없는 오류가 발생했습니다."
       },
+      "details": "세부정보",
       "backToHome": "홈으로 돌아가기"
     },
     "download": {
diff --git a/packages/i18n/src/locales/pt-br.json b/packages/i18n/src/locales/pt-br.json
index de37d98e132e7..643069c8779cc 100644
--- a/packages/i18n/src/locales/pt-br.json
+++ b/packages/i18n/src/locales/pt-br.json
@@ -366,6 +366,7 @@
         "title": "Erro Interno do Servidor",
         "description": "Esta página lançou um erro não recuperável."
       },
+      "details": "Detalhes",
       "backToHome": "Voltar para a Página Inicial"
     },
     "download": {
diff --git a/packages/i18n/src/locales/pt.json b/packages/i18n/src/locales/pt.json
index 643d8e2def5c1..cb5783e2f0c59 100644
--- a/packages/i18n/src/locales/pt.json
+++ b/packages/i18n/src/locales/pt.json
@@ -255,6 +255,7 @@
         "title": "Erro Interno do Servidor",
         "description": "Esta página registou um erro irrecuperável."
       },
+      "details": "Detalhes",
       "backToHome": "Voltar à Página Inicial"
     },
     "download": {
diff --git a/packages/i18n/src/locales/ro.json b/packages/i18n/src/locales/ro.json
index 199b01ccf0b2d..05598f3091d7f 100644
--- a/packages/i18n/src/locales/ro.json
+++ b/packages/i18n/src/locales/ro.json
@@ -347,6 +347,7 @@
         "title": "Eroare internă de server",
         "description": "Această pagină a generat o eroare nerecuperabilă."
       },
+      "details": "Detalii",
       "backToHome": "Înapoi la prima pagină"
     },
     "download": {
diff --git a/packages/i18n/src/locales/ta.json b/packages/i18n/src/locales/ta.json
index 2b146ce2628b8..55f9f0847f263 100644
--- a/packages/i18n/src/locales/ta.json
+++ b/packages/i18n/src/locales/ta.json
@@ -366,6 +366,7 @@
         "title": "உள் சேவையக பிழை",
         "description": "இந்தப் பக்கத்தில் சரிசெய்ய முடியாத பிழை ஏற்பட்டது."
       },
+      "details": "விவரங்கள்",
       "backToHome": "முகப்பிற்கு திரும்பவும்"
     },
     "download": {
diff --git a/packages/i18n/src/locales/tr.json b/packages/i18n/src/locales/tr.json
index 41d9c8ff64e9f..5f92c805f991f 100644
--- a/packages/i18n/src/locales/tr.json
+++ b/packages/i18n/src/locales/tr.json
@@ -277,6 +277,7 @@
         "title": "Dahili Sunucu Hatası",
         "description": "Bu sayfa kurtarılamaz bir hata verdi."
       },
+      "details": "Ayrıntılar",
       "backToHome": "Ana Sayfaya Geri Dön"
     },
     "download": {
diff --git a/packages/i18n/src/locales/uk.json b/packages/i18n/src/locales/uk.json
index 055b9a43e5267..f9915340c4cc7 100644
--- a/packages/i18n/src/locales/uk.json
+++ b/packages/i18n/src/locales/uk.json
@@ -370,6 +370,7 @@
         "title": "Внутрішня помилка сервера",
         "description": "На цій сторінці виникла невиправна помилка."
       },
+      "details": "Деталі",
       "backToHome": "До головної"
     },
     "download": {
diff --git a/packages/i18n/src/locales/zh-cn.json b/packages/i18n/src/locales/zh-cn.json
index 02818c1415e50..bf4ccd99fe411 100644
--- a/packages/i18n/src/locales/zh-cn.json
+++ b/packages/i18n/src/locales/zh-cn.json
@@ -256,6 +256,7 @@
         "title": "服务器内部错误",
         "description": "该页面出现了不可恢复的错误。"
       },
+      "details": "详细信息",
       "backToHome": "回到首页"
     },
     "download": {
diff --git a/packages/i18n/src/locales/zh-tw.json b/packages/i18n/src/locales/zh-tw.json
index db3e3fd60164e..8413c437ff8d9 100644
--- a/packages/i18n/src/locales/zh-tw.json
+++ b/packages/i18n/src/locales/zh-tw.json
@@ -281,6 +281,7 @@
         "title": "內部伺服器錯誤",
         "description": "此頁面發生了無法恢復的錯誤。"
       },
+      "details": "詳細資訊",
       "backToHome": "回到首頁"
     },
     "download": {

From ea812c7da13c8ac44d7877aae8a40e2225afcc61 Mon Sep 17 00:00:00 2001
From: ZeroPointSix <229769386+ZeroPointSix@users.noreply.github.com>
Date: Sun, 22 Mar 2026 19:26:49 +0800
Subject: [PATCH 3/4] fix: keep new error i18n key in english only

---
 packages/i18n/src/locales/es.json    | 1 -
 packages/i18n/src/locales/fr.json    | 1 -
 packages/i18n/src/locales/id.json    | 1 -
 packages/i18n/src/locales/ja.json    | 1 -
 packages/i18n/src/locales/ko.json    | 1 -
 packages/i18n/src/locales/pt-br.json | 1 -
 packages/i18n/src/locales/pt.json    | 1 -
 packages/i18n/src/locales/ro.json    | 1 -
 packages/i18n/src/locales/ta.json    | 1 -
 packages/i18n/src/locales/tr.json    | 1 -
 packages/i18n/src/locales/uk.json    | 1 -
 packages/i18n/src/locales/zh-cn.json | 1 -
 packages/i18n/src/locales/zh-tw.json | 1 -
 13 files changed, 13 deletions(-)

diff --git a/packages/i18n/src/locales/es.json b/packages/i18n/src/locales/es.json
index 0e682fd41276c..dd15732fcecb6 100644
--- a/packages/i18n/src/locales/es.json
+++ b/packages/i18n/src/locales/es.json
@@ -275,7 +275,6 @@
         "title": "Error interno del servidor",
         "description": "Esta página ha generado un error no recuperable."
       },
-      "details": "Detalles",
       "backToHome": "Volver al inicio"
     },
     "download": {
diff --git a/packages/i18n/src/locales/fr.json b/packages/i18n/src/locales/fr.json
index feb232f960240..851616fe1f311 100644
--- a/packages/i18n/src/locales/fr.json
+++ b/packages/i18n/src/locales/fr.json
@@ -370,7 +370,6 @@
         "title": "Erreur interne du serveur",
         "description": "Cette page a généré une erreur irrécupérable."
       },
-      "details": "Détails",
       "backToHome": "Retourner à l'accueil"
     },
     "download": {
diff --git a/packages/i18n/src/locales/id.json b/packages/i18n/src/locales/id.json
index f5cce098415a4..e5ceffe8aa3a4 100644
--- a/packages/i18n/src/locales/id.json
+++ b/packages/i18n/src/locales/id.json
@@ -360,7 +360,6 @@
         "title": "Kesalahan Server Internal",
         "description": "Halaman ini mengalami error yang tidak dapat diperbaiki."
       },
-      "details": "Rincian",
       "backToHome": "Kembali ke Beranda"
     },
     "download": {
diff --git a/packages/i18n/src/locales/ja.json b/packages/i18n/src/locales/ja.json
index d2dafc34014f9..6e6080d50e266 100644
--- a/packages/i18n/src/locales/ja.json
+++ b/packages/i18n/src/locales/ja.json
@@ -370,7 +370,6 @@
         "title": "内部サーバーエラー",
         "description": "このページで回復不可能なエラーが発生しました。"
       },
-      "details": "詳細",
       "backToHome": "ホームに戻る"
     },
     "download": {
diff --git a/packages/i18n/src/locales/ko.json b/packages/i18n/src/locales/ko.json
index 810deee83d034..591a7b1422647 100644
--- a/packages/i18n/src/locales/ko.json
+++ b/packages/i18n/src/locales/ko.json
@@ -249,7 +249,6 @@
         "title": "Internal Server Error",
         "description": "이 페이지에서 복구할 수 없는 오류가 발생했습니다."
       },
-      "details": "세부정보",
       "backToHome": "홈으로 돌아가기"
     },
     "download": {
diff --git a/packages/i18n/src/locales/pt-br.json b/packages/i18n/src/locales/pt-br.json
index 643069c8779cc..de37d98e132e7 100644
--- a/packages/i18n/src/locales/pt-br.json
+++ b/packages/i18n/src/locales/pt-br.json
@@ -366,7 +366,6 @@
         "title": "Erro Interno do Servidor",
         "description": "Esta página lançou um erro não recuperável."
       },
-      "details": "Detalhes",
       "backToHome": "Voltar para a Página Inicial"
     },
     "download": {
diff --git a/packages/i18n/src/locales/pt.json b/packages/i18n/src/locales/pt.json
index cb5783e2f0c59..643d8e2def5c1 100644
--- a/packages/i18n/src/locales/pt.json
+++ b/packages/i18n/src/locales/pt.json
@@ -255,7 +255,6 @@
         "title": "Erro Interno do Servidor",
         "description": "Esta página registou um erro irrecuperável."
       },
-      "details": "Detalhes",
       "backToHome": "Voltar à Página Inicial"
     },
     "download": {
diff --git a/packages/i18n/src/locales/ro.json b/packages/i18n/src/locales/ro.json
index 05598f3091d7f..199b01ccf0b2d 100644
--- a/packages/i18n/src/locales/ro.json
+++ b/packages/i18n/src/locales/ro.json
@@ -347,7 +347,6 @@
         "title": "Eroare internă de server",
         "description": "Această pagină a generat o eroare nerecuperabilă."
       },
-      "details": "Detalii",
       "backToHome": "Înapoi la prima pagină"
     },
     "download": {
diff --git a/packages/i18n/src/locales/ta.json b/packages/i18n/src/locales/ta.json
index 55f9f0847f263..2b146ce2628b8 100644
--- a/packages/i18n/src/locales/ta.json
+++ b/packages/i18n/src/locales/ta.json
@@ -366,7 +366,6 @@
         "title": "உள் சேவையக பிழை",
         "description": "இந்தப் பக்கத்தில் சரிசெய்ய முடியாத பிழை ஏற்பட்டது."
       },
-      "details": "விவரங்கள்",
       "backToHome": "முகப்பிற்கு திரும்பவும்"
     },
     "download": {
diff --git a/packages/i18n/src/locales/tr.json b/packages/i18n/src/locales/tr.json
index 5f92c805f991f..41d9c8ff64e9f 100644
--- a/packages/i18n/src/locales/tr.json
+++ b/packages/i18n/src/locales/tr.json
@@ -277,7 +277,6 @@
         "title": "Dahili Sunucu Hatası",
         "description": "Bu sayfa kurtarılamaz bir hata verdi."
       },
-      "details": "Ayrıntılar",
       "backToHome": "Ana Sayfaya Geri Dön"
     },
     "download": {
diff --git a/packages/i18n/src/locales/uk.json b/packages/i18n/src/locales/uk.json
index f9915340c4cc7..055b9a43e5267 100644
--- a/packages/i18n/src/locales/uk.json
+++ b/packages/i18n/src/locales/uk.json
@@ -370,7 +370,6 @@
         "title": "Внутрішня помилка сервера",
         "description": "На цій сторінці виникла невиправна помилка."
       },
-      "details": "Деталі",
       "backToHome": "До головної"
     },
     "download": {
diff --git a/packages/i18n/src/locales/zh-cn.json b/packages/i18n/src/locales/zh-cn.json
index bf4ccd99fe411..02818c1415e50 100644
--- a/packages/i18n/src/locales/zh-cn.json
+++ b/packages/i18n/src/locales/zh-cn.json
@@ -256,7 +256,6 @@
         "title": "服务器内部错误",
         "description": "该页面出现了不可恢复的错误。"
       },
-      "details": "详细信息",
       "backToHome": "回到首页"
     },
     "download": {
diff --git a/packages/i18n/src/locales/zh-tw.json b/packages/i18n/src/locales/zh-tw.json
index 8413c437ff8d9..db3e3fd60164e 100644
--- a/packages/i18n/src/locales/zh-tw.json
+++ b/packages/i18n/src/locales/zh-tw.json
@@ -281,7 +281,6 @@
         "title": "內部伺服器錯誤",
         "description": "此頁面發生了無法恢復的錯誤。"
       },
-      "details": "詳細資訊",
       "backToHome": "回到首頁"
     },
     "download": {

From 52cec4f0acbf23ae1efb7dee32a3f17ecb1f5020 Mon Sep 17 00:00:00 2001
From: ZeroPointSix <229769386+ZeroPointSix@users.noreply.github.com>
Date: Mon, 23 Mar 2026 10:28:43 +0800
Subject: [PATCH 4/4] fix(site): address error page review feedback

---
 apps/site/app/[locale]/error.tsx | 14 ++++++--------
 apps/site/next.config.mjs        |  4 ----
 2 files changed, 6 insertions(+), 12 deletions(-)

diff --git a/apps/site/app/[locale]/error.tsx b/apps/site/app/[locale]/error.tsx
index ce729f094e0cc..afeaeb7932b83 100644
--- a/apps/site/app/[locale]/error.tsx
+++ b/apps/site/app/[locale]/error.tsx
@@ -14,12 +14,7 @@ type ErrorPageProps = {
 
 const ErrorPage: FC = ({ error }) => {
   const t = useTranslations();
-  const errorDetails = [
-    error.message,
-    error.digest && `digest: ${error.digest}`,
-  ]
-    .filter(Boolean)
-    .join('\n');
+  const hasErrorDetails = Boolean(error.message || error.digest);
 
   return (
     
@@ -33,14 +28,17 @@ const ErrorPage: FC = ({ error }) => {
         {t('layouts.error.internalServerError.description')}
       

- {SHOW_ERROR_DETAILS && errorDetails && ( + {SHOW_ERROR_DETAILS && hasErrorDetails && (
{t('layouts.error.details')}
-            {errorDetails}
+            {error.message}
+            {error.digest
+              ? `${error.message ? '\n' : ''}digest: ${error.digest}`
+              : ''}
           
)} diff --git a/apps/site/next.config.mjs b/apps/site/next.config.mjs index 30447adaa239e..40d1f89e87cd3 100644 --- a/apps/site/next.config.mjs +++ b/apps/site/next.config.mjs @@ -29,10 +29,6 @@ const nextConfig = { basePath: BASE_PATH, // Vercel/Next.js Image Optimization Settings images: getImagesConfig(), - env: { - NEXT_PUBLIC_VERCEL_ENV: - process.env.NEXT_PUBLIC_VERCEL_ENV || process.env.VERCEL_ENV, - }, serverExternalPackages: ['twoslash'], outputFileTracingIncludes: { // Twoslash needs TypeScript declarations to function, and, by default, Next.js