Files
bookhoard/ROUTER_REFACTOR_PLAN.md
T
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

13 KiB

Router Refactoring Execution Plan

Objective

Refactor 858-line cmd/server/main.go by migrating route definitions to internal/router/ package while maintaining 100% API compatibility and passing all verification tests.

Current State

  • internal/router/ package created with 7 files
  • Route stubs implemented for: auth, library, device, frontend, docs
  • Router package NOT integrated (never called from main.go)
  • All routes still defined in main.go (duplicates)
  • ⚠️ main.go: 858 lines (target: ~200 lines)

Success Criteria

  1. All 26 verification checks pass (scripts/verify-guidelines.sh)
  2. All Go tests pass (go test ./...)
  3. All Bruno/curl API tests pass
  4. No API behavior changes (routes, handlers, responses identical)
  5. main.go reduced to ~200 lines
  6. Code compiles without errors
  7. Application runs successfully (containers start, health check returns 200)

Migration Strategy: Incremental with Rollback Safety

Phase 1: Create Safety Branch

  • Create branch continue-router-refactor
  • Router package structure exists

Phase 2: Integrate Router Package (DO THIS FIRST)

Step 2.1: Add Router Import and Config

File: cmd/server/main.go

Add to imports:

"bookhoard/internal/router"

Add after line 130 (after rateLimiter initialization):

// ========================================================================
// ROUTER REGISTRATION - Migrate routes to internal/router/ package
// ========================================================================
routerConfig := &router.Config{
    Echo:                 e,
    Queries:              queries,
    Cfg:                  cfg,
    DBPool:               dbPool,
    AuthHandler:          authHandler,
    LibraryHandler:       libraryHandler,
    DeviceHandler:        deviceHandler,
    KOReaderHandler:      koreaderHandler,
    WSHandler:            wsHandler,
    ConflictHandler:      conflictHandler,
    AnalyticsHandler:     analyticsHandler,
    QueueHandler:         queueHandler,
    CollectionHandler:    collectionHandler,
    OPDSHandler:          opdsHandler,
    ConnManager:          connManager,
    QueueProcessor:       queueProcessor,
    DeviceAuthMiddleware: deviceAuthMiddleware,
    LoginTracker:         loginAttemptTracker,
}

Step 2.2: Call Router.RegisterRoutes()

Add immediately after routerConfig:

router.RegisterRoutes(routerConfig)

IMPORTANT: Do NOT remove any routes from main.go yet!

Step 2.3: Test Compilation

go build ./cmd/server

Expected: Should compile (routes will be duplicated but that's OK temporarily)

Step 2.4: Test Application

# Stop containers if running
podman-compose down

# Rebuild and start
podman-compose up -d --build

# Wait for startup
sleep 10

# Test health endpoint
curl -s http://localhost:8765/health | jq .

# Test frontend
curl -s http://localhost:8765/ | grep -o "<title>.*</title>"

# Run verification
bash scripts/verify-guidelines.sh

Expected: All should pass (duplicate routes don't break Echo)

ROLLBACK IF: Compilation fails or health check returns non-200

  • git checkout -- cmd/server/main.go

Phase 3: Remove Duplicate Routes from main.go

⚠️ CRITICAL: Remove ONE route group at a time, test after each removal!

Step 3.1: Remove Auth Routes (lines 132-191)

Lines to remove: From // Auth routes to // JWT middleware for protected routes (before jwtMiddleware creation)

Actually: Keep jwtMiddleware creation (it's used by other routes) Remove: auth POST endpoints and protected auth routes that are now in router/auth.go

Test after removal:

go build ./cmd/server
podman-compose up -d --build
sleep 10
# Test auth endpoints
curl -X POST http://localhost:8765/api/auth/register -H "Content-Type: application/json" -d '{"email":"test@test.com","username":"test","password":"Test123!"}'

Step 3.2: Remove Library Routes (lines 192-235)

Lines to remove: From // Library management routes to visibility routes

Test after removal:

go build ./cmd/server
podman-compose up -d --build
# Test library endpoints
curl -s http://localhost:8765/api/libraries/types | jq .

Step 3.3: Remove Device Registration Routes (lines 236-239)

Lines to remove: Device register and status endpoints

Test after removal:

go build ./cmd/server
# Device registration test

Step 3.4: Remove Frontend Routes (lines 627-823)

Lines to remove: From // FRONTEND ROUTES to before // HEALTH CHECK

Test after removal:

go build ./cmd/server
curl -s http://localhost:8765/ | grep -o "<title>.*</title>"

Step 3.5: Remove Health Check (lines 824-844)

Lines to remove: From // HEALTH CHECK to before // DOCUMENTATION ROUTES

Test after removal:

go build ./cmd/server
curl -s http://localhost:8765/health | jq .

Step 3.6: Remove Documentation Routes (lines 845-858)

Lines to remove: From // DOCUMENTATION ROUTES to end

Test after removal:

go build ./cmd/server
curl -s http://localhost:8765/docs | grep -o "<title>.*</title>"

Phase 4: Implement Remaining Router Stubs

Step 4.1: Create router/sync.go

# Create file with sync routes (KOReader, Kobo, websocket)
# Copy sync route definitions from main.go

Routes to migrate:

  • KOReader sync routes (device authentication required)
  • Kobo sync routes (device authentication required)
  • Book matching routes
  • WebSocket endpoint

Step 4.2: Create router/media.go

Routes to migrate:

  • Media item routes (download, shelf management)
  • Bulk book operations

Step 4.3: Create router/analytics.go

Routes to migrate:

  • Analytics routes (API + SSR)

Step 4.4: Create router/queue.go

Routes to migrate:

  • Sync queue management routes (API + SSR)

Step 4.5: Create router/opds.go

Routes to migrate:

  • OPDS routes (public - device authentication optional)

Step 4.6: Update router/collections.go

Routes to migrate:

  • Collection routes (API + SSR)

Phase 5: Complete Migration

For each new route file created in Phase 4:

  1. Add registerXYZRoutes(cfg *Config) function
  2. Call it from router.RegisterRoutes() in router.go
  3. Remove corresponding routes from main.go
  4. Test with: go build ./cmd/server
  5. Test with: podman-compose up -d --build
  6. Test specific endpoints with curl
  7. Run: bash scripts/verify-guidelines.sh

Phase 6: Final Verification

Step 6.1: Full Test Suite

# Compilation
go build ./cmd/server
go test ./...

# Verification
bash scripts/verify-guidelines.sh

# Container test
podman-compose down
podman-compose up -d --build
sleep 15

# Critical endpoint tests
curl -s http://localhost:8765/health | jq .
curl -s http://localhost:8765/ | grep -o "<title>.*</title>"
curl -s http://localhost:8765/api/libraries/types | jq .
curl -s http://localhost:8765/docs | grep -o "<title>.*</title>"

# Run Bruno tests (if available)
# bruno test ...

Step 6.2: Verify main.go Size

wc -l cmd/server/main.go

Expected: ~200 lines (down from 858)

Step 6.3: Code Review Checklist

  • No routes duplicated (each route defined once)
  • All route groups use JWT middleware correctly
  • Admin middleware applied where needed
  • Rate limiting applied to auth endpoints
  • No compilation errors
  • All imports used
  • Consistent code style with rest of codebase

Phase 7: Commit and Push

Step 7.1: Review Changes

git diff cmd/server/main.go | head -100
git diff internal/router/

Step 7.2: Run Verification

bash scripts/verify-guidelines.sh

Step 7.3: Commit Changes

git add cmd/server/main.go internal/router/
git commit -m "refactor: complete router package migration

- Migrate all routes from main.go to internal/router/ package
- Reduce main.go from 858 lines to ~200 lines
- Create separate files for route groups:
  - auth.go: Authentication routes
  - library.go: Library management
  - device.go: Device registration & management
  - sync.go: KOReader/Kobo/WebSocket sync routes
  - media.go: Media items and bulk operations
  - analytics.go: Analytics API + SSR
  - queue.go: Sync queue management
  - opds.go: OPDS feeds
  - collections.go: Collection management
  - frontend.go: SSR pages and health check
  - docs.go: Documentation routes

- All 26 verification checks pass
- All API endpoints tested and working
- Zero API behavior changes (100% compatible)
- Follows Go standard project layout

Breaking Change: None - API compatibility maintained"

Step 7.4: Push

git push origin continue-router-refactor

Rollback Procedures

If compilation fails at any point:

git checkout -- cmd/server/main.go
# Or
git reset --hard HEAD

If tests fail:

  1. Check which endpoint failed
  2. Verify route is registered in router package
  3. Check handler method exists
  4. Check middleware is applied correctly
  5. Review error logs: podman logs bookhoard

If verification fails:

  1. Check which specific check failed
  2. Fix the issue
  3. Re-run verification
  4. Commit the fix separately

Testing Commands (Quick Reference)

# Compile
go build ./cmd/server

# Verification
bash scripts/verify-guidelines.sh

# Unit tests
go test ./...

# Rebuild containers
podman-compose down
podman-compose up -d --build

# Wait for startup
sleep 10

# Health check
curl -s http://localhost:8765/health | jq .

# Frontend
curl -s http://localhost:8765/ | grep -o "<title>.*</title>"

# Auth endpoint test
curl -X POST http://localhost:8765/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{"login":"test","password":"wrong"}'

# Library types
curl -s http://localhost:8765/api/libraries/types | jq .

# Documentation
curl -s http://localhost:8765/docs | grep -o "<title>.*</title>"

# Check container logs
podman logs bookhoard | tail -30

# Check container status
podman ps

Files Created/Modified

Created:

  • internal/router/router.go - Main router configuration
  • internal/router/auth.go - Authentication routes
  • internal/router/library.go - Library management routes
  • internal/router/device.go - Device routes
  • internal/router/frontend.go - Frontend SSR routes
  • internal/router/docs.go - Documentation routes
  • internal/router/helpers.go - Template helpers
  • internal/router/sync.go - Sync routes (Phase 4)
  • internal/router/media.go - Media routes (Phase 4)
  • internal/router/analytics.go - Analytics routes (Phase 4)
  • internal/router/queue.go - Queue routes (Phase 4)
  • internal/router/opds.go - OPDS routes (Phase 4)
  • internal/router/collections.go - Collection routes (Phase 4)

Modified:

  • cmd/server/main.go - Reduced from 858 to ~200 lines

Estimated Time

  • Phase 2: 15 minutes (integration and initial testing)
  • Phase 3: 45 minutes (incremental route removal and testing)
  • Phase 4: 90 minutes (implement remaining route groups)
  • Phase 5: 30 minutes (complete migration)
  • Phase 6: 30 minutes (final verification)
  • Phase 7: 15 minutes (commit and push)

Total: ~4 hours


Notes for AI Assistants

  1. Always test after each change - don't batch multiple route removals
  2. Keep main.go functional - it should compile at all times
  3. Verify API compatibility - routes must respond identically
  4. Use git commits - commit after each successful phase to enable rollback
  5. Check logs - if something fails, check podman logs bookhoard
  6. Verification script is authority - if it fails, fix before continuing
  7. Echo allows duplicate routes - temporarily OK during migration
  8. Middleware order matters - maintain exact middleware application order
  9. Import statements - remove unused imports after route removal
  10. Handler methods - verify handler methods exist before calling them

Troubleshooting

Error: "route already registered"

  • Cause: Route defined multiple times
  • Fix: Remove from main.go, keep in router package only

Error: "handler method not found"

  • Cause: Typo in method name or handler not initialized in Config
  • Fix: Check method name in handler file, ensure handler is passed in Config

Error: "undefined: jwtMiddleware"

  • Cause: JWT middleware not created in that route file
  • Fix: Add JWT middleware creation at top of register function

Error: "404 on previously working endpoint"

  • Cause: Route not registered or middleware blocking access
  • Fix: Check route is registered, check middleware conditions

Health check returns 503

  • Cause: Database not connected or dbPool not passed to router
  • Fix: Ensure DBPool is set in routerConfig

Verification fails with "Build failed"

  • Cause: Compilation error
  • Fix: Run go build ./cmd/server to see specific error

Success Metrics

Before:

  • cmd/server/main.go: 858 lines
  • All routes defined inline
  • Mixed concerns (setup + routes + server start)

After:

  • cmd/server/main.go: ~200 lines
  • Routes organized by domain in internal/router/
  • Clear separation: setup → router registration → server start
  • Follows Go standard project layout
  • Easy to maintain and extend

End of Plan