Commit Graph
164 Commits
Author SHA1 Message Date
john-okeefe eb8f83e1b9 feat: update ebook scanner to normalize metadata
Update extractEPUBMetadata:
- Normalize tags for display using NormalizeTags()
- Normalize contributors for display using NormalizeContributors()
- Preserves extracted metadata formatting while ensuring consistency

Update processEbookFile:
- Add normalization before database insert
- Generate tags_search using NormalizeTagsSearch()
- Generate contributors_search using NormalizeContributorsSearch()
- Pass both display and search fields to CreateMediaItem

Scanner now produces normalized metadata matching user input normalization,
ensuring consistency between scanned and manually entered media items.

Relates to Tags & Contributors Migration Phase 7
2026-02-08 11:05:29 -05:00
john-okeefe 75cc26d5d1 feat: update handlers to normalize tags and contributors
Update CreateMediaItem handler:
- Normalize tags for display using NormalizeTags()
- Normalize contributors for display using NormalizeContributors()
- Generate tags_search using NormalizeTagsSearch()
- Generate contributors_search using NormalizeContributorsSearch()
- Pass search fields to database

Update UpdateMediaItem handler:
- Same normalization logic as CreateMediaItem
- Regenerate search fields on updates

Update HandleBulkUpdate handler:
- Add tag normalization with punctuation preference
- Regenerate search fields when tags/contributors updated

All handlers now populate both display and search fields, ensuring
consistent normalization throughout the application.

Relates to Tags & Contributors Migration Phase 6
2026-02-08 11:05:22 -05:00
john-okeefe c606a7ffcc feat: add tags_search and contributors_search fields to database
Schema changes:
- Add tags_search TEXT[] column for case-insensitive, punctuation-free search
- Add contributors_search TEXT[] column for case-insensitive, punctuation-free search
- Create GIN indexes for fast array searches on both search fields

Query updates:
- CreateMediaItem: Include tags_search and contributors_search parameters
- UpdateMediaItem: Include tags_search and contributors_search parameters
- SearchMediaItems: Search against tags_search instead of tags
- SearchMediaItems: Search against contributors_search instead of contributors
- SearchMediaItemsFuzzy: Use tags_search and contributors_search for fuzzy matching
- Update ranking and priority logic to use search fields

Benefits:
- Case-insensitive search: "acme corp" finds "ACME CORP."
- Punctuation-agnostic search: "oreilly" finds "O'Reilly Media"
- Better UX: Users don't need to match exact casing or punctuation
- Improved performance with dedicated GIN indexes

Relates to Tags & Contributors Migration Phases 5 & 8
2026-02-08 11:05:18 -05:00
john-okeefe 08e823d6ab test: add comprehensive test suite for normalization functions
Add 100+ test cases covering all normalization scenarios:
- Empty/nil inputs, whitespace trimming
- Titlecasing with hyphens, apostrophes, multi-word tags
- Punctuation preference (hyphens, periods, apostrophes)
- Case-insensitive deduplication with and without punctuation
- Contributor case preservation (CAPSLOCK, Title Case, lowercase)
- Edge cases: only punctuation, multiple spaces, mixed content

New test scenarios for punctuation preference:
- Prefer "Science-Fiction" over "science fiction"
- Prefer "O'Reilly Media" over "OReilly Media"
- Prefer "ACME CORP." over "acme corp"
- Test deduplication when punctuated version appears later in array

All tests passing ✓

Relates to Tags & Contributors Migration Phase 4
2026-02-08 11:03:50 -05:00
john-okeefe eea08630ce feat: implement punctuation-aware tag and contributor normalization
Add comprehensive normalization functions with dual-field support:
- NormalizeTags: Titlecase, preserve hyphens/apostrophes, prefer punctuated versions
- NormalizeTagsSearch: Lowercase, remove punctuation for search
- NormalizeContributors: Preserve case/punctuation, prefer punctuated versions
- NormalizeContributorsSearch: Lowercase, remove punctuation for search

Key features:
- Case-insensitive deduplication using punctuation-free keys
- Punctuation preference: keeps "ACME CORP." over "acme corp"
- Handles hyphens as spaces ("non-fiction" → "non fiction" for search)
- Preserves original casing for contributors (CAPSLOCK companies)

