diff --git a/apps/timo-web/components/boundary/AsyncBoundary.tsx b/apps/timo-web/components/boundary/AsyncBoundary.tsx
new file mode 100644
index 00000000..07eb3111
--- /dev/null
+++ b/apps/timo-web/components/boundary/AsyncBoundary.tsx
@@ -0,0 +1,26 @@
+import { Suspense, type ReactNode } from "react";
+
+import {
+ ErrorBoundary,
+ type ErrorFallbackTypes,
+} from "@/components/boundary/ErrorBoundary";
+
+interface AsyncBoundaryProps {
+ children: ReactNode;
+ pendingFallback?: ReactNode;
+ errorFallback?: ErrorFallbackTypes;
+}
+
+export const AsyncBoundary = ({
+ children,
+ pendingFallback = null,
+ errorFallback,
+}: AsyncBoundaryProps) => {
+ const content = {children};
+
+ if (!errorFallback) {
+ return content;
+ }
+
+ return {content};
+};
diff --git a/apps/timo-web/components/boundary/ErrorBoundary.tsx b/apps/timo-web/components/boundary/ErrorBoundary.tsx
new file mode 100644
index 00000000..edf80bd9
--- /dev/null
+++ b/apps/timo-web/components/boundary/ErrorBoundary.tsx
@@ -0,0 +1,56 @@
+"use client";
+
+import * as Sentry from "@sentry/nextjs";
+import { Component } from "react";
+
+import type { ErrorInfo, ReactNode } from "react";
+
+export type ErrorFallbackTypes =
+ | ReactNode
+ | ((error: Error, reset: () => void) => ReactNode);
+
+interface ErrorBoundaryProps {
+ children: ReactNode;
+ fallback: ErrorFallbackTypes;
+}
+
+interface ErrorBoundaryState {
+ error: Error | null;
+}
+
+const toError = (value: unknown): Error =>
+ value instanceof Error ? value : new Error(String(value));
+
+export class ErrorBoundary extends Component<
+ ErrorBoundaryProps,
+ ErrorBoundaryState
+> {
+ state: ErrorBoundaryState = { error: null };
+
+ static getDerivedStateFromError(error: unknown): ErrorBoundaryState {
+ return { error: toError(error) };
+ }
+
+ componentDidCatch(error: unknown, errorInfo: ErrorInfo): void {
+ Sentry.captureException(toError(error), {
+ contexts: { react: { componentStack: errorInfo.componentStack } },
+ });
+ }
+
+ reset = (): void => {
+ this.setState({ error: null });
+ };
+
+ render(): ReactNode {
+ const { error } = this.state;
+ const { children, fallback } = this.props;
+
+ if (error) {
+ return typeof fallback === "function"
+ ? fallback(error, this.reset)
+ : fallback;
+ }
+
+ return children;
+ }
+}