diff --git a/templates/header.templ b/templates/header.templ
new file mode 100644
index 0000000..597e2f4
--- /dev/null
+++ b/templates/header.templ
@@ -0,0 +1,119 @@
+package templates
+
+templ Header(user User, currentPath string) {
+
+}
diff --git a/templates/header_templ.go b/templates/header_templ.go
new file mode 100644
index 0000000..afe1acf
--- /dev/null
+++ b/templates/header_templ.go
@@ -0,0 +1,63 @@
+// Code generated by templ - DO NOT EDIT.
+
+// templ: version: v0.3.977
+package templates
+
+//lint:file-ignore SA4006 This context is only used if a nested component is present.
+
+import "github.com/a-h/templ"
+import templruntime "github.com/a-h/templ/runtime"
+
+func Header(user User, currentPath string) templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
+ return templ_7745c5c3_CtxErr
+ }
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Var1 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var1 == nil {
+ templ_7745c5c3_Var1 = templ.NopComponent
+ }
+ ctx = templ.ClearChildren(ctx)
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return nil
+ })
+}
+
+var _ = templruntime.GeneratedTemplate
diff --git a/web/src/header.ts b/web/src/header.ts
new file mode 100644
index 0000000..bc3cc7c
--- /dev/null
+++ b/web/src/header.ts
@@ -0,0 +1,114 @@
+// Header functionality
+
+const toggleThemeDropdown = (): void => {
+ const dropdown = document.getElementById('theme-dropdown');
+ if (dropdown) {
+ dropdown.classList.toggle('hidden');
+
+ // Close user menu if open
+ const userMenu = document.getElementById('user-menu');
+ if (userMenu && !dropdown.classList.contains('hidden')) {
+ userMenu.classList.add('hidden');
+ }
+ }
+};
+
+const toggleUserMenu = (): void => {
+ const menu = document.getElementById('user-menu');
+ if (menu) {
+ menu.classList.toggle('hidden');
+
+ // Close theme dropdown if open
+ const themeDropdown = document.getElementById('theme-dropdown');
+ if (themeDropdown && !menu.classList.contains('hidden')) {
+ themeDropdown.classList.add('hidden');
+ }
+ }
+};
+
+const changeThemeTo = (theme: string): void => {
+ // Apply the theme
+ if (theme.startsWith('wood-')) {
+ // Apply wood background theme
+ document.body.className = `theme-${theme}`;
+
+ // Set wood background style
+ let woodGradient = '';
+ switch (theme) {
+ case 'wood-light':
+ woodGradient = 'linear-gradient(135deg, #deb887 0%, #d2a679 50%, #c9975b 100%)';
+ break;
+ case 'wood-dark':
+ woodGradient = 'linear-gradient(135deg, #8b7355 0%, #6b5344 50%, #5a4636 100%)';
+ break;
+ case 'wood-mahogany':
+ woodGradient = 'linear-gradient(135deg, #a0522d 0%, #8b4513 50%, #7a3c10 100%)';
+ break;
+ }
+
+ document.body.style.background = woodGradient;
+ document.body.style.backgroundSize = 'cover';
+ document.body.style.backgroundAttachment = 'fixed';
+ } else {
+ // Apply regular theme
+ document.body.className = `theme-${theme}`;
+ document.body.style.background = '';
+ document.body.style.backgroundSize = '';
+ document.body.style.backgroundAttachment = '';
+ }
+
+ // Save to localStorage
+ localStorage.setItem('theme', theme);
+
+ // Save to server if logged in
+ const token = localStorage.getItem('token');
+ if (token) {
+ fetch('/api/auth/theme', {
+ method: 'PUT',
+ headers: {
+ 'Content-Type': 'application/json',
+ 'Authorization': `Bearer ${token}`
+ },
+ body: JSON.stringify({ theme })
+ }).catch(err => console.log('Theme save failed', err));
+ }
+
+ // Close dropdown
+ const dropdown = document.getElementById('theme-dropdown');
+ if (dropdown) {
+ dropdown.classList.add('hidden');
+ }
+};
+
+const logout = (): void => {
+ localStorage.removeItem('token');
+ localStorage.removeItem('user');
+ window.location.href = '/';
+};
+
+// Close dropdowns when clicking outside
+document.addEventListener('click', (e) => {
+ const target = e.target as HTMLElement;
+ const themeDropdown = document.getElementById('theme-dropdown');
+ const userMenu = document.getElementById('user-menu');
+ const themeButton = target?.closest('button[onclick="toggleThemeDropdown()"]');
+ const userButton = target?.closest('button[onclick="toggleUserMenu()"]');
+
+ if (!themeButton && themeDropdown && !themeDropdown.classList.contains('hidden')) {
+ if (!themeDropdown.contains(target)) {
+ themeDropdown.classList.add('hidden');
+ }
+ }
+
+ if (!userButton && userMenu && !userMenu.classList.contains('hidden')) {
+ if (!userMenu.contains(target)) {
+ userMenu.classList.add('hidden');
+ }
+ }
+});
+
+// Make functions available globally
+(window as any).toggleThemeDropdown = toggleThemeDropdown;
+(window as any).toggleUserMenu = toggleUserMenu;
+(window as any).changeThemeTo = changeThemeTo;
+(window as any).logout = logout;