diff --git a/web/src/lib/components/settings/SettingsColumns.svelte b/web/src/lib/components/settings/SettingsColumns.svelte
new file mode 100644
index 00000000..e2e1b9cf
--- /dev/null
+++ b/web/src/lib/components/settings/SettingsColumns.svelte
@@ -0,0 +1,24 @@
+
+
+
+
+ {@render main()}
+
+ {#if side}
+
+ {@render side()}
+
+ {/if}
+
diff --git a/web/src/lib/components/settings/SettingsColumns.test.ts b/web/src/lib/components/settings/SettingsColumns.test.ts
new file mode 100644
index 00000000..1c0187ca
--- /dev/null
+++ b/web/src/lib/components/settings/SettingsColumns.test.ts
@@ -0,0 +1,21 @@
+import { describe, expect, test } from 'vitest';
+import { render, screen } from '@testing-library/svelte';
+import { createRawSnippet } from 'svelte';
+import SettingsColumns from './SettingsColumns.svelte';
+
+const snip = (id: string) => createRawSnippet(() => ({ render: () => `` }));
+
+describe('SettingsColumns', () => {
+ test('main and side are two columns that sit side by side on a wide screen', () => {
+ render(SettingsColumns, { main: snip('main'), side: snip('side') });
+ const grid = screen.getByTestId('main').parentElement!.parentElement!;
+ expect(grid.className).toMatch(/xl:grid-cols-2/);
+ expect(grid.children).toHaveLength(2);
+ expect(screen.getByTestId('side').parentElement!.parentElement).toBe(grid);
+ });
+
+ test('with only main, the groups keep to one column', () => {
+ render(SettingsColumns, { main: snip('only') });
+ expect(screen.getByTestId('only').parentElement!.parentElement!.children).toHaveLength(1);
+ });
+});
diff --git a/web/src/routes/settings/+layout.svelte b/web/src/routes/settings/+layout.svelte
index f1afb0c7..e872f42b 100644
--- a/web/src/routes/settings/+layout.svelte
+++ b/web/src/routes/settings/+layout.svelte
@@ -24,8 +24,10 @@
-
-
+
+
{@render children?.()}
diff --git a/web/src/routes/settings/about/+page.svelte b/web/src/routes/settings/about/+page.svelte
index ccd49a3c..9bcd2d83 100644
--- a/web/src/routes/settings/about/+page.svelte
+++ b/web/src/routes/settings/about/+page.svelte
@@ -1,4 +1,5 @@
{pageTitle('Settings · Notifications')}
-
+
+ {#snippet main()}
+
+ {/snippet}
+
diff --git a/web/src/routes/settings/playback/+page.svelte b/web/src/routes/settings/playback/+page.svelte
index 31dc1b2e..fadc038a 100644
--- a/web/src/routes/settings/playback/+page.svelte
+++ b/web/src/routes/settings/playback/+page.svelte
@@ -1,4 +1,5 @@