diff --git a/app/(app)/layout.tsx b/app/(app)/layout.tsx
index 9271c4c..424f323 100644
--- a/app/(app)/layout.tsx
+++ b/app/(app)/layout.tsx
@@ -8,6 +8,8 @@ import { MinWidthBanner } from '@/components/shared/min-width-banner'
import { StatusBar } from '@/components/shared/status-bar'
import { SoloRealtimeBridge } from '@/components/solo/realtime-bridge'
import { NotificationsBridge } from '@/components/notifications/notifications-bridge'
+import { UserSettingsBridge } from '@/components/shared/user-settings-bridge'
+import { parseUserSettings } from '@/lib/user-settings'
import { AlertToast } from '@/components/shared/alert-toast'
import { Suspense } from 'react'
@@ -17,7 +19,7 @@ export default async function AppLayout({ children }: { children: React.ReactNod
const [user, userRoles, accessibleProducts] = await Promise.all([
prisma.user.findUnique({
where: { id: session.userId },
- select: { username: true, email: true, active_product_id: true, min_quota_pct: true },
+ select: { username: true, email: true, active_product_id: true, min_quota_pct: true, settings: true },
}),
prisma.userRole.findMany({
where: { user_id: session.userId },
@@ -79,6 +81,10 @@ export default async function AppLayout({ children }: { children: React.ReactNod
+
diff --git a/components/shared/user-settings-bridge.tsx b/components/shared/user-settings-bridge.tsx
new file mode 100644
index 0000000..6a8740e
--- /dev/null
+++ b/components/shared/user-settings-bridge.tsx
@@ -0,0 +1,41 @@
+'use client'
+
+import { useEffect } from 'react'
+import { useUserSettingsStore } from '@/stores/user-settings/store'
+import type { UserSettings } from '@/lib/user-settings'
+
+interface Props {
+ initial: UserSettings
+ isDemo: boolean
+}
+
+/**
+ * PBI-76: hydrates the user-settings Zustand store with server-rendered prefs
+ * and opens an SSE subscription so other tabs/devices of the same user
+ * immediately see changes. Demo accounts skip the SSE subscription — their
+ * settings live only in-memory.
+ */
+export function UserSettingsBridge({ initial, isDemo }: Props) {
+ const hydrate = useUserSettingsStore((s) => s.hydrate)
+ const applyServerPatch = useUserSettingsStore((s) => s.applyServerPatch)
+
+ useEffect(() => {
+ hydrate(initial, isDemo)
+ }, [hydrate, initial, isDemo])
+
+ useEffect(() => {
+ if (isDemo) return
+ const es = new EventSource('/api/realtime/user-settings')
+ es.onmessage = (e) => {
+ try {
+ const patch = JSON.parse(e.data) as Partial
+ applyServerPatch(patch)
+ } catch {
+ // ignore malformed event
+ }
+ }
+ return () => es.close()
+ }, [applyServerPatch, isDemo])
+
+ return null
+}