diff --git a/TYPESCRIPT_CONVERSION_PLAN.md b/TYPESCRIPT_CONVERSION_PLAN.md
deleted file mode 100644
index 1e8e364..0000000
--- a/TYPESCRIPT_CONVERSION_PLAN.md
+++ /dev/null
@@ -1,1666 +0,0 @@
-# TypeScript Conversion Plan for Bookhoard
-
-## Executive Summary
-
-Convert **~2,800 lines of inline JavaScript** across 14 template files into organized TypeScript modules while **preserving the existing Hybrid SSR architecture**. The web UI will remain a client of the JSON API, alongside Kobo, KOReader, and future plugins.
-
-**Core Strategy:** Server-Side Rendering (SSR) for initial page loads + TypeScript for CRUD operations via existing JSON API.
-
----
-
-## Current Architecture Analysis
-
-### Already Converted to TypeScript ✅
-| Source | Output | Lines | Purpose |
-|--------|--------|-------|---------|
-| `web/src/toast.ts` | `toast.js` | 226 | Toast notifications, HTMX/fetch interceptors |
-| `web/src/theme.ts` | `theme.js` | 130 | Theme management, smooth scrolling |
-| `web/src/header.ts` | `header.js` | 114 | Header dropdowns, theme/user menus |
-| `web/src/device-management.ts` | `device-management.js` | 102 | Device token copy/regeneration |
-
-### Remaining Standalone JavaScript ❌
-| File | Lines | Purpose |
-|------|-------|---------|
-| `web/static/search.js` | 275 | Header search with keyboard navigation, debouncing |
-
-### Inline JavaScript in Templates (~2,800 lines)
-| Template | Script Lines | Primary Functions |
-|----------|--------------|-------------------|
-| `dashboard.templ` | ~456 | Statistics, recent activity |
-| `docs.templ` | ~392 | Documentation search, sidebar toggle |
-| `devices.templ` | ~386 | Token regeneration, sync URL display |
-| `collections.templ` | ~362 | Bulk operations, filtering |
-| `unlinked_books.templ` | ~312 | Book matching, linking, bulk operations |
-| `collection_rules.templ` | ~239 | Rule CRUD operations, testing |
-| `admin_library.templ` | ~229 | Admin library scan |
-| `bookshelf.templ` | ~200 | Book viewing, pagination |
-| `api_explorer.templ` | ~103 | API testing, cURL generation |
-| `admin.templ` | ~29 | Admin dashboard actions |
-| `login.templ` | ~29 | Login theme selection |
-| `index.templ` | ~24 | Landing page theme preview |
-| `admin_profile.templ` | ~11 | Admin profile management |
-| `progress.templ` | ~6 | Reading progress |
-| `conflicts.templ` | 0 | **No inline JS - uses onclick handlers only** |
-| `queue.templ` | 0 | **No inline JS - uses onclick handlers only** |
-| `analytics.templ` | 0 | **No inline JS - uses onclick handlers only** |
-
-**Total: ~2,800 lines of inline JavaScript to convert**
-
-**Note:** `conflicts.templ`, `queue.templ`, and `analytics.templ` have NO `` in `
`
-- **Why:** Theme logic already exists in `web/src/theme.ts`, remove duplication
-- **Verify:** Theme dropdown still works after cleanup
-
-**6.2 Verify Progressive Enhancement**
-- Test all pages with JavaScript disabled
-- Ensure forms submit with full page reload (see Progressive Enhancement Pattern below)
-- Verify critical paths work without JS
-
-**6.3 Build Configuration**
-- Update `tsconfig.json` with new file structure (if needed)
-- Verify all `.ts` files compile to `.js` in `web/static/`
-- Add source maps for debugging (optional)
-
-**6.4 Testing**
-- Verify all features work with TypeScript
-- Check keyboard navigation
-- Test form submissions
-- Validate error handling
-
-**6.5 Documentation Search Integration**
-- Create `web/src/docs.ts`
-- `toggleSidebar()` - sidebar visibility toggle for mobile
-- Documentation search functionality:
- - Initialize lunr.js search index
- - Search input debouncing
- - Display search results
- - Navigate to search results
-- Remove inline script from `docs.templ`
-- **Note:** Template uses external libraries (lunr.js, lunr-flex.js) for search
-- Keep it simple - no complex search UI, just basic functionality
-
-**Build Verification:**
-- Run `npm run build:ts` to verify entire project compiles
-- Confirm all `.js` files generated in `web/static/`
-- No TypeScript compilation errors
-- Full manual testing of all features
-- Test documentation search functionality
-- Verify sidebar toggle works on mobile
-
-**Deliverable:** Clean templates, all inline JavaScript replaced with TypeScript modules, documentation search functional
-
----
-
-## Code Style Guidelines
-
-### 1. Procedural/Imperative with Functional Techniques
-
-**✅ GOOD:**
-```typescript
-// Pure function, no classes
-function createRuleItem(rule: Rule): HTMLElement {
- const div = document.createElement('div');
- div.className = 'rule-item';
- div.innerHTML = renderRuleHTML(rule);
- return div;
-}
-
-// Event delegation (one listener)
-document.addEventListener('click', (e) => {
- const target = e.target as HTMLElement;
- const deleteBtn = target.closest('[data-action="delete-rule"]');
- if (deleteBtn) {
- const ruleId = deleteBtn.dataset.ruleId;
- deleteRule(ruleId);
- }
-});
-```
-
-**❌ BAD:**
-```typescript
-// Class-based, OOP
-class RuleManager {
- private rules: Rule[] = [];
- constructor() { ... }
- addRule(rule: Rule) { ... }
-}
-```
-
-### 2. Type Definitions
-
-**Define TypeScript Interfaces Matching Go Handler JSON Tags:**
-```typescript
-// Matches internal/handlers/book_matching.go
-// Check JSON tags: `json:"progress_id"`, `json:"device_id"`, etc.
-// Reference: Find struct definition in Go handler file
-interface UnlinkedBookData {
- progress_id: string;
- device_id: string;
- device_name: string;
- device_type: 'koreader' | 'kobo' | 'web';
- title_from_device: string;
- file_path: string;
- sha256: string;
- last_sync_time: string;
- confidence_score: number;
- potential_matches: PotentialMatchData[];
-}
-
-interface PotentialMatchData {
- media_item_id: string;
- title: string;
- author: string;
- confidence: number;
- cover_image_path?: string;
-}
-```
-
-**Important: Database Rows vs Handler Structs**
-Some endpoints return database rows directly (e.g., `SearchMediaItemsRow`), not handler-defined structs. Always check the endpoint's return statement:
-
-```go
-// internal/handlers/media.go:SearchMediaItems()
-return c.JSON(http.StatusOK, partialResults) // Returns []SearchMediaItemsRow from database
-```
-
-When in doubt, grep the endpoint function and check what it actually returns.
-
-**Only Create Frontend-Specific Types When Necessary:**
-```typescript
-// OK: Frontend-specific state
-type SearchState = {
- query: string;
- results: MediaItem[];
- selectedIndex: number;
-};
-
-// OK: UI-specific config
-type ToastType = 'error' | 'success' | 'info';
-```
-
-### 3. Error Handling
-
-**Integrate with Toast System:**
-```typescript
-async function deleteRule(ruleId: string): Promise {
- try {
- const response = await (window as any).api.delete(`/collections/rules/${ruleId}`);
-
- if (!response.ok) {
- const error = await response.json();
- (window as any).showToast.error(error.message || 'Failed to delete rule');
- return;
- }
-
- (window as any).showToast.success('Rule deleted');
- removeRuleFromDOM(ruleId);
- } catch (error) {
- (window as any).showToast.error('Network error: Unable to connect to server');
- console.error('Delete rule error:', error);
- }
-}
-```
-
-### 4. API Client Pattern
-
-**Procedural API Client (No Classes):**
-```typescript
-// web/src/api.ts
-function getAuthHeader(): string {
- const token = localStorage.getItem('token');
- return token ? `Bearer ${token}` : '';
-}
-
-async function apiGet(url: string): Promise {
- return fetch(`/api${url}`, {
- headers: {
- 'Authorization': getAuthHeader(),
- 'Content-Type': 'application/json'
- }
- });
-}
-
-async function apiPost(url: string, data: unknown): Promise {
- return fetch(`/api${url}`, {
- method: 'POST',
- headers: {
- 'Authorization': getAuthHeader(),
- 'Content-Type': 'application/json'
- },
- body: JSON.stringify(data)
- });
-}
-
-async function apiDelete(url: string): Promise {
- return fetch(`/api${url}`, {
- method: 'DELETE',
- headers: {
- 'Authorization': getAuthHeader()
- }
- });
-}
-
-async function apiPut(url: string, data: unknown): Promise {
- return fetch(`/api${url}`, {
- method: 'PUT',
- headers: {
- 'Authorization': getAuthHeader(),
- 'Content-Type': 'application/json'
- },
- body: JSON.stringify(data)
- });
-}
-
-// Export to window for use in other modules
-(window as any).api = {
- get: apiGet,
- post: apiPost,
- delete: apiDelete,
- put: apiPut
-};
-```
-
-### 5. Event Handler Pattern (Pragmatic Mix)
-
-**Use onclick for Simple Static Content:**
-```html
-
-
-```
-**When to use:**
-- Static server-rendered HTML
-- Simple function calls to well-named functions
-- When you want explicit, readable HTML
-
-**Use data-action + Event Delegation for Dynamic Content:**
-```html
-
-
-```
-
-```typescript
-// Event delegation (one listener handles all dynamic items)
-document.addEventListener('click', async (e) => {
- const target = e.target as HTMLElement;
- const deleteBtn = target.closest('[data-action="delete-rule"]');
-
- if (deleteBtn) {
- const ruleId = deleteBtn.dataset.ruleId;
- if (ruleId && confirm('Are you sure you want to delete this rule?')) {
- await deleteRule(ruleId);
- }
- }
-});
-```
-**When to use:**
-- Dynamic content (rows added after page load)
-- Lists where every item needs the same handler
-- When event delegation genuinely simplifies the code
-
-**Use Form Interception for Progressive Enhancement:**
-```html
-
-
-```
-**When to use:**
-- Forms that must work without JavaScript
-- Progressive enhancement is required
-- Critical user flows
-
-**❌ DON'T:**
-- Mandate data-action everywhere (over-engineering)
-- Remove all onclick handlers (unnecessary refactoring)
-
-**✅ DO:**
-- Remove inline `
-```
-
-### After: TypeScript Module (Browser Globals)
-
-**TypeScript Module:**
-```typescript
-// web/src/collections.ts
-
-interface Rule {
- id: string;
- field: string;
- operator: string;
- value: string;
-}
-
-function escapeHtml(text: string): string {
- const div = document.createElement('div');
- div.textContent = text;
- return div.innerHTML;
-}
-
-async function loadRules(collectionId: string): Promise {
- try {
- const response = await (window as any).api.get(`/collections/${collectionId}/rules`);
-
- if (!response.ok) {
- throw new Error('Failed to load rules');
- }
-
- const rules: Rule[] = await response.json();
- renderRules(rules);
- } catch (error) {
- console.error('Load rules error:', error);
- (window as any).showToast.error('Failed to load rules');
- }
-}
-
-function renderRules(collectionId: string, rules: Rule[]): void {
- const container = document.getElementById('rules-container');
- if (!container) return;
-
- container.innerHTML = rules.map(rule => `
-
- ${escapeHtml(rule.field)}
-
-
- `).join('');
-}
-
-async function loadRules(collectionId: string): Promise {
- try {
- const response = await (window as any).api.get(`/collections/${collectionId}/rules`);
-
- if (!response.ok) {
- throw new Error('Failed to load rules');
- }
-
- const rules: Rule[] = await response.json();
- renderRules(collectionId, rules);
- } catch (error) {
- console.error('Load rules error:', error);
- (window as any).showToast.error('Failed to load rules');
- }
-}
-
-async function deleteRule(collectionId: string, ruleId: string): Promise {
- if (!confirm('Are you sure you want to delete this rule?')) {
- return;
- }
-
- try {
- const response = await (window as any).api.delete(`/collections/${collectionId}/rules/${ruleId}`);
-
- if (!response.ok) {
- throw new Error('Failed to delete rule');
- }
-
- (window as any).showToast.success('Rule deleted');
-
- const ruleElement = document.querySelector(`[data-rule-id="${ruleId}"]`);
- ruleElement?.remove();
- } catch (error) {
- console.error('Delete rule error:', error);
- (window as any).showToast.error('Failed to delete rule');
- }
-}
-
-// Export to window for HTML access
-(window as any).loadRules = loadRules;
-(window as any).deleteRule = deleteRule;
-
-// Initialize on page load
-if (typeof document !== 'undefined') {
- if (document.readyState === 'loading') {
- document.addEventListener('DOMContentLoaded', initializeCollectionRules);
- } else {
- initializeCollectionRules();
- }
-}
-
-function initializeCollectionRules() {
- const collectionId = document.body.dataset.collectionId;
- if (collectionId) {
- loadRules(collectionId);
- }
-}
-```
-
-**Cleaned Template:**
-```html
-
-
-
-
-
-
-
-
-
-
-
-
- { range .Rules }
-
- { .Field }
-
-
- { end }
-
-
-
-```
-
-**Benefits:**
-- ✅ No inline JavaScript logic (functions, fetch calls, state management)
-- ✅ Simple onclick calls are explicit and easy to understand
-- ✅ Type-safe API calls through procedural api module
-- ✅ Better error handling with toast integration
-- ✅ Reusable module attached to window
-- ✅ SSR still works (initial rules in HTML)
-- ✅ Progressive enhancement (form can submit without JS)
-- ✅ No ES modules or bundler needed (browser globals)
-
----
-
-*Generated: 2025-02-17*
-*Updated: 2025-02-18 (Revised to match existing codebase patterns)*
-*Updated: 2025-02-18 (Fixed file paths, removed unnecessary build scripts, added manual type sync strategy)*
-*Updated: 2025-02-18 (Changed to .d.ts for type definitions, added build verification steps, documented progressive enhancement pattern)*
-*Updated: 2025-02-18 (Corrected type definitions to use snake_case matching Go JSON tags, simplified progressive enhancement section, added missing types)*
-*Updated: 2025-02-18 (Clarified database row vs handler struct confusion, documented template-handler type sharing, added HTMX progressive enhancement details, added common pitfalls appendix)*
-*Updated: 2025-02-18 (Added missing templates: analytics, queue, conflicts, docs; added 10 missing type definitions; updated line counts to ~6,300; revised timeline to 20-25 days; added all missing phases and tasks)*
-*Updated: 2025-02-18 (VERIFIED CORRECTIONS: Fixed line counts (~2,800 actual vs ~6,300 estimated), corrected analytics/queue/conflicts type definitions to match actual Go structs, noted HTMX forms lack action attributes, reduced timeline to 13-18 days)*
-*Follows: PROJECT_GUIDELINES.md*
-*Architecture: Hybrid SSR + TypeScript CRUD (Browser Globals, No ES Modules)*
diff --git a/TYPESCRIPT_CONVERSION_VERIFICATION_CHECKLIST.md b/TYPESCRIPT_CONVERSION_VERIFICATION_CHECKLIST.md
deleted file mode 100644
index 30df244..0000000
--- a/TYPESCRIPT_CONVERSION_VERIFICATION_CHECKLIST.md
+++ /dev/null
@@ -1,781 +0,0 @@
-# TypeScript Conversion Plan Verification Checklist
-
-Use this checklist to comprehensively audit the TypeScript Conversion Plan in a single pass. Each item includes verification steps to confirm accuracy.
-
----
-
-## 1. Type Definition Verification
-
-### 1.1 Verify All Types Match Actual API Responses
-
-**For each type definition in `web/src/types/api.d.ts` (planned):**
-
-- [ ] Locate the API endpoint in `internal/handlers/*.go`
-- [ ] Check what the endpoint **actually returns** (return statement)
-- [ ] Determine if it returns:
- - Handler-defined struct (e.g., `handlers.BookInfo`)
- - Database row (e.g., `database.SearchMediaItemsRow`)
- - Map/slice of either
-- [ ] Find the source type definition:
- - Handler structs: `internal/handlers/*.go`
- - Database rows: `internal/database/queries.sql.go`
-- [ ] Verify all JSON tags match TypeScript interface fields (snake_case)
-- [ ] Map pgtype fields to TypeScript types:
- - `pgtype.Text` → `string | undefined`
- - `pgtype.UUID` → `string`
- - `pgtype.Timestamp` → `string` (ISO datetime)
- - `pgtype.Numeric` → `number` or `string`
- - `pgtype.Bool` → `boolean`
- - `[]string` → `string[]`
-
-**Common Pitfalls:**
-- Handler structs may be defined but unused (e.g., `search.go`'s `MediaItemSummary`)
-- Endpoints may return database rows directly, not handler structs
-- JSON tags may use snake_case while Go fields use PascalCase
-- Arrays vs single values (e.g., `author` string vs `authors` array)
-
-**Verification Commands:**
-```bash
-# Find endpoint implementation
-rg "func.*SearchMediaItems" internal/handlers/
-
-# Check return type
-rg -A 10 "func.*SearchMediaItems" internal/handlers/media.go | grep "return c.JSON"
-
-# Find type definition
-rg "type SearchMediaItemsRow struct" internal/database/queries.sql.go
-
-# Check JSON tags
-rg 'json:"' internal/database/queries.sql.go | grep "SearchMediaItemsRow"
-```
-
-### 1.2 Verify No Duplicate/Conflicting Type Definitions
-
-- [ ] No two TypeScript interfaces describe the same API response
-- [ ] No interface fields contradict actual JSON response
-- [ ] No unused handler structs are referenced in type comments
-- [ ] All inline types in `.ts` files could move to `types/api.d.ts`
-
----
-
-## 2. API Contract Verification
-
-### 2.1 Verify All API Endpoints Referenced in Plan Exist
-
-**For each endpoint mentioned:**
-
-- [ ] Endpoint exists in `internal/handlers/*.go`
-- [ ] Route is registered in routing code
-- [ ] HTTP method matches (GET/POST/PUT/DELETE)
-- [ ] Response format matches plan's type definitions
-- [ ] Authentication requirements match plan assumptions
-
-**Check Commands:**
-```bash
-# Find endpoint definition
-rg "POST.*collections.*rules" internal/handlers/
-
-# Check route registration
-rg "collections.*rules" cmd/server/ or internal/router/
-```
-
-### 2.2 Verify Authentication Patterns
-
-- [ ] All API endpoints that require auth are documented
-- [ ] Token storage approach matches (`localStorage.getItem('token')`)
-- [ ] Auth header format consistent (`Bearer ${token}`)
-- [ ] 401 handling documented (token clearing, redirect)
-
-### 2.3 Verify Error Response Formats
-
-- [ ] Error responses use consistent structure (`{"error": "message"}`)
-- [ ] Toast integration documented for all error cases
-- [ ] Network error handling documented
-- [ ] Validation error handling documented (400 responses)
-
----
-
-## 3. Cross-Reference Verification
-
-### 3.1 Template-Handler Type Sharing
-
-**For each template that imports handlers:**
-
-- [ ] Template imports `internal/handlers` package
-- [ ] Template uses handler types for SSR data (e.g., `handlers.BookInfo`)
-- [ ] TypeScript interfaces match the same handler JSON responses
-- [ ] No duplicate type definitions between handlers and templates
-- [ ] Template-only types are clearly marked (e.g., `PageData`, `UnsafeHTML`)
-
-**Verification:**
-```bash
-# Find templates importing handlers
-rg 'import.*handlers' templates/*.templ
-
-# Check handler type usage in templates
-rg 'handlers\.(CollectionData|BookInfo|UserProfile)' templates/*.templ
-```
-
-### 3.2 Existing TypeScript Module Patterns
-
-**Verify all existing `.ts` modules follow documented patterns:**
-
-- [ ] Procedural style (no classes, no `this`)
-- [ ] Functions exported to `window` object
-- [ ] No ES module imports/exports (browser globals)
-- [ ] Proper type annotations (`import type` for type-only imports)
-- [ ] Consistent error handling with toast integration
-
-**Check existing modules:**
-- `web/src/toast.ts`
-- `web/src/theme.ts`
-- `web/src/header.ts`
-- `web/src/device-management.ts`
-
-### 3.3 JavaScript to TypeScript Mapping
-
-**For each inline script in templates:**
-
-- [ ] Identify all `