diff --git a/webclient-vue/src/app/App.vue b/webclient-vue/src/app/App.vue
index 18da5ed..798c710 100644
--- a/webclient-vue/src/app/App.vue
+++ b/webclient-vue/src/app/App.vue
@@ -1,10 +1,13 @@
-
+
+
+
diff --git a/webclient-vue/src/app/main.js b/webclient-vue/src/app/main.js
index e9359f1..17f597f 100644
--- a/webclient-vue/src/app/main.js
+++ b/webclient-vue/src/app/main.js
@@ -2,11 +2,13 @@
import { createPinia } from "pinia";
import App from "./App.vue";
import { router } from "../router";
+import { useGlobalErrorHandler } from "../composables/useGlobalErrorHandler";
import "@phosphor-icons/web/regular";
import "@phosphor-icons/web/fill";
import "../styles/main.css";
-createApp(App)
- .use(createPinia())
- .use(router)
- .mount("#app");
+const app = createApp(App);
+
+useGlobalErrorHandler(app);
+
+app.use(createPinia()).use(router).mount("#app");
diff --git a/webclient-vue/src/components/feedback/AppErrorBoundary.vue b/webclient-vue/src/components/feedback/AppErrorBoundary.vue
new file mode 100644
index 0000000..d2397f8
--- /dev/null
+++ b/webclient-vue/src/components/feedback/AppErrorBoundary.vue
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
diff --git a/webclient-vue/src/composables/useGlobalErrorHandler.js b/webclient-vue/src/composables/useGlobalErrorHandler.js
new file mode 100644
index 0000000..94a2dd4
--- /dev/null
+++ b/webclient-vue/src/composables/useGlobalErrorHandler.js
@@ -0,0 +1,44 @@
+/**
+ * Composable that wires up global error-catching surfaces.
+ * Should be called once during app bootstrap (main.js).
+ */
+export function useGlobalErrorHandler(app) {
+ /**
+ * 1. Vue runtime errors — render, watcher, lifecycle hooks, event handlers.
+ * This does NOT catch errors inside async functions (those are promises).
+ */
+ app.config.errorHandler = (err, instance, info) => {
+ const message = err?.message || String(err);
+ console.error(`[Vue errorHandler] ${info}`, message, err);
+ // In Phase 3 this is where we would push to a toast/notification service.
+ };
+
+ /**
+ * 2. Unhandled promise rejections (fetch without catch, async function
+ * that throws and is not awaited, etc.)
+ */
+ window.addEventListener("unhandledrejection", (event) => {
+ const reason = event.reason;
+ const message = reason?.message || reason?.error?.message || String(reason);
+ console.error("[Unhandled rejection]", message, reason);
+ // Prevent the default browser console noise (redundant with our log).
+ event.preventDefault();
+ });
+
+ /**
+ * 3. Global synchronous JS errors (script parse errors, runtime throws
+ * outside of Vue, etc.)
+ */
+ window.addEventListener("error", (event) => {
+ const error = event.error;
+ const message = error?.message || event.message || "Unknown error";
+ console.error(
+ `[Global error] ${message}`,
+ "at",
+ event.filename,
+ event.lineno,
+ event.colno,
+ error
+ );
+ });
+}