diff --git a/web/src/lib/components/layouts/user-page-layout.svelte b/web/src/lib/components/layouts/user-page-layout.svelte
index eb4f286d96..df12e59640 100644
--- a/web/src/lib/components/layouts/user-page-layout.svelte
+++ b/web/src/lib/components/layouts/user-page-layout.svelte
@@ -51,7 +51,7 @@
 </header>
 <main
   tabindex="-1"
-  class="relative grid h-screen grid-cols-[theme(spacing.0)_auto] overflow-hidden bg-immich-bg max-md:pt-[var(--navbar-height-md)] pt-[var(--navbar-height)] dark:bg-immich-dark-bg md:grid-cols-[theme(spacing.64)_auto]"
+  class="relative grid h-screen grid-cols-[theme(spacing.0)_auto] overflow-hidden bg-immich-bg max-md:pt-[var(--navbar-height-md)] pt-[var(--navbar-height)] dark:bg-immich-dark-bg sidebar:grid-cols-[theme(spacing.64)_auto]"
 >
   {#if sidebar}{@render sidebar()}{:else if admin}
     <AdminSideBar />
diff --git a/web/src/lib/components/shared-components/navigation-bar/navigation-bar.svelte b/web/src/lib/components/shared-components/navigation-bar/navigation-bar.svelte
index 161407fde4..a6a72e842d 100644
--- a/web/src/lib/components/shared-components/navigation-bar/navigation-bar.svelte
+++ b/web/src/lib/components/shared-components/navigation-bar/navigation-bar.svelte
@@ -23,7 +23,7 @@
   import ThemeButton from '../theme-button.svelte';
   import UserAvatar from '../user-avatar.svelte';
   import AccountInfoPanel from './account-info-panel.svelte';
-  import { isSidebarOpen } from '$lib/stores/side-bar.svelte';
+  import { sidebarStore } from '$lib/stores/sidebar.svelte';
   import { mobileDevice } from '$lib/stores/mobile-device.svelte';
 
   interface Props {
@@ -62,32 +62,30 @@
 >
   <SkipLink text={$t('skip_to_content')} />
   <div
-    class="grid h-full grid-cols-[theme(spacing.32)_auto] items-center border-b bg-immich-bg py-2 dark:border-b-immich-dark-gray dark:bg-immich-dark-bg md:grid-cols-[theme(spacing.64)_auto]"
+    class="grid h-full grid-cols-[theme(spacing.32)_auto] items-center border-b bg-immich-bg py-2 dark:border-b-immich-dark-gray dark:bg-immich-dark-bg sidebar:grid-cols-[theme(spacing.64)_auto]"
   >
     <div class="flex flex-row gap-1 mx-4 items-center">
-      <div>
-        <IconButton
-          id={menuButtonId}
-          shape="round"
-          color="secondary"
-          variant="ghost"
-          size="medium"
-          aria-label={$t('main_menu')}
-          icon={mdiMenu}
-          onclick={() => {
-            isSidebarOpen.value = !isSidebarOpen.value;
-          }}
-          onmousedown={(event: MouseEvent) => {
-            if (isSidebarOpen.value) {
-              // stops event from reaching the default handler when clicking outside of the sidebar
-              event.stopPropagation();
-            }
-          }}
-          class="md:hidden"
-        />
-      </div>
+      <IconButton
+        id={menuButtonId}
+        shape="round"
+        color="secondary"
+        variant="ghost"
+        size="medium"
+        aria-label={$t('main_menu')}
+        icon={mdiMenu}
+        onclick={() => {
+          sidebarStore.toggle();
+        }}
+        onmousedown={(event: MouseEvent) => {
+          if (sidebarStore.isOpen) {
+            // stops event from reaching the default handler when clicking outside of the sidebar
+            event.stopPropagation();
+          }
+        }}
+        class="sidebar:hidden"
+      />
       <a data-sveltekit-preload-data="hover" href={AppRoute.PHOTOS}>
-        <ImmichLogo class="max-md:h-[48px] h-[50px]" noText={mobileDevice.maxMd} />
+        <ImmichLogo class="max-md:h-[48px] h-[50px]" noText={!mobileDevice.isFullSidebar} />
       </a>
     </div>
     <div class="flex justify-between gap-4 lg:gap-8 pr-6">
diff --git a/web/src/lib/components/shared-components/side-bar/purchase-info.svelte b/web/src/lib/components/shared-components/side-bar/purchase-info.svelte
index 47e46c59b5..67d3eaf523 100644
--- a/web/src/lib/components/shared-components/side-bar/purchase-info.svelte
+++ b/web/src/lib/components/shared-components/side-bar/purchase-info.svelte
@@ -110,7 +110,7 @@
         <div>
           <Icon
             path={mdiInformationOutline}
-            class="hidden md:flex text-immich-primary dark:text-immich-dark-primary font-medium"
+            class="hidden sidebar:flex text-immich-primary dark:text-immich-dark-primary font-medium"
             size="18"
           />
         </div>
@@ -123,7 +123,7 @@
   {#if showMessage}
     <dialog
       open
-      class="hidden md:block w-[500px] absolute bottom-[75px] left-[255px] bg-gray-50 dark:border-gray-800 border border-gray-200 dark:bg-immich-dark-gray dark:text-white text-black rounded-3xl z-10 shadow-2xl px-8 py-6"
+      class="hidden sidebar:block w-[500px] absolute bottom-[75px] left-[255px] bg-gray-50 dark:border-gray-800 border border-gray-200 dark:bg-immich-dark-gray dark:text-white text-black rounded-3xl z-10 shadow-2xl px-8 py-6"
       transition:fade={{ duration: 150 }}
       onmouseover={() => (hoverMessage = true)}
       onmouseleave={() => (hoverMessage = false)}
diff --git a/web/src/lib/components/shared-components/side-bar/side-bar-section.spec.ts b/web/src/lib/components/shared-components/side-bar/side-bar-section.spec.ts
new file mode 100644
index 0000000000..16c985ce35
--- /dev/null
+++ b/web/src/lib/components/shared-components/side-bar/side-bar-section.spec.ts
@@ -0,0 +1,80 @@
+import SideBarSection from '$lib/components/shared-components/side-bar/side-bar-section.svelte';
+import { sidebarStore } from '$lib/stores/sidebar.svelte';
+import { render, screen } from '@testing-library/svelte';
+import { vi } from 'vitest';
+
+const mocks = vi.hoisted(() => {
+  return {
+    mobileDevice: {
+      isFullSidebar: false,
+    },
+  };
+});
+
+vi.mock('$lib/stores/mobile-device.svelte', () => ({
+  mobileDevice: mocks.mobileDevice,
+}));
+
+vi.mock('$lib/stores/sidebar.svelte', () => ({
+  sidebarStore: {
+    isOpen: false,
+    reset: vi.fn(),
+  },
+}));
+
+describe('SideBarSection component', () => {
+  beforeEach(() => {
+    vi.resetAllMocks();
+    mocks.mobileDevice.isFullSidebar = false;
+    sidebarStore.isOpen = false;
+  });
+
+  it.each`
+    isFullSidebar | isSidebarOpen | expectedInert
+    ${false}      | ${false}      | ${true}
+    ${false}      | ${true}       | ${false}
+    ${true}       | ${false}      | ${false}
+    ${true}       | ${true}       | ${false}
+  `(
+    'inert is $expectedInert when isFullSidebar=$isFullSidebar and isSidebarOpen=$isSidebarOpen',
+    ({ isFullSidebar, isSidebarOpen, expectedInert }) => {
+      // setup
+      mocks.mobileDevice.isFullSidebar = isFullSidebar;
+      sidebarStore.isOpen = isSidebarOpen;
+
+      // when
+      render(SideBarSection);
+      const parent = screen.getByTestId('sidebar-parent');
+
+      // then
+      expect(parent.inert).toBe(expectedInert);
+    },
+  );
+
+  it('should set width when sidebar is expanded', () => {
+    // setup
+    mocks.mobileDevice.isFullSidebar = false;
+    sidebarStore.isOpen = true;
+
+    // when
+    render(SideBarSection);
+    const parent = screen.getByTestId('sidebar-parent');
+
+    // then
+    expect(parent.classList).toContain('sidebar:w-[16rem]'); // sets the initial width for page load
+    expect(parent.classList).toContain('w-[min(100vw,16rem)]');
+    expect(parent.classList).toContain('shadow-2xl');
+  });
+
+  it('should close the sidebar if it is open on initial render', () => {
+    // setup
+    mocks.mobileDevice.isFullSidebar = false;
+    sidebarStore.isOpen = true;
+
+    // when
+    render(SideBarSection);
+
+    // then
+    expect(sidebarStore.reset).toHaveBeenCalled();
+  });
+});
diff --git a/web/src/lib/components/shared-components/side-bar/side-bar-section.svelte b/web/src/lib/components/shared-components/side-bar/side-bar-section.svelte
index 4b22a16c9c..74eb7d266b 100644
--- a/web/src/lib/components/shared-components/side-bar/side-bar-section.svelte
+++ b/web/src/lib/components/shared-components/side-bar/side-bar-section.svelte
@@ -2,52 +2,45 @@
   import { clickOutside } from '$lib/actions/click-outside';
   import { focusTrap } from '$lib/actions/focus-trap';
   import { menuButtonId } from '$lib/components/shared-components/navigation-bar/navigation-bar.svelte';
-  import { isSidebarOpen } from '$lib/stores/side-bar.svelte';
-  import { type Snippet } from 'svelte';
+  import { mobileDevice } from '$lib/stores/mobile-device.svelte';
+  import { sidebarStore } from '$lib/stores/sidebar.svelte';
+  import { onMount, type Snippet } from 'svelte';
 
   interface Props {
     children?: Snippet;
   }
 
-  const mdBreakpoint = 768;
-
   let { children }: Props = $props();
 
-  let innerWidth: number = $state(0);
+  const isHidden = $derived(!sidebarStore.isOpen && !mobileDevice.isFullSidebar);
+  const isExpanded = $derived(sidebarStore.isOpen && !mobileDevice.isFullSidebar);
 
-  const closeSidebar = (width: number) => {
-    isSidebarOpen.value = width >= mdBreakpoint;
-  };
-
-  $effect(() => {
-    closeSidebar(innerWidth);
+  onMount(() => {
+    closeSidebar();
   });
 
-  const isHidden = $derived(!isSidebarOpen.value && innerWidth < mdBreakpoint);
-  const isExpanded = $derived(isSidebarOpen.value && innerWidth < mdBreakpoint);
-
-  const handleClickOutside = () => {
-    if (!isSidebarOpen.value) {
+  const closeSidebar = () => {
+    if (!isExpanded) {
       return;
     }
-    closeSidebar(innerWidth);
+    sidebarStore.reset();
     if (isHidden) {
       document.querySelector<HTMLButtonElement>(`#${menuButtonId}`)?.focus();
     }
   };
 </script>
 
-<svelte:window bind:innerWidth />
 <section
   id="sidebar"
   tabindex="-1"
-  class="immich-scrollbar relative z-10 w-0 md:w-[16rem] overflow-y-auto overflow-x-hidden bg-immich-bg pt-8 transition-all duration-200 dark:bg-immich-dark-bg"
+  class="immich-scrollbar relative z-10 w-0 sidebar:w-[16rem] overflow-y-auto overflow-x-hidden bg-immich-bg pt-8 transition-all duration-200 dark:bg-immich-dark-bg"
   class:shadow-2xl={isExpanded}
   class:dark:border-r-immich-dark-gray={isExpanded}
   class:border-r={isExpanded}
-  class:w-[min(100vw,16rem)]={isSidebarOpen.value}
+  class:w-[min(100vw,16rem)]={sidebarStore.isOpen}
+  data-testid="sidebar-parent"
   inert={isHidden}
-  use:clickOutside={{ onOutclick: handleClickOutside, onEscape: handleClickOutside }}
+  use:clickOutside={{ onOutclick: closeSidebar, onEscape: closeSidebar }}
   use:focusTrap={{ active: isExpanded }}
 >
   <div class="pr-6 flex flex-col gap-1 h-max min-h-full">
diff --git a/web/src/lib/stores/mobile-device.svelte.ts b/web/src/lib/stores/mobile-device.svelte.ts
index 19fe28b452..ee6fa87dab 100644
--- a/web/src/lib/stores/mobile-device.svelte.ts
+++ b/web/src/lib/stores/mobile-device.svelte.ts
@@ -2,6 +2,7 @@ import { MediaQuery } from 'svelte/reactivity';
 
 const pointerCoarse = new MediaQuery('pointer:coarse');
 const maxMd = new MediaQuery('max-width: 767px');
+const sidebar = new MediaQuery(`min-width: 850px`);
 
 export const mobileDevice = {
   get pointerCoarse() {
@@ -10,4 +11,7 @@ export const mobileDevice = {
   get maxMd() {
     return maxMd.current;
   },
+  get isFullSidebar() {
+    return sidebar.current;
+  },
 };
diff --git a/web/src/lib/stores/side-bar.svelte.ts b/web/src/lib/stores/side-bar.svelte.ts
deleted file mode 100644
index 791ee32c91..0000000000
--- a/web/src/lib/stores/side-bar.svelte.ts
+++ /dev/null
@@ -1 +0,0 @@
-export const isSidebarOpen = $state({ value: false });
diff --git a/web/src/lib/stores/sidebar.svelte.ts b/web/src/lib/stores/sidebar.svelte.ts
new file mode 100644
index 0000000000..bebc9ca5b2
--- /dev/null
+++ b/web/src/lib/stores/sidebar.svelte.ts
@@ -0,0 +1,21 @@
+import { mobileDevice } from '$lib/stores/mobile-device.svelte';
+
+class SidebarStore {
+  isOpen = $derived.by(() => mobileDevice.isFullSidebar);
+
+  /**
+   * Reset the sidebar visibility to the default, based on the current screen width.
+   */
+  reset() {
+    this.isOpen = mobileDevice.isFullSidebar;
+  }
+
+  /**
+   * Toggles the sidebar visibility, if available at the current screen width.
+   */
+  toggle() {
+    this.isOpen = mobileDevice.isFullSidebar ? true : !this.isOpen;
+  }
+}
+
+export const sidebarStore = new SidebarStore();
diff --git a/web/tailwind.config.js b/web/tailwind.config.js
index e701eefd7a..95611d486d 100644
--- a/web/tailwind.config.js
+++ b/web/tailwind.config.js
@@ -55,6 +55,7 @@ export default {
         'max-lg': { max: '1023px' },
         'max-md': { max: '767px' },
         'max-sm': { max: '639px' },
+        sidebar: { min: '850px' },
       },
     },
   },