- Remove wood-light, wood-dark, wood-mahogany from ThemeType
- Remove wood theme gradient logic from applyTheme()
- Wood themes will be reimplemented as separate paneling feature
- Paneling will target dashboard bookshelf background only
- Phase 5: Change line number to structural reference (before closing brace)
- Fix all TypeScript build commands from 'npm run build' to 'npm run build:ts'
- Ensures plan aligns with actual package.json scripts
- Prevents execution failures during implementation
- Add Phase 1b to remove wood themes from profile_form.templ
- Add woodPanelingInit.ts to Phase 2 for early initialization
- Remove inline JavaScript from Phase 7, use TypeScript instead
- Update Critical Requirements to prohibit inline scripts entirely
- Update Files Summary with new files and modifications
- All changes align with PROJECT_GUIDELINES.md requirements
- Add .zed/ to gitignore (Zed editor config)
- Add .opencode/ to gitignore (opencode tool data)
- Remove .zed/settings.json from version control
- Keeps repository clean of IDE-specific files
- Add theme.js script include to header template
- Fixes theme selector not working on pages using Header component
- Ensures applyTheme() is defined before changeThemeTo() calls it
- Update admin.templ to use @AdminSidebar component
- Update admin_library.templ to use @AdminSidebar component
- Update admin_users.templ to use @AdminSidebar component
- Add sidebar layout wrapper to admin_users.templ (previously missing)
- Fix theme rendering to use user.Theme in all admin templates
- Remove duplicated sidebar markup across admin pages
- Create AdminSidebar component for admin panel navigation
- Support active state highlighting based on currentPath
- Consistent navigation across all admin pages
- Replaces duplicated sidebar markup in admin templates
- Add THEME_FIX_PLAN.md: comprehensive plan for theme system consistency
- Add ADMIN_SIDEBAR_PLAN.md: reusable admin sidebar component plan
- Add WOOD_PANELING_PLAN.md: wood paneling and full-width layout plan
- Document root cause of theme flashing issue
- Detail implementation plan for server-side theme rendering
- Include testing checklist and rollback strategy
- Cover wood theme gradient persistence fix
-- Rename 'build' to 'rebuild' for clarity (rebuilds all containers)
-- Rename 'build-force' to 'rebuild-force' for consistency
-- Add 'rebuild-app-force' target for app-only rebuild without cache
-- Add 'rebuild-force-db' target that DELETES database for clean rebuild
-- Improve help text to clarify what each target does
-- Remove circular dependency (rebuild no longer depends on clean)
-- All rebuild targets now preserve database unless explicitly stated
-- Reformat all generated template Go files with consistent indentation
-- Standardize code style across templates/
-- No functional changes, formatting only
-- Generated by templ tool during development
-- Add dedicated delete confirmation modal to admin/library page
-- Refactor deleteLibrary() to use modal instead of inline confirm()
-- Add showDeleteModal(), hideDeleteModal(), confirmDeleteLibrary() functions
-- Modal displays clear warning about what gets deleted
-- Improves UX by making the confirmation dialog more prominent and informative
- Create bruno/library/browse-folders.yml
- Single manual test case for admin context
- Unit/integration tests cover all scenarios (no auth, user, admin)
- Bruno provides quick manual API contract verification
Fixes: Issue 2 (manual testing)
- Add unit tests in internal/services/library_service_test.go
- Test path traversal protection
- Test non-existent path handling
- Test file vs directory validation
- Test successful directory listing
- Add integration tests in cmd/server/tests/library_browse_test.go
- Use setupTestServer() helper from test_helpers.go
- Test no authentication returns 401
- Test regular user returns 403 forbidden
- Test admin can browse directories
- Test path traversal blocking
- All tests use table-driven approach with t.Run()
Fixes: Issue 2 (tests)
- Add BrowseDirectories() to library service with path traversal protection
- Add BrowseDirectories handler with proper error handling
- Register GET /api/libraries/browse endpoint (admin-only)
- Returns current path, parent path, and list of subdirectories
- Security: blocks "..", validates path exists, checks is directory
Fixes: Issue 2 (backend)
- Add optional data parameter to apiDelete() with generic type safety
- Enables DELETE requests with request bodies (needed for folder deletion)
- 100% backward compatible (optional parameter)
- Supports type-safe request body passing
Part of: Issue 1
- Reuse Create Library modal for edit mode
- Add hidden library-id input to track create vs edit
- Update handleCreateLibrarySubmit to detect mode and use PUT vs POST
- Implement editLibrary() to populate modal with existing data
- Pass library data to Edit button via data attributes
- Reset modal title when opening for create mode
Fixes: Issue 3
Complete refactor of /admin/library page to use server-side rendering
and TypeScript, fixing broken Create Library button and improving UX.
Backend Integration:
- Update template signature to accept libraries and users parameters
- Add SSR rendering of library list (no empty state)
- Add SSR rendering of user select dropdown
- Data fetched in router handler and passed to template
TypeScript Conversion:
- Create web/src/library.ts (394 lines) - complete rewrite of inline JS
- Convert all inline JavaScript to TypeScript
- Fix critical data.data API response bug
- Replace broken HTMX form with fetch() API calls
- Implement event delegation for dynamic button clicks
- Add missing editLibrary() function (placeholder)
- Add proper error handling with toast notifications
Template Changes:
- Remove 229 lines of inline JavaScript
- Update Create Library button: onclick → data-action
- Update form: remove HTMX attributes, add onsubmit handler
- Remove duplicate script tags from <head> section
- Keep all script loading at end of <body> for performance
Bug Fixes:
- Fix API response handling: data → data.data
- Replace broken hx-headers (JavaScript not supported in HTMX)
- Fix modal z-index and visibility classes
Progressive Enhancement:
- Page works without JavaScript (SSR content visible)
- JavaScript enhances with interactive features
- Follows PROJECT_GUIDELINES: procedural style, no OOP
Update the /admin/library route handler to fetch and pass data to
template for server-side rendering, improving page load performance.
Changes:
- Fetch all libraries using ListLibrariesData() helper
- Fetch all users for visibility management
- Convert database rows to template types (LibraryData, User)
- Pass data to AdminLibrary template for SSR
- Follows existing pattern from dashboard and custom-section pages
Benefits:
- Faster initial page load (no AJAX fetch)
- Better UX (content visible immediately)
- Progressive enhancement (works without JS)
Add ListLibrariesData() method to LibraryHandler to support
server-side rendering of all libraries on the /admin/library page.
This follows the existing pattern of GetUserVisibleLibrariesData() and
GetLibraryTypeData() methods, which return data structures instead of
JSON for template rendering.
Changes:
- Add ListLibrariesData() method (3 lines)
- Returns []database.ListLibrariesRow for template consumption
- Called by frontend route handler for SSR
Update admin dashboard sidebar to point to user administration page
instead of profile settings:
- Change link from /profile to /admin/users
- Update label from 'Profile Settings' to 'User Administration'
This completes the admin navigation refactoring to use dedicated
admin pages instead of the main user profile page.
Add --force-recreate flag to all build targets that create containers:
- build: Force recreation when building all containers
- rebuild-app: Force recreation of app container only (fixes template update issue)
- build-force: Force recreation even when using --no-cache
- test-env-up: Force recreation in test environment
This fixes a critical issue where 'make rebuild-app' would build a new image
but continue running the old container, causing template changes to not appear.
Root cause: podman-compose up --build doesn't recreate containers if they're
already running, even when a new image is built. The --force-recreate flag
ensures containers are recreated with the new image.
BuildKit caching still works as expected - cache is used during image build,
while --force-recreate ensures the new image is actually deployed.
Changes:
- build: Add --force-recreate flag
- rebuild-app: Add --force-recreate flag, update success message
- build-force: Add --force-recreate flag
- test-env-up: Add --force-recreate flag
Verified: Template changes now appear immediately after rebuild.
- Add password requirements checklist with visual indicators (✓/○)
- Implement real-time validation for length, case, numbers, special chars
- Add confirm password field with matching validation
- Disable submit button until all requirements are met
- Add TypeScript client-side validation with password manager compatibility
- Replace inline nav code with @Header component in admin.templ
- Replace inline nav code with @Header component in admin_library.templ
- DRY up navigation, theme switcher, and user menu across admin pages
- Optimize Dockerfile layer caching with --mount=type=cache for Go modules and npm
- Reorganize Dockerfile layers for better cache hit rates
- Improve .dockerignore organization with categorized comments
- Add Makefile targets: up, down, rebuild-app, restart, ps
- Enhance Makefile help output with categorized sections
- Add theme.js script for proper theme support
- Update form to use CSS variables (--bg-primary, --text-secondary, etc.)
- Replace hardcoded colors with theming system
- Add optional first_name and last_name fields
- Update button to use .btn-primary class
- All form inputs now properly themed
Vendored the sevenzip package to eliminate dependency chain:
- sevenzip -> go4.org -> 25+ Google/Cloud/telemetry packages
Changes:
- Added internal/sevenzip/ with full package source
- Inlined go4.org/readerutil into multireaderat.go
- Updated all internal imports to use bookhoard/internal/sevenzip
- Preserved .cb7 comic archive support
This reduces bloat by ~4.9 MB and removes unused telemetry
dependencies while maintaining all functionality.
Add explicit check to verify target user exists in database before
attempting deletion. Previously, the handler would return 200 OK when
trying to delete non-existent users.
Changes:
- Add userFound flag to track if target user was found in user list
- Explicitly check pgtype.UUID.Bytes against all users' IDs
- Return 404 Not Found if user doesn't exist (before last admin check)
- Supports both JSON and HTML (HTMX) response formats
This fixes the failing test:
- TestDeleteUserConsolidated/DELETE_/api/auth/profile/:id_-_Delete_non-existent_user
The check uses the existing ListUsers result, so no additional database
query is required. The pgtype.UUID.Bytes comparison ensures exact
16-byte UUID matching.
The test was using simple passwords ('password1', 'password2') that
failed complexity validation before the mismatch check could run.
Changed to use valid complex passwords that don't match:
- new_password: 'NewPassword123!'
- confirm_password: 'DifferentPass123!'
This properly tests the mismatch validation path. All 4 subtests in
TestUpdatePasswordAdminMode now pass.
Add comprehensive testing documentation covering:
- Test email domain usage (@tests.bookhoard.internal)
- Standard test users and their credentials
- Test lifecycle and cleanup process
- How to write tests properly
- Running tests (make targets, specific tests)
- Test organization and helper functions
This helps developers understand the testing infrastructure and
prevents accidental data loss when running tests.