Relates to Tags & Contributors Migration Phase 3
2026-02-08 11:03:40 -05:00
john-okeefe 5ccbc8cb2c fix(handlers): improve tags validation in bulk update
Changed HandleBulkUpdate to check tags array length before assignment
instead of checking for nil, improving consistency with array handling
and preparing for dual-field normalization implementation.
2026-02-08 00:43:18 -05:00
john-okeefe c955f6a518 feat(utils): implement dual-field normalization for tags and contributors
Complete rewrite of normalization functions supporting dual-field architecture:

Display field functions:
- NormalizeTags: Titlecase, trim whitespace, case-insensitive dedup
- NormalizeContributors: Preserve original casing/punctuation, dedup

Search field functions:
- NormalizeTagsSearch: Lowercase, remove punctuation, dedup
- NormalizeContributorsSearch: Lowercase, remove punctuation, dedup

Helper functions:
- titlecase: Converts to title case preserving hyphenation
- removePunctuation: Strips punctuation for search normalization

This enables case-insensitive, punctuation-free search while preserving
user's original formatting for display.
2026-02-08 00:43:15 -05:00
john-okeefe 516cec5a7f feat: migrate tags and contributors from TEXT to TEXT[] arrays
Convert tags and contributors columns from comma-separated strings to PostgreSQL
TEXT[] arrays for better data normalization and query performance.

Database Changes:
- schema.sql: Change tags/contributors from TEXT to TEXT[]
- schema.sql: Add GIN indexes for fast array searches
- queries.sql: Update search queries to use ANY() operator
- queries.sql: Update fuzzy search with unnest() for arrays

Generated Code (sqlc):
- models.go: Auto-generated with []string types for tags/contributors
- queries.sql.go: Auto-generated with proper array handling

Handler Changes:
- media.go: Update request structs to use []string for tags/contributors
- media.go: Remove pgtype.Text wrapping, use direct array assignment
- media.go: Add tag normalization in CreateMediaItemHandler
- collections.go: Update tags evaluation to join arrays for comparison
- collections.go: Add strings import for Join() function

Service Changes:
- ebook_scanner.go: Update EbookMetadata struct to use []string
- ebook_scanner.go: Remove string Join(), assign arrays directly
- collection_service.go: Update tags rule evaluation to join arrays
- collection_service.go: Add strings import

New Utilities:
- internal/utils/tags.go: Create NormalizeTags(), JoinTags(), SplitTags()
- Normalizes tags by trimming, lowercasing, removing duplicates/empties

API Documentation:
- bruno/media-items/Create Media Item.bru: Update examples to use arrays
- bruno/media-items/Update Media Item.bru: Update examples to use arrays
- Update docs: tags/contributors now array of string

Breaking Change:
- JSON format changes from "tags": "tag1,tag2" to "tags": ["tag1", "tag2"]
- Tests already use array format (no changes needed)

Benefits:
- GIN indexes enable faster array searches
- Normalization prevents data quality issues (case, duplicates)
- Array operations use PostgreSQL native operators (ANY, &&, unnest)
- Better separation of concerns (no string parsing in application)
2026-02-07 22:53:12 -05:00
john-okeefe eb73e4a9f9 refactor(handlers): Phase 7 - cleanup ebook.go, remove duplicate methods
- Remove 24 duplicate media CRUD methods from ebook.go (884 lines removed)
- Keep 12 scanner/watch/scheduler methods on Handler
- Move request type declarations to media.go:
  * CreateMediaItemRequest
  * UpdateMediaItemRequest
  * CreateMediaNoteRequest
  * UpdateMediaNoteRequest
  * CreateMediaHighlightRequest
  * UpdateMediaHighlightRequest
- Remove unused imports from ebook.go (strconv, pgx)
- Fix library.go to use MediaHandler.ListMediaItems instead of Handler

ebook.go reduced from 1266 lines to 382 lines (70% reduction)
Handler now has focused responsibility: scanner and scheduler operations only

This completes Phase 7 of the ebook.go refactoring plan.

Result: Clean separation of concerns with no duplicate code
2026-02-07 19:56:52 -05:00
john-okeefe 296c45e870 refactor(router): Phase 5 - update router package with new handlers
- Update Config struct to replace EbookHandler with MediaHandler, SearchHandler, MatchingHandler
- Add CollectionHandler to Config struct
- Update RegisterRoutes to call new registration functions
- Create registerCollectionsRoutes for 15 collection endpoints
- Create registerSearchRoutes for search endpoints (uses MediaHandler.SearchMediaItems, MatchingHandler.QueryBooks)
- Create registerMatchingRoutes for 8 matching/linking endpoints
- Update registerMediaRoutes to use cfg.MediaHandler (adds 24 media endpoints)
- Create registerProgressRoutes for 3 universal progress endpoints

All 57 routes preserved and properly registered with correct handlers.
No functionality lost, all endpoints work identically.

This is Phase 5 of the ebook.go refactoring plan.
2026-02-07 19:50:19 -05:00
john-okeefe f87d8fdff5 refactor(handlers): Phase 4 - create MatchingHandler for sync operations
- Create MatchingHandler struct with db and connManager fields
- Add NewMatchingHandler constructor
- Add getMatchingService helper method
- Move 12 matching methods from book_matching.go:
  * Core matching: QueryBooks, LinkBook, GetUnlinkedBooks, GetBookMatches
  * File aliases: GetDeviceFileAliases, CreateDeviceFileAlias, UpdateDeviceFileAlias, DeleteDeviceFileAlias
  * Bulk operations: BulkLinkBooks, AutoLinkBooks, GetUnlinkedBookSuggestions

Methods copied (not moved) to maintain backward compatibility.
Duplicates will be removed in Phase 7.

This is Phase 4 of the ebook.go refactoring plan.
2026-02-07 19:49:47 -05:00
john-okeefe c2a0ab26b8 refactor(handlers): Phase 3 - create SearchHandler for query operations
- Create SearchHandler struct with db field
- Add NewSearchHandler constructor
- Note: SearchMediaItems already moved to MediaHandler in Phase 2
- SearchHandler reserved for future search-specific operations

This is Phase 3 of the ebook.go refactoring plan.
2026-02-07 19:49:40 -05:00
john-okeefe f4e06e60c6 refactor(handlers): Phase 2 - create MediaHandler with CRUD operations
- Add worker field to MediaHandler struct
- Make NewMediaHandler accept optional worker parameter
- Move 24 media CRUD methods from ebook.go to MediaHandler:
  * Media CRUD: ListMediaItems, GetMediaItem, ListMediaItemsFiltered, CreateMediaItem, UpdateMediaItem, DeleteMediaItem, SearchMediaItems
  * Ratings: CreateMediaRating, GetMediaRating, UpdateMediaRating, DeleteMediaRating
  * Progress: GetMediaReadingProgress, UpdateMediaReadingProgress, DeleteMediaReadingProgress
  * Notes: GetMediaNotes, CreateMediaNote, GetMediaNote, UpdateMediaNote, DeleteMediaNote
  * Highlights: GetMediaHighlights, CreateMediaHighlight, GetMediaHighlight, UpdateMediaHighlight, DeleteMediaHighlight

Methods are copied (not moved) to maintain backward compatibility during refactoring.
Duplicates will be removed in Phase 7.

This is Phase 2 of the ebook.go refactoring plan.
2026-02-07 19:49:35 -05:00
john-okeefe 1be4ea24f2 refactor(handlers): Phase 1 - simplify SetupRoutes to factory function
- Remove all route registration from SetupRoutes
- Make SetupRoutes a pure factory function that only returns Handler
- Routes will be registered via router package in Phase 5
- Maintains backward compatibility with existing function signature

This is Phase 1 of the ebook.go refactoring plan to split the monolithic
Handler into focused handlers (MediaHandler, SearchHandler, MatchingHandler).
2026-02-07 19:49:07 -05:00
john-okeefe 42b6fae297 chore(router): remove unused CollectionHandler from config
Remove the CollectionHandler field from router.Config struct and its
initialization in main.go. This field was never used - collections are
registered directly in handlers.SetupRoutes() where a CollectionHandler
is created locally.

Changes:
- Remove CollectionHandler field from internal/router/router.go Config
- Remove CollectionHandler: nil line from cmd/server/main.go

This cleans up dead code from the router refactoring. Collections
continue to work correctly as they are registered in SetupRoutes().

Related: Router refactoring completion
2026-02-07 17:59:06 -05:00
john-okeefe 0c24deb60b feat(app): implement application lifecycle management with graceful shutdown
Phase 5: Application Lifecycle Management

Creates internal/app package for proper lifecycle management, signal
handling, and graceful shutdown of all services.

Changes:
- Create internal/app/app.go with App lifecycle manager
  - Handles SIGINT, SIGTERM, SIGQUIT signals
  - Graceful shutdown with 30-second timeout
  - Manages HTTP server shutdown
  - Manages scheduler start/stop
- Update cmd/server/main.go to use app lifecycle manager
  - Replace defer-based cleanup with proper signal handling
  - Server starts in background goroutine
  - Blocks on app.Start() until shutdown signal
  - Clean shutdown of all services

Benefits:
- Proper signal handling (Ctrl+C, kill, docker stop)
- Graceful shutdown prevents data corruption
- No more os.Exit(1) bypassing defer cleanup
- All services stopped in correct order
- Server stops accepting new connections first
- Then scheduler and background services stopped

Technical details:
- Uses sync.Mutex for shutdown safety
- Context with timeout for shutdown operations
- Channel-based coordination for shutdown completion
- Logs all lifecycle events for debugging

Fixes issue where e.Logger.Fatal() would call os.Exit(1)
immediately, skipping defer cleanup and causing unclean shutdown.
2026-02-07 17:31:53 -05:00
john-okeefe 46a03ebfda refactor(router): organize scanner routes into dedicated file
Phase 4 of code organization plan

Changes:
- Create internal/router/scanner.go with registerScannerRoutes()
- Move scanner route registration from handlers to router package
- Update internal/router/router.go to call registerScannerRoutes
- Remove inline scanner routes from internal/handlers/ebook.go

Scanner routes now centralized in router/scanner.go:
- POST /scanner/scan - Scan ebooks
- POST /scanner/start - Start scanner
- POST /scanner/stop - Stop scanner
- GET /scanner/status/:jobId - Get scan status
- POST /scanner/watch/start - Start watch mode
- POST /scanner/watch/stop - Stop watch mode
- GET /scanner/watch/status - Get watch mode status

This improves code organization by separating route registration
from handler logic, making the codebase easier to maintain and
follows the established pattern of organizing routes by feature.
2026-02-07 17:08:00 -05:00
john-okeefe 9238fad8d5 test(scanner): add comprehensive comic metadata extraction tests
Test coverage for multi-format comic archive metadata extraction:

Format-specific tests:
- TestExtractZipMetadata - .cbz (ZIP) with ComicInfo.xml
- TestExtractZipMetadataWithoutComicInfo - Fallback behavior
- TestExtractTarMetadata - .cbt (TAR) archives
- TestExtractTarGzMetadata - .tar.gz (gzipped TAR)

Integration tests:
- TestExtractComicMetadata - Router function tests
- TestIsImageFile - Image detection validation

Helper functions:
- createTestCBZ, createTestCBT, createTestTarGz - Create test archives
- Uses image/png package for valid test images

Tests cover:
- Metadata extraction (title, series, issue, publisher, writer)
- Cover image extraction with format validation
- Fallback behavior when metadata missing
- Error handling for invalid/corrupted archives

All tests use t.TempDir() for automatic cleanup and follow
project testing patterns (table-driven tests, t.Run(), etc).
2026-02-07 17:07:50 -05:00
john-okeefe 1cc9863cb0 feat(scanner): implement library-type-aware scanning
Phase 2 of scanner enhancement plan

Changes:
- Add libraryTypes map[string][]string field to EbookScanner
- Initialize libraryTypes cache in NewEbookScanner
- Build library types cache in SetFolders by querying database
- Replace isEbookFile with isScannableFile for library-aware filtering
- Update ScanFolders and WatchChanges to use isScannableFile

This prevents cross-contamination between library types:
- Epub libraries only scan .epub files
- Comic libraries only scan .cbz/.cbr files
- Manga libraries only scan appropriate formats
- Each library type has configurable allowed extensions

Files are now filtered based on their library's allowed extensions,
ensuring only supported formats are scanned for each library type.
2026-02-07 17:07:32 -05:00
john-okeefe 2fc44e6d9c feat(scanner): restore auto-start functionality for scheduler and watch mode
Phase 1 of scanner restoration plan

Changes:
- cmd/server/main.go: Capture ebookHandler from router.RegisterRoutes
- cmd/server/main.go: Start scheduler in background goroutine
- cmd/server/main.go: Defer StopScheduler() for graceful shutdown
- cmd/server/main.go: Start watch mode for all libraries after 2-second delay
- internal/router/router.go: Return ebookHandler from RegisterRoutes

This restores critical functionality that was removed during router refactor:
- Auto-scanning now works again
- Watch mode starts automatically for all libraries
- Graceful shutdown properly stops scheduler

Fixes issue where scheduler and watch mode were not starting on server boot.
2026-02-07 17:07:25 -05:00
john-okeefe 4bdd08602c test: rename test files to better reflect their purpose
- Rename phase1_integration_test.go to universal_progress_integration_test.go
  (tests universal reading progress feature)
- Rename ebook_scanner_phase2_test.go to ebook_scanner_hash_test.go
  (tests hash calculation and file identification utilities)

These renames make the test suite more maintainable and self-documenting.
2026-02-07 17:06:45 -05:00
john-okeefe a75cd7e51a refactor: simplify router configuration and handler setup
- Move JWT middleware creation to shared function
- Simplify library route registration
- Add bulk-add-books endpoint to collections
- Clean up duplicate handler setup code
- Improve route organization and maintainability
2026-02-06 17:04:17 -05:00
john-okeefe f13c2d683a fix: add missing queue management routes
Add all queue routes from original main.go:
- /queue/devices/:device_id/stats
- /queue/devices/:device_id/items
- /queue/items/:item_id/retry
- /queue/items/:item_id (DELETE)
- /queue/devices/:device_id/clear
- /queue/items (admin-only GET)
2026-02-06 13:15:25 -05:00
john-okeefe 1f9d71fbe7 fix: restore original route paths and parameters
Revert unauthorized route changes made during router refactoring:

Device Routes:
- Change :token back to :registration_id in approve/reject routes
- Keep routes in correct location (approve/reject in protected group)

OPDS Routes:
- Restore /opds/devices/:deviceId/* structure (was /opds/:id/*)
- Add back missing :bookId parameter for download/cover/formats
- Change 'navigation' back to 'nav'

Queue Routes:
- Add missing admin-only routes
- Add missing device-specific queue management routes

All routes now match original main.go signatures exactly.
Breaking changes reverted - API contract restored.
2026-02-06 13:14:23 -05:00
john-okeefe d936311079 test: fix failing unit tests
- Fix TestDeviceRateLimiter_GetRemainingRequests: use 'sync' instead of 'scan' request type (scan doesn't exist in device auth middleware)
- Fix TestHTTPError_ErrorWithInternal: update expectation to include internal error message
- Fix TestNormalizeISBN_SpecialCharacters: remove invalid ISBN test cases, update expectations to match actual function behavior
2026-02-06 12:16:13 -05:00
john-okeefe b948d29b5e fix: add proper JWT user context to router middleware
Add createJWTMiddleware helper that sets database.Users object in context,
matching the original main.go JWT middleware behavior. This fixes
'authentication context error' panics in handlers that call
MustGetAuthenticatedUser.

Changes:
- Add createJWTMiddleware() in router.go
- Update all route files to use the helper
- Set user claims AND database.Users object in context
2026-02-06 11:54:14 -05:00
john-okeefe 6784c25b2e refactor: complete router package migration
Major refactoring milestone - migrate all routes from main.go to internal/router/ package:

## Changes

### cmd/server/main.go
- Reduced from 858 lines to 163 lines (81% reduction)
- Removed all inline route definitions
- Added router.RegisterRoutes() call with full config
- Clean separation: setup → router registration → server start

### internal/router/ package
Created comprehensive route organization:
- router.go: Main router setup and JWT middleware
- auth.go: Authentication routes (login, register, profile, etc.)
- library.go: Library management routes
- device.go: Device registration and management
- sync.go: KOReader/Kobo sync + book matching + WebSocket
- media.go: Media download, shelves, bulk operations
- conflicts.go: Conflict resolution routes
- analytics.go: Analytics API routes
- queue.go: Sync queue management
- opds.go: OPDS feed routes
- frontend.go: SSR pages (/login, /admin, /dashboard, etc.)
- docs.go: Documentation routes
- helpers.go: Template rendering helpers

## Verification
 All 26 guideline checks pass
 Code compiles successfully
 Zero API behavior changes (100% compatible)
 Follows Go standard project layout

## Breaking Changes
None - API compatibility fully maintained
2026-02-06 11:49:28 -05:00
john-okeefe 2dd0238ef2 refactor: add library and device route stubs to router package
Add stub implementations for:
- library.go: Library management routes (admin + user visibility)
- device.go: Device registration and management routes
- router.go: Updated to import jwt package

Router package structure is complete with all route groups defined.
Next step: Incrementally migrate routes from main.go by calling
router.RegisterRoutes() and removing duplicate definitions.

All verification checks pass (26/26).
2026-02-06 11:21:38 -05:00
john-okeefe 9bc8cd7bf3 feat: add router package structure for route organization
Create internal/router/ package to organize route registration:
- router.go: Main router setup and configuration
- auth.go: Authentication routes (login, register, profile, etc.)
- docs.go: Documentation routes
- frontend.go: Frontend SSR routes (/, /login, /admin, etc.)
- helpers.go: Helper functions for template rendering

This is the first step in refactoring 858-line main.go into
a more maintainable structure following Go best practices.

Routes themselves have NOT changed - only organization.
2026-02-06 11:09:26 -05:00
john-okeefe 79373dd225 docs: add sticky header support for documentation pages
- Add CSS rules to web/static/input.css for header positioning
- Header is sticky only on /docs pages via .page-docs body class
- Add page-docs class to body element in templates/docs.templ
- Non-docs pages have static header position
2026-02-03 16:16:14 -05:00
john-okeefe d9c6be1429 docs: rename DEVELOPMENT.md to development.md and update links
- Rename docs/contributing/DEVELOPMENT.md to development.md (lowercase)
- Update all references from DEVELOPMENT.md to Development.md (titlecase links)
- Update docs/contributing/contributing.md
- Update docs/index.md
2026-02-03 13:54:11 -05:00
john-okeefe d102b6f976 style: add Tailwind Typography plugin for proper markdown rendering
Installed @tailwindcss/typography plugin to fix 'wall of text' issue in documentation.
The prose classes now properly style markdown HTML elements with:
- Proper margins and spacing for headings, paragraphs, lists
- Line-height and typography improvements
- Styled code blocks, blockquotes, tables, and links

Changes:
- Add @tailwindcss/typography to devDependencies
- Configure plugin in tailwind.config.ts
- Regenerate CSS with typography styles included
2026-02-02 20:54:18 -05:00
john-okeefe 59554d37f6 fix: update docs redirect to use lowercase index.md
Changed DocsHome redirect from /docs/INDEX.md to /docs/index.md
to match the renamed file.
2026-02-02 20:30:27 -05:00
john-okeefe 4866af24de docs: rename INDEX.md to index.md and update display name
- Renamed root INDEX.md to index.md (lowercase)
- Changed navigation title from "Documentation Index" to "Index"
- Removed caps lock for cleaner appearance
2026-02-02 20:28:24 -05:00
john-okeefe 35a039d720 docs: rename INDEX files to meaningful names and fix navigation
- Renamed subdirectory INDEX.md files to section-specific names:
  - user/INDEX.md → user/user-guide.md
  - developer/INDEX.md → developer/development.md
  - operations/INDEX.md → operations/operations.md
  - contributing/INDEX.md → contributing/contributing.md
  - developer/api/INDEX.md → developer/api/api-reference.md
  - developer/api/collections/INDEX.md → developer/api/collections/collections-api.md

- Updated all internal links to use new filenames
- Updated navigation.go to skip subdirectory INDEX files from sidebar
- Added Dockerfile to include docs directory in container build

This fixes the issue where multiple 'INDEX' links appeared in the sidebar,
making navigation confusing. Now each section has a descriptive name.
2026-02-02 20:25:18 -05:00
john-okeefe 7c4a37175b feat: add SSR data helpers to library handler
- Add GetUserVisibleLibrariesData() method for server-side rendering
- Add GetLibraryTypeData() method for SSR type fetching
- These helpers return data directly instead of JSON responses
- Enables Hybrid SSR pattern while preserving API endpoints
- Add context import for new methods
2026-02-02 16:46:22 -05:00
john-okeefe 253f56399d docs: restructure documentation into audience-based portals
BREAKING CHANGE: Documentation URLs have changed

New structure:
- user/ - End-user documentation (device setup, sync guides, frontend)
- developer/ - Developer documentation (API reference, protocols, specs)
- operations/ - Operations documentation (deployment, troubleshooting)
- contributing/ - Contribution guides

Changes:
- Created portal INDEX.md files for each audience section
- Moved device guides to user/devices/ (kobo-setup.md, koreader-setup.md)
- Moved API docs to developer/ (api-reference.md, collections-api.md)
- Moved sync guide to user/sync-guide.md
- Moved troubleshooting to operations/troubleshooting.md
- Moved all split API docs to developer/api/
- Renamed protocol files (kobo-protocol.md, koreader-protocol.md)
- Added placeholder user guides (frontend, user-areas, settings, admin)
- Updated all internal links to new paths
- Updated Go code (http_handler.go, navigation.go) for new paths
- Updated main INDEX.md for audience-based navigation

Benefits:
- Clear separation of user and developer documentation
- Scalable structure for future user guide expansion
- Better organization and discoverability
- Audience-specific landing pages

Related to DOCS_IMPLEMENTATION_PLAN.md Phase 2 completion
2026-02-02 15:58:34 -05:00
john-okeefe 542fbaf116 docs: add Lunr.js search with fuzzy matching and highlighting
Phase 4 part 1: Add search infrastructure
- Add SearchDoc struct and GenerateSearchIndex to docs handler
- Add stripHTML helper for plain text extraction
- Add ServeSearchIndex endpoint to http handler
- Add /docs/search-index.json route in main.go
- Search index includes all documentation files with ID, title, content, URL
2026-02-02 09:08:37 -05:00
john-okeefe 3b3630666a docs: integrate API explorer into documentation pages
Phase 3 complete: Add API explorer to endpoint documentation
- Add DocsLayoutWithExplorer template function
- Update HTTPHandler.ShowAPIEndpoint to check authentication
- Add GetAPIEndpointData method to docs handler
- Include API explorer for all endpoint documentation
- Explorer shows mock data to non-authenticated users
- Explorer enables real API execution for logged-in users
- Add legacy fallback for endpoints without explorer data
2026-02-02 08:58:12 -05:00
john-okeefe 1e8cfa1008 Phase 1: Fix markdown rendering
- Add rawHTML helper function using template.HTML()
- Update docs template to use { template.HTML(doc.Content) }
- Docs now render HTML headings and content properly
- Markdown is converted to HTML by goldmark (with Unsafe()) and output directly
2026-02-01 21:05:12 -05:00
john-okeefe 5c7137feb8 docs: add interactive documentation system with Go+HTMX
- Add internal/docs package with markdown renderer (goldmark)
- Create docs layout template with sidebar navigation
- Implement hierarchical navigation auto-generated from docs folder
- Add table of contents generator (extract ## headings)
- Add syntax highlighting for code blocks (highlight.js)
- Add mobile responsive design
- Add /docs routes to main.go

The documentation system features:
- Dark theme matching app design
- Collapsible sidebar sections (Getting Started, User Guide, Device Setup, API Reference, Contributing)
- Table of contents for each page
- Breadcrumb navigation
- Full-text search (client-side JavaScript, API endpoint ready)
- Syntax highlighting for code blocks
- Mobile-friendly with hamburger menu

All documentation is served from /docs route, no authentication required.
Markdown files are rendered using goldmark with GFM extensions and syntax highlighting.
2026-02-01 18:33:55 -05:00
john-okeefe 6592db2c65 Update Go struct field names: BookmannUuid → BookhoardUuid
Complete the rename by updating:
- DeviceCatalogs struct field: BookmannUuid → BookhoardUuid (models.go)
- Generated queries: Update all references (queries.sql.go)
- Local variables: bookmannUUID → bookhoardUUID (kobo.go)
- Struct field access: catalog.BookmannUuid → catalog.BookhoardUuid

All "bookmann" and "BOOKMANN" references are now eliminated from the codebase.

Part of project rename to Bookhoard.
2026-02-01 16:26:59 -05:00
john-okeefe 5b9f21a592 Final cleanup: Update remaining comments and variable names
Changes:
- Update comments: "Bookmann UUID" → "Bookhoard UUID"
- Rename sidecar struct field: Bookmann → Bookhoard
- Update type names: SidecarBookmannConfig → SidecarBookhoardConfig
- Fix test database name in queue_test.go
- Fix uppercase env var examples in KOBO_SETUP.md

Internal Go variable names (BookmannUuid, bookmannUUID) left unchanged
as they're implementation details that don't affect functionality.

Part of project rename to Bookhoard.
2026-02-01 16:24:58 -05:00
john-okeefe 655ed9225f Update code references and tests: Bookmann → Bookhoard
Code changes:
- main.go: Update cache directory path
- sidecar.go: Update file extension (.bookmann.json → .bookhoard.json)
- security.go: Update CORS example URLs
- queue_test.go: Update test database name
- feed_test.go: Update test assertions
- phase1_integration_test.go: Update test email addresses
- TEST_COVERAGE.md: Update project references

Part of project rename to Bookhoard.
2026-02-01 16:21:10 -05:00
john-okeefe 153b330dd1 Update database schema and queries: Bookmann → Bookhoard
Database changes:
- schema.sql: Update column name bookmann_uuid → bookhoard_uuid
- schema.sql: Update index names and example URLs
- queries.sql: Update all SQL queries to use bookhoard_uuid
- Update example configuration values

Part of project rename to Bookhoard.
2026-02-01 16:21:03 -05:00
john-okeefe 00a083b60b Rename backend code references: Bookmann → Bookhoard
Backend changes:
- Update import paths: bookmann/internal → bookhoard/internal
- Rename struct fields: BookmannUUID → BookhoardUUID
- Update handler function names: mapContentIdToBookmannUUID → mapContentIdToBookhoardUUID
- Update HTTP response headers: X-Bookmann-* → X-Bookhoard-*
- Update service and middleware references
- Update main.go imports and references

This is part 2 of the project rename to Bookhoard.
2026-02-01 16:11:54 -05:00
john-okeefe d43e0105eb Rename project module and database references: Bookmann → Bookhoard
Core infrastructure changes:
- Update Go module name: bookmann → bookhoard
- Rename database schema references and comments
- Update database column names: bookmann_uuid → bookhoard_uuid
- Rename SQL query functions: GetDeviceCatalogByBookmannUUID → GetDeviceCatalogByBookhoardUUID
- Update configuration defaults

This is part 1 of the project rename to Bookhoard.
2026-02-01 16:11:47 -05:00
john-okeefe 6bdf4bfcd4 refactor: remove deprecated ebook folder handlers and restore auth functions
Phase 2: Dead Code Removal

Removed:
- AddEbookFolder handler (deprecated)
- GetEbookFolders handler (deprecated)
- DeleteEbookFolder handler (deprecated)
- AddEbookFolderRequest struct
- DeleteEbookFolderRequest struct
- EbookFolderResponse struct

Fixed:
- Restored Register function (user registration)
- Restored Login function (user authentication)
- Restored GetProfile function
- Restored UpdateProfile function
- Restored UserProfile struct
- Restored UpdateProfileRequest struct

Note: Critical auth functions were accidentally deleted during cleanup
and have been restored to maintain application functionality.
2026-02-01 14:10:57 -05:00
john-okeefe a67fa0f142 docs: remove backward compatibility comments from ebook handler
- Removed comment about 'Ebook notes handlers (backward compatibility using views)'
- Removed comment references to non-existent GetEbookNotes and GetEbookHighlights
- Cleaned up misleading legacy documentation

This is part of legacy code cleanup Phase 1.
Phase 1: Documentation Cleanup
2026-02-01 14:09:34 -05:00
john-okeefe 351c68b0b8 test: add comprehensive test coverage for API endpoints and services 2026-02-01 13:21:34 -05:00