diff --git a/website/src/components/ui/FadeIn.tsx b/website/src/components/ui/FadeIn.tsx
index d3ccdd31..ce1b4096 100644
--- a/website/src/components/ui/FadeIn.tsx
+++ b/website/src/components/ui/FadeIn.tsx
@@ -1,9 +1,24 @@
'use client';
import { motion, useReducedMotion } from 'framer-motion';
-import { ReactNode } from 'react';
+import { ReactNode, useState, useEffect, memo } from 'react';
-export function FadeIn({ children, delay = 0, className = '' }: { children: ReactNode; delay?: number; className?: string }) {
+export const FadeIn = memo(function FadeIn({ children, delay = 0, className = '' }: { children: ReactNode; delay?: number; className?: string }) {
const shouldReduce = useReducedMotion();
+ const [isMounted, setIsMounted] = useState(false);
+
+ // Defer Framer Motion's initial state until after hydration. Without this,
+ // Framer Motion applies initial={{ opacity: 0 }} before React hydrates, causing
+ // the server-rendered HTML (opacity:1) to mismatch the client DOM (opacity:0).
+ useEffect(() => {
+ setIsMounted(true);
+ }, []);
+
+ if (!isMounted) {
+ // Server + hydration pass: render without Framer Motion so the DOM matches
+ // the server HTML exactly. No opacity/transform styles applied.
+ return
{children}
;
+ }
+
return (
);
-}
+});
diff --git a/website/src/instrumentation-client.ts b/website/src/instrumentation-client.ts
index 4fe3437b..1a27bbab 100644
--- a/website/src/instrumentation-client.ts
+++ b/website/src/instrumentation-client.ts
@@ -12,6 +12,31 @@ Sentry.init({
integrations: [
Sentry.replayIntegration(),
],
+ beforeSend(event) {
+ const msg = event.exception?.values?.[0]?.value ?? "";
+
+ // Drop known browser-extension noise that cannot be fixed in app code:
+ //
+ // 1. "Cannot assign to read only property 'pushState'" — extensions
+ // (Vue/Redux DevTools, privacy tools) wrap history.pushState before our
+ // app loads, making it read-only. Not reproducible without the extension.
+ //
+ // 2. "Object Not Found Matching Id:N, MethodName:update" — Chrome DevTools
+ // Protocol messages from extensions interacting with CodeMirror/Monaco.
+ // The error originates outside our code and only affects a single session.
+ const isExtensionNoise =
+ msg.includes("Cannot assign to read only property 'pushState'") ||
+ msg.includes("Object Not Found Matching Id:");
+
+ if (isExtensionNoise) {
+ if (process.env.NODE_ENV === "development") {
+ console.debug("[Sentry] Suppressed extension noise:", msg);
+ }
+ return null;
+ }
+
+ return event;
+ },
});
export const onRouterTransitionStart = dsn