From 01ae8b558dee4bb08575604b9e88044cf4354bec Mon Sep 17 00:00:00 2001
From: MohamedBassem <me@mbassem.com>
Date: Mon, 4 Aug 2025 00:07:50 -0700
Subject: feat: Add an error boundary around the custom renderer

---
 .../dashboard/preview/LinkContentSection.tsx       | 37 ++++++++++++++++++++--
 1 file changed, 35 insertions(+), 2 deletions(-)

(limited to 'apps/web/components/dashboard/preview/LinkContentSection.tsx')

diff --git a/apps/web/components/dashboard/preview/LinkContentSection.tsx b/apps/web/components/dashboard/preview/LinkContentSection.tsx
index 3855cb2a..67de4e75 100644
--- a/apps/web/components/dashboard/preview/LinkContentSection.tsx
+++ b/apps/web/components/dashboard/preview/LinkContentSection.tsx
@@ -1,6 +1,7 @@
 import { useState } from "react";
 import Image from "next/image";
 import Link from "next/link";
+import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
 import { buttonVariants } from "@/components/ui/button";
 import { ScrollArea } from "@/components/ui/scroll-area";
 import {
@@ -17,7 +18,15 @@ import {
   TooltipTrigger,
 } from "@/components/ui/tooltip";
 import { useTranslation } from "@/lib/i18n/client";
-import { Archive, BookOpen, Camera, ExpandIcon, Video } from "lucide-react";
+import {
+  AlertTriangle,
+  Archive,
+  BookOpen,
+  Camera,
+  ExpandIcon,
+  Video,
+} from "lucide-react";
+import { ErrorBoundary } from "react-error-boundary";
 
 import {
   BookmarkTypes,
@@ -28,6 +37,26 @@ import {
 import { contentRendererRegistry } from "./content-renderers";
 import ReaderView from "./ReaderView";
 
+function CustomRendererErrorFallback({ error }: { error: Error }) {
+  return (
+    <div className="flex h-full w-full items-center justify-center p-4">
+      <Alert variant="destructive" className="max-w-md">
+        <AlertTriangle className="h-4 w-4" />
+        <AlertTitle>Renderer Error</AlertTitle>
+        <AlertDescription>
+          Failed to load custom content renderer.{" "}
+          <details className="mt-2">
+            <summary className="cursor-pointer text-xs">
+              Technical details
+            </summary>
+            <code className="mt-1 block text-xs">{error.message}</code>
+          </details>
+        </AlertDescription>
+      </Alert>
+    </div>
+  );
+}
+
 function FullPageArchiveSection({ link }: { link: ZBookmarkedLink }) {
   const archiveAssetId =
     link.fullPageArchiveAssetId ?? link.precrawledArchiveAssetId;
@@ -90,7 +119,11 @@ export default function LinkContentSection({
   const customRenderer = availableRenderers.find((r) => r.id === section);
   if (customRenderer) {
     const RendererComponent = customRenderer.component;
-    content = <RendererComponent bookmark={bookmark} />;
+    content = (
+      <ErrorBoundary FallbackComponent={CustomRendererErrorFallback}>
+        <RendererComponent bookmark={bookmark} />
+      </ErrorBoundary>
+    );
   } else if (section === "cached") {
     content = (
       <ScrollArea className="h-full">
-- 
cgit v1.2.3-70-g09d2

