diff --git a/next.config.ts b/next.config.ts
index 1d0afeba7c..517c438532 100644
--- a/next.config.ts
+++ b/next.config.ts
@@ -42,6 +42,7 @@ const nextConfig: NextConfig = {
devIndicators: false,
experimental: {
cpus: 1,
+ optimizePackageImports: ["lucide-react"],
},
poweredByHeader: false,
turbopack: {
diff --git a/src/app/documents/[id]/loading.tsx b/src/app/documents/[id]/loading.tsx
new file mode 100644
index 0000000000..81ca711676
--- /dev/null
+++ b/src/app/documents/[id]/loading.tsx
@@ -0,0 +1,7 @@
+export default function Loading() {
+ return (
+
+ );
+}
diff --git a/src/app/documents/[id]/page.tsx b/src/app/documents/[id]/page.tsx
index 0950bc1fb1..17f79250aa 100644
--- a/src/app/documents/[id]/page.tsx
+++ b/src/app/documents/[id]/page.tsx
@@ -1,4 +1,4 @@
-import { DocumentViewer } from "@/components/DocumentViewer";
+import { DocumentViewerLazy as DocumentViewer } from "@/components/document-viewer-lazy";
export default async function DocumentPage({
params,
diff --git a/src/app/loading.tsx b/src/app/loading.tsx
new file mode 100644
index 0000000000..81ca711676
--- /dev/null
+++ b/src/app/loading.tsx
@@ -0,0 +1,7 @@
+export default function Loading() {
+ return (
+
+ );
+}
diff --git a/src/app/page.tsx b/src/app/page.tsx
index 40d4f1a758..e6d9b98a0e 100644
--- a/src/app/page.tsx
+++ b/src/app/page.tsx
@@ -1,4 +1,4 @@
-import { ClinicalDashboard } from "@/components/clinical-dashboard";
+import { ClinicalDashboardLazy as ClinicalDashboard } from "@/components/clinical-dashboard-lazy";
import { isAppModeId, isAppModeVisible, type AppModeId } from "@/lib/app-modes";
type HomeProps = {
diff --git a/src/components/ClinicalDashboard.tsx b/src/components/ClinicalDashboard.tsx
index 45a17cf9df..e366a8467a 100644
--- a/src/components/ClinicalDashboard.tsx
+++ b/src/components/ClinicalDashboard.tsx
@@ -53,6 +53,7 @@ import {
import {
type CSSProperties,
FormEvent,
+ memo,
useCallback,
useEffect,
useMemo,
@@ -509,7 +510,7 @@ function subscribeAuthEmail(onStoreChange: () => void) {
};
}
-function SourceImage({
+const SourceImage = memo(function SourceImage({
endpoint,
caption,
className = "max-h-52",
@@ -609,7 +610,7 @@ function SourceImage({
className={cn(className, "w-full rounded-lg object-contain")}
/>
);
-}
+});
function ScopeAndGovernanceNotice({
scope,
diff --git a/src/components/clinical-dashboard-lazy.tsx b/src/components/clinical-dashboard-lazy.tsx
new file mode 100644
index 0000000000..70bd7aafc0
--- /dev/null
+++ b/src/components/clinical-dashboard-lazy.tsx
@@ -0,0 +1,11 @@
+"use client";
+
+import dynamic from "next/dynamic";
+
+// `ssr: false` requires a Client Component in the App Router; this wrapper
+// keeps the heavy dashboard bundle browser-only for the server-rendered
+// home page.
+export const ClinicalDashboardLazy = dynamic(
+ () => import("@/components/clinical-dashboard").then((m) => m.ClinicalDashboard),
+ { ssr: false },
+);
diff --git a/src/components/document-viewer-lazy.tsx b/src/components/document-viewer-lazy.tsx
new file mode 100644
index 0000000000..f910a6c2b7
--- /dev/null
+++ b/src/components/document-viewer-lazy.tsx
@@ -0,0 +1,10 @@
+"use client";
+
+import dynamic from "next/dynamic";
+
+// `ssr: false` requires a Client Component in the App Router; this wrapper
+// keeps the viewer bundle browser-only for the server-rendered document page.
+export const DocumentViewerLazy = dynamic(
+ () => import("@/components/DocumentViewer").then((m) => m.DocumentViewer),
+ { ssr: false },
+);