diff --git a/frontend/src/lib/nav/DesktopSidebar.svelte b/frontend/src/lib/nav/DesktopSidebar.svelte
new file mode 100644
index 0000000..3812cb5
--- /dev/null
+++ b/frontend/src/lib/nav/DesktopSidebar.svelte
@@ -0,0 +1,42 @@
+
+
+
diff --git a/frontend/src/lib/nav/DesktopSidebar.test.ts b/frontend/src/lib/nav/DesktopSidebar.test.ts
new file mode 100644
index 0000000..0f5ef69
--- /dev/null
+++ b/frontend/src/lib/nav/DesktopSidebar.test.ts
@@ -0,0 +1,61 @@
+import { describe, it, expect, vi } from 'vitest';
+import { render, screen } from '@testing-library/svelte';
+import DesktopSidebar from './DesktopSidebar.svelte';
+
+vi.mock('$app/stores', () => {
+ const { readable } = require('svelte/store');
+ return {
+ page: readable({ url: new URL('http://localhost/planner') })
+ };
+});
+
+describe('DesktopSidebar', () => {
+ it('renders the app name', () => {
+ render(DesktopSidebar, { props: { appName: 'Mealprep', householdName: 'Familie Müller' } });
+ expect(screen.getByText('Mealprep')).toBeInTheDocument();
+ });
+
+ it('renders the household name', () => {
+ render(DesktopSidebar, { props: { appName: 'Mealprep', householdName: 'Familie Müller' } });
+ expect(screen.getByText('Familie Müller')).toBeInTheDocument();
+ });
+
+ it('renders Plan section with 3 items', () => {
+ render(DesktopSidebar, { props: { appName: 'Mealprep', householdName: 'Familie Müller' } });
+ expect(screen.getByText('Plan')).toBeInTheDocument();
+ expect(screen.getByText('Planer')).toBeInTheDocument();
+ expect(screen.getByText('Rezepte')).toBeInTheDocument();
+ expect(screen.getByText('Einkauf')).toBeInTheDocument();
+ });
+
+ it('renders Household section with 2 items', () => {
+ render(DesktopSidebar, { props: { appName: 'Mealprep', householdName: 'Familie Müller' } });
+ expect(screen.getByText('Haushalt')).toBeInTheDocument();
+ expect(screen.getByText('Mitglieder')).toBeInTheDocument();
+ expect(screen.getByText('Einstellungen')).toBeInTheDocument();
+ });
+
+ it('has 5 navigation links total', () => {
+ render(DesktopSidebar, { props: { appName: 'Mealprep', householdName: 'Familie Müller' } });
+ const links = screen.getAllByRole('link');
+ expect(links).toHaveLength(5);
+ });
+
+ it('marks active item with aria-current="page"', () => {
+ render(DesktopSidebar, { props: { appName: 'Mealprep', householdName: 'Familie Müller' } });
+ const plannerLink = screen.getByRole('link', { name: /planer/i });
+ expect(plannerLink).toHaveAttribute('aria-current', 'page');
+ });
+
+ it('non-active items do not have aria-current', () => {
+ render(DesktopSidebar, { props: { appName: 'Mealprep', householdName: 'Familie Müller' } });
+ const recipesLink = screen.getByRole('link', { name: /rezepte/i });
+ expect(recipesLink).not.toHaveAttribute('aria-current');
+ });
+
+ it('renders a variety widget slot area', () => {
+ render(DesktopSidebar, { props: { appName: 'Mealprep', householdName: 'Familie Müller' } });
+ const widget = screen.getByTestId('variety-widget-slot');
+ expect(widget).toBeInTheDocument();
+ });
+});