diff --git a/.sisyphus/notepads/club-work-manager/learnings.md b/.sisyphus/notepads/club-work-manager/learnings.md
index 67dcad7..de37b1e 100644
--- a/.sisyphus/notepads/club-work-manager/learnings.md
+++ b/.sisyphus/notepads/club-work-manager/learnings.md
@@ -1546,3 +1546,5 @@ frontend/
3. **Add auth test**: Navigate to login flow (tests NextAuth integration)
4. **Add form test**: Fill tasks form and submit (tests API integration)
+- **Testing Radix UI DropdownMenu**: When testing Radix UI components like `DropdownMenu` with React Testing Library, you often need to either use complex test setups waiting for portal rendering and pointer events, or simply mock the Radix UI components out to test just the integration logic. Mocking `DropdownMenu`, `DropdownMenuTrigger`, etc., makes checking dropdown logic faster and less prone to portal-related DOM test issues.
+- **Provider Architecture in Next.js App Router**: Combining multiple providers like `SessionProvider`, `QueryProvider`, and a custom context provider like `TenantProvider` in `app/layout.tsx` is an effective way to handle global state. Custom components needing hooks must have `"use client"` at the top.
diff --git a/.sisyphus/plans/club-work-manager.md b/.sisyphus/plans/club-work-manager.md
index d6f71c3..1c0cd0a 100644
--- a/.sisyphus/plans/club-work-manager.md
+++ b/.sisyphus/plans/club-work-manager.md
@@ -1680,7 +1680,7 @@ Max Concurrent: 6 (Wave 1)
---
-- [ ] 18. App Layout + Club-Switcher + Auth Guard
+- [x] 18. App Layout + Club-Switcher + Auth Guard
**What to do**:
- Create root layout (`frontend/src/app/layout.tsx`):
diff --git a/frontend/bun.lock b/frontend/bun.lock
index e0dcdb9..6f33ae6 100644
--- a/frontend/bun.lock
+++ b/frontend/bun.lock
@@ -6,6 +6,7 @@
"name": "frontend",
"dependencies": {
"@auth/core": "^0.34.3",
+ "@tanstack/react-query": "^5.90.21",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"lucide-react": "^0.576.0",
@@ -543,6 +544,10 @@
"@tailwindcss/postcss": ["@tailwindcss/postcss@4.2.1", "", { "dependencies": { "@alloc/quick-lru": "^5.2.0", "@tailwindcss/node": "4.2.1", "@tailwindcss/oxide": "4.2.1", "postcss": "^8.5.6", "tailwindcss": "4.2.1" } }, "sha512-OEwGIBnXnj7zJeonOh6ZG9woofIjGrd2BORfvE5p9USYKDCZoQmfqLcfNiRWoJlRWLdNPn2IgVZuWAOM4iTYMw=="],
+ "@tanstack/query-core": ["@tanstack/query-core@5.90.20", "", {}, "sha512-OMD2HLpNouXEfZJWcKeVKUgQ5n+n3A2JFmBaScpNDUqSrQSjiveC7dKMe53uJUg1nDG16ttFPz2xfilz6i2uVg=="],
+
+ "@tanstack/react-query": ["@tanstack/react-query@5.90.21", "", { "dependencies": { "@tanstack/query-core": "5.90.20" }, "peerDependencies": { "react": "^18 || ^19" } }, "sha512-0Lu6y5t+tvlTJMTO7oh5NSpJfpg/5D41LlThfepTixPYkJ0sE2Jj0m0f6yYqujBwIXlId87e234+MxG3D3g7kg=="],
+
"@testing-library/dom": ["@testing-library/dom@10.4.1", "", { "dependencies": { "@babel/code-frame": "^7.10.4", "@babel/runtime": "^7.12.5", "@types/aria-query": "^5.0.1", "aria-query": "5.3.0", "dom-accessibility-api": "^0.5.9", "lz-string": "^1.5.0", "picocolors": "1.1.1", "pretty-format": "^27.0.2" } }, "sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg=="],
"@testing-library/jest-dom": ["@testing-library/jest-dom@6.9.1", "", { "dependencies": { "@adobe/css-tools": "^4.4.0", "aria-query": "^5.0.0", "css.escape": "^1.5.1", "dom-accessibility-api": "^0.6.3", "picocolors": "^1.1.1", "redent": "^3.0.0" } }, "sha512-zIcONa+hVtVSSep9UT3jZ5rizo2BsxgyDYU7WFD5eICBE7no3881HGeb/QkGfsJs6JTkY1aQhT7rIPC7e+0nnA=="],
diff --git a/frontend/package.json b/frontend/package.json
index 580b7c9..1df3d6c 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -13,6 +13,7 @@
},
"dependencies": {
"@auth/core": "^0.34.3",
+ "@tanstack/react-query": "^5.90.21",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"lucide-react": "^0.576.0",
diff --git a/frontend/src/app/(protected)/layout.tsx b/frontend/src/app/(protected)/layout.tsx
new file mode 100644
index 0000000..10c01b4
--- /dev/null
+++ b/frontend/src/app/(protected)/layout.tsx
@@ -0,0 +1,53 @@
+import { AuthGuard } from '@/components/auth-guard';
+import { ClubSwitcher } from '@/components/club-switcher';
+import Link from 'next/link';
+import { Button } from '@/components/ui/button';
+import { LogOut } from 'lucide-react';
+import { SignOutButton } from '@/components/sign-out-button';
+
+export default function ProtectedLayout({
+ children,
+}: {
+ children: React.ReactNode;
+}) {
+ return (
+