diff --git a/apps/web/src/lib/utils/url.ts b/apps/web/src/lib/utils/url.ts
new file mode 100644
index 0000000..975fa84
--- /dev/null
+++ b/apps/web/src/lib/utils/url.ts
@@ -0,0 +1,15 @@
+const API_BASE_URL = import.meta.env.VITE_API_BASE_URL ?? 'http://localhost:3000';
+
+export function resolveAssetUrl(url: string | null | undefined): string {
+ if (!url) return '';
+ if (url.startsWith('http://') || url.startsWith('https://') || url.startsWith('blob:') || url.startsWith('data:')) {
+ return url;
+ }
+ // If it starts with /assets/, prepend API_BASE_URL
+ if (url.startsWith('/assets/')) {
+ // Check if it's already a full URL (though startsWith /assets/ implies relative)
+ return `${API_BASE_URL}${url}`;
+ }
+ // Otherwise, return as is (could be a legacy relative path or something else)
+ return url;
+}
diff --git a/apps/web/src/routes/+layout.svelte b/apps/web/src/routes/+layout.svelte
index 10c6ee1..1102ac7 100644
--- a/apps/web/src/routes/+layout.svelte
+++ b/apps/web/src/routes/+layout.svelte
@@ -3,6 +3,7 @@
import { token, user } from "$lib/stores/auth";
import { organization, loadOrganization } from "$lib/stores/organization";
import { onMount } from "svelte";
+ import { resolveAssetUrl } from "$lib/utils/url";
onMount(async () => {
if ($user?.organizationId) {
@@ -19,7 +20,7 @@