Files
Huntarr-Sonarr/.cursor/rules/huntarr-dev.mdc
Admin9705 515927bd67 Enhance caching and refresh logic in huntarrUI
- Introduced mandatory page refresh on section changes to address caching issues and ensure fresh data display.
- Added guidelines to prevent complex cache management systems and endless refresh loops using an `isInitialized` flag.
- Implemented localStorage usage for storing target sections to facilitate navigation post-refresh.
- Updated debugging strategies to monitor refresh behavior and initialization status effectively.
2025-06-27 18:13:18 -04:00

663 lines
35 KiB
Plaintext

---
description: Huntarr development rules and patterns
globs: ["**/*.py", "**/*.js", "**/*.html", "**/*.css", "**/*.md"]
alwaysApply: true
---
# Huntarr Development Rules for Cursor AI
## 🚨 CRITICAL MANDATORY RULES
### NEVER AUTO-COMMIT
- NEVER automatically commit changes without explicit user approval
- Always present fixes to user first and get explicit approval before committing
- Let user decide when to commit
### MANDATORY TESTING WORKFLOW
- Docker: ALWAYS rebuild and test changes using: `cd /Users/home/Huntarr/Huntarr.io && docker-compose down && COMPOSE_BAKE=true docker-compose up -d --build`
- Local: ALWAYS use port 9706 for local testing: `HUNTARR_PORT=9706 python main.py`
- ALWAYS check logs for errors: `docker logs huntarr` (Docker) or terminal output (local)
- Test in both Docker and local environments
- Docker uses port 9705, local testing uses port 9706 to avoid conflicts
### CROSS-PLATFORM REQUIREMENTS
- NEVER use hard-coded absolute paths (e.g., `/config/file.json`)
- ALWAYS use `os.path.join()` for path construction
- ALWAYS use relative URLs in frontend (e.g., `./api/` not `/api/`)
- ALWAYS test: Docker, Windows, Mac, Linux, subpaths (`domain.com/huntarr/`)
## 🗄️ DATABASE-FIRST DEVELOPMENT
### ALWAYS Use DatabaseManager
- Use `DatabaseManager` class from `src/primary/utils/database.py` for ALL data operations
- NEVER use direct SQLite calls (`sqlite3.connect()`)
- NEVER use JSON file operations for persistent data
- DatabaseManager auto-detects environment (Docker vs local)
### Database Locations
- Docker: `/config/huntarr.db` (persistent volume)
- Local: `{project_root}/data/huntarr.db`
- Auto-detection handles path selection
### Code Pattern
```python
# ✅ CORRECT
from src.primary.utils.database import DatabaseManager
db = DatabaseManager()
db.set_setting('app', 'key', 'value')
# ❌ NEVER DO THIS
import sqlite3
conn = sqlite3.connect('/config/huntarr.db')
```
## 🌐 FRONTEND DEVELOPMENT RULES
### URL Patterns
- ALWAYS use relative URLs: `./api/endpoint` not `/api/endpoint`
- ALWAYS use relative redirects: `window.location.href = './'` not `'/'`
- This ensures subpath deployment works (`domain.com/huntarr/`)
### Documentation Links
- ALWAYS use GitHub documentation domain: `https://plexguide.github.io/Huntarr.io/`
- ALWAYS include proper anchors that exist in documentation
- ALWAYS verify anchors exist before linking
- Pattern: `https://plexguide.github.io/Huntarr.io/apps/[app-name].html#[anchor]`
### JavaScript Patterns
- ALWAYS declare variables before use in form generation
- NEVER use double backslashes in regex patterns
- ALWAYS handle undefined variables gracefully
### Page Refresh Caching Solution (Mandatory)
- ALWAYS implement page refresh on section changes to eliminate caching issues
- NEVER use complex cache management systems - simple refresh is more reliable
- ALWAYS use `isInitialized` flag to prevent endless refresh loops
- ALWAYS store target section in localStorage for post-refresh navigation
- This solves toggle visibility issues, stale data, and all frontend caching problems
## 🐛 COMMON ISSUE PREVENTION
### Log Regex Issues
- Use clean regex patterns without double backslashes
- Test regex patterns thoroughly
- File: `/frontend/static/js/new-main.js` - `connectEventSource()` method
### Settings Form Issues
- Include all field name variations for different apps
- Readarr: `hunt_missing_books`, `hunt_upgrade_books`
- Radarr: `hunt_missing_movies`, `hunt_upgrade_movies`
- Sonarr/Lidarr/Whisparr/Eros: `hunt_missing_items`, `hunt_upgrade_items`
- File: `/frontend/static/js/settings_forms.js`
### CSS Loading Order
- Add responsive CSS to external files, not inline in components
- Use debug borders to test CSS loading: `border: 2px solid lime !important;`
- Files: `/frontend/static/css/responsive-fix.css`, `/frontend/static/css/new-style.css`
### Hard-Coded Path Issues
- NEVER use hard-coded Docker paths that don't exist on bare metal
- Use environment detection pattern with DatabaseManager
- Test both Docker and local environments
### JavaScript Variable Undefined Errors
- Ensure all variables are declared before use in form generation
- File: `/frontend/static/js/settings_forms.js`
### Subpath Compatibility Issues
- Works at root domain but fails in subdirectories
- Use relative URLs everywhere: `./api/` not `/api/`
### Info Icon Documentation Link Issues
- Use proper GitHub documentation pattern with specific anchors
- Pattern: `https://plexguide.github.io/Huntarr.io/apps/[app-name].html#[anchor]`
- Always include `target="_blank" rel="noopener"` attributes
### GitHub API Rate Limiting Issues
- Use GitHub Actions + static manifest approach instead of direct API calls
- Fetch from static manifest.json updated by GitHub Actions
## 📁 KEY FILE LOCATIONS
### Backend Core
- `/src/primary/utils/database.py` - DatabaseManager class (USE THIS)
- `/src/primary/routes/common.py` - API endpoints
- `/src/primary/auth.py` - Authentication logic
- `/src/primary/cycle_tracker.py` - Timer functionality
### Frontend Core
- `/frontend/static/js/new-main.js` - Main UI logic
- `/frontend/static/js/settings_forms.js` - Settings forms
- `/frontend/templates/components/` - UI components
### Database Files
- Docker: `/config/huntarr.db`
- Local: `./data/huntarr.db`
## 🔧 DEVELOPMENT WORKFLOW
### Before Making Changes
1. Check current directory: `/Users/home/Huntarr/Huntarr.io`
2. Activate venv for local development: `source venv/bin/activate`
3. Review these rules
### Making Changes
1. Edit source code (never modify inside container)
2. For local testing: `HUNTARR_PORT=9706 python main.py` (uses ./data/huntarr.db on port 9706)
3. For Docker testing: `docker-compose down && COMPOSE_BAKE=true docker-compose up -d --build`
4. Check logs: `docker logs huntarr` (Docker) or terminal output (local)
5. Test functionality in both environments
### Before Committing
1. Test in Docker environment (port 9705)
2. Test in local environment (port 9706)
3. Test cross-platform compatibility
4. Test subpath scenarios
5. Check browser console for errors
6. Verify database persistence across container restarts
7. Get user approval before committing
## ⚠️ ANTI-PATTERNS TO AVOID
### Database Anti-Patterns
- ❌ Direct SQLite calls: `sqlite3.connect()`
- ❌ Hard-coded database paths: `/config/huntarr.db`
- ❌ JSON file operations for persistent data
- ❌ Not testing both Docker and local database operations
- ❌ Bypassing Synology optimizations with direct SQLite configuration
- ❌ Using `PRAGMA synchronous = FULL` outside of `_configure_connection()`
- ❌ Not testing database performance on network file systems
### Frontend Anti-Patterns
- ❌ Absolute URLs: `/api/endpoint`, `window.location.href = '/'`
- ❌ Wrong documentation domain links
- ❌ Missing anchor verification
- ❌ Double backslashes in regex
- ❌ Inline responsive CSS in components
### Development Anti-Patterns
- ❌ Modifying files inside containers
- ❌ Auto-committing without approval
- ❌ Testing only in Docker
- ❌ Not using virtual environment for local development
- ❌ Creating temporary files instead of fixing source
- ❌ Inconsistent behavior between missing/upgrade logic
- ❌ Reactive violation fixing (scan proactively instead)
- ❌ Documentation that promises non-existent features
- ❌ Frontend links without verifying documentation anchors exist
- ❌ Organic feature growth without reality checks
- ❌ Theoretical FAQ content (base on real user problems)
- ❌ Using port 9705 for local testing (conflicts with Docker)
### State Management Anti-Patterns
- ❌ Using global state locks instead of per-instance locks
- ❌ Frontend calculating times with `Date.now()` instead of using database times
- ❌ Inconsistent instance naming between frontend and backend API calls
- ❌ Not testing state persistence across page reloads
- ❌ Mixing cached frontend times with database-locked times
### Frontend Anti-Patterns (Additional)
- ❌ Event listeners overriding backend-provided data
- ❌ Inconsistent styling between similar components across apps
- ❌ Hard-coded CSS values instead of consistent color schemes
- ❌ Not clearing browser cache when testing frontend fixes
- ❌ Assuming frontend calculations match backend logic
- ❌ Multiple pagination systems conflicting (template vs JavaScript module)
- ❌ Template HTML containing pagination logic that overrides API-based pagination
- ❌ DOM element counting for pagination instead of using API total counts
### Caching Anti-Patterns (Critical)
- ❌ Complex cache management systems for simple data refresh needs
- ❌ Manual cache invalidation instead of automatic page refresh
- ❌ Frontend state caching causing stale data display
- ❌ Toggle visibility issues due to cached frontend state
- ❌ Endless refresh loops due to improper initialization detection
- ❌ Section switching without proper data refresh
## 🚨 PROACTIVE VIOLATION SCANNING
### Before Every Commit, Check For:
1. Absolute URL violations: `grep -r "fetch('/api/" frontend/ --include="*.js"`
2. Documentation violations: `grep -r "href.*plexguide.github.io" frontend/ --include="*.js" | grep -v "plexguide.github.io/Huntarr.io"`
3. Settings form initialization violations: `grep -r "innerHTML.trim.*!==.*''" frontend/static/js/new-main.js | grep -v "includes.*Content will be loaded here"`
4. Database violations: `grep -r "sqlite3.connect\|import sqlite3" src/ --include="*.py" | grep -v "database.py"`
5. Hard-coded path violations: `grep -r "/config" src/ --include="*.py" | grep -v "_detect_environment\|_get.*path\|DatabaseManager"`
6. JSON file operations: `grep -r "\.json\|json.load\|json.dump" src/ --include="*.py" | grep -v "requests.*json\|response.json\|Content-Type.*json"`
7. Frontend time calculation violations: `grep -r "Date.now.*hours.*60.*1000" frontend/ --include="*.js"`
8. Global state lock usage: `grep -r "stateful_lock" src/ --include="*.py" | grep -v "stateful_instance_locks"`
9. Inconsistent app styling: `grep -r "background.*linear-gradient.*rgba(15, 23, 42" frontend/ --include="*.js"`
10. Logs pagination conflicts: `grep -r "updateLogsPagination\|updatePagination" frontend/ --include="*.html" --include="*.js" | grep -v "LogsModule"`
11. Hunt Manager non-Sonarr clickable links: `grep -r "isClickable.*entry.app_type.*&&.*entry.instance_name" frontend/static/js/hunt_manager.js | grep -v "=== 'sonarr'" | wc -l`
12. Port 9705 usage in local testing: `grep -r "9705" main.py src/ | grep -v "docker\|container"`
13. Synology optimization bypasses: `grep -r "sqlite3.connect\|PRAGMA synchronous = FULL" src/ --include="*.py" | grep -v "_configure_connection"`
14. Endless refresh loop violations: `grep -r "location.reload" frontend/ --include="*.js" | grep -v "isInitialized"`
15. Missing initialization flag violations: `grep -r "switchSection.*function" frontend/ --include="*.js" | xargs grep -L "isInitialized"`
### Violation Scanning Commands
```bash
# Create violation_scan.sh for easy reuse
echo "=== HUNTARR VIOLATION SCAN ==="
echo "1. Absolute URL violations: $(grep -r "fetch('/api/" frontend/ --include="*.js" | wc -l)"
echo "2. Documentation violations: $(grep -r "href.*plexguide.github.io" frontend/ --include="*.js" | grep -v "plexguide.github.io/Huntarr.io" | wc -l)"
echo "3. Settings form initialization violations: $(grep -r "innerHTML.trim.*!==.*''" frontend/static/js/new-main.js | grep -v "includes.*Content will be loaded here" | wc -l)"
echo "4. Database violations: $(grep -r "sqlite3.connect\|import sqlite3" src/ --include="*.py" | grep -v "database.py" | wc -l)"
echo "5. Hard-coded path violations: $(grep -r "/config" src/ --include="*.py" | grep -v "_detect_environment\|_get.*path\|DatabaseManager" | wc -l)"
echo "6. JSON file violations: $(grep -r "\.json\|json.load\|json.dump" src/ --include="*.py" | grep -v "requests.*json\|response.json\|Content-Type.*json" | wc -l)"
echo "7. Frontend time calculation violations: $(grep -r "Date.now.*hours.*60.*1000" frontend/ --include="*.js" | wc -l)"
echo "8. Global state lock violations: $(grep -r "stateful_lock" src/ --include="*.py" | grep -v "stateful_instance_locks" | wc -l)"
echo "9. Inconsistent app styling violations: $(grep -r "background.*linear-gradient.*rgba(15, 23, 42" frontend/ --include="*.js" | wc -l)"
echo "10. Logs pagination conflict violations: $(grep -r "updateLogsPagination\|updatePagination" frontend/ --include="*.html" --include="*.js" | grep -v "LogsModule" | wc -l)"
echo "11. Hunt Manager non-Sonarr clickable links: $(grep -r "isClickable.*entry.app_type.*&&.*entry.instance_name" frontend/static/js/hunt_manager.js | grep -v "=== 'sonarr'" | wc -l)"
echo "12. Port 9705 usage in local code: $(grep -r "9705" main.py src/ | grep -v "docker\|container" | wc -l)"
echo "13. Synology optimization bypass violations: $(grep -r "sqlite3.connect\|PRAGMA synchronous = FULL" src/ --include="*.py" | grep -v "_configure_connection" | wc -l)"
echo "14. Endless refresh loop violations: $(grep -r "location.reload" frontend/ --include="*.js" | grep -v "isInitialized" | wc -l)"
echo "15. Missing initialization flag violations: $(grep -r "switchSection.*function" frontend/ --include="*.js" | xargs grep -L "isInitialized" | wc -l)"
```
## 📊 SPECIFIC BUG PATTERNS TO AVOID
### GitHub Issue #626 Pattern (2FA Verification)
- Check both `temp_2fa_secret` (setup) and `two_fa_secret` (enabled) in auth functions
- File: `/src/primary/auth.py`
### GitHub Issue #624 Pattern (Settings Persistence)
- Include all field name variations in form collection logic
- File: `/frontend/static/js/settings_forms.js`
### GitHub Issue #629 Pattern (Windows Database Access)
- Use DatabaseManager with proper Windows AppData support
- Never hard-code database paths
### GitHub Issue #615 Pattern (Synology NAS Performance Issues)
- Synology NAS systems experience severe SQLite performance issues with default settings
- Root cause: Network file systems (NFS/CIFS) perform poorly with `PRAGMA synchronous = FULL`
- Symptoms: 20-39 second database operations, "database is locked" errors, general slowness
- Solution: Automatic Synology detection with optimized SQLite settings
- Detection methods: `/usr/syno`, `/etc/synoinfo.conf`, `SYNOPKG_PKGNAME` env var, hostname patterns
- Optimized settings: `synchronous=NORMAL`, 40MB cache, 30s timeout, 128MB mmap, less frequent checkpoints
- User control: `HUNTARR_SYNOLOGY_OPTIMIZATIONS=false` to disable optimizations
- Expected improvement: 70-90% performance boost on Synology systems
- Safety: WAL mode, integrity checks, and error handling preserved
- File: `/src/primary/utils/database.py` - `_detect_synology_nas()` and `_configure_connection()` methods
### Frontend Log Regex Issues
- Malformed regex with double backslashes
- Fix: Use clean regex patterns without double backslashes
- File: `/frontend/static/js/new-main.js` - `connectEventSource()` method
### DEBUG Log Filtering Race Condition
- DEBUG logs appear in wrong filters (Info, Warning, Error)
- Fix: Apply filter to new entries as they arrive in EventSource
- File: `/frontend/static/js/new-main.js` - `connectEventSource()` method
### Per-Instance State Management Issues
- Global state locks affect all instances instead of being per-instance
- Frontend time calculations override database-locked times causing inconsistent display
- Fix: Implement per-instance database locks with `stateful_instance_locks` table
- File: `/src/primary/stateful_manager.py`, `/src/primary/utils/database.py`
### Frontend Time Calculation Override Bug
- Event listeners in form generation calculate new times using `Date.now()` instead of using database times
- Pattern: `const resetTime = new Date(Date.now() + (hours * 60 * 60 * 1000));`
- Symptom: Times change on page reload despite being locked in database
- Fix: Remove time calculation from event listeners, let backend provide locked times
- File: `/frontend/static/js/settings_forms.js` - state hours input event listeners
### Inconsistent App Styling Issues
- Apps may have different styling for similar components (e.g., state status sections)
- Check for consistent CSS styling across all app form generation functions
- Pattern: Sonarr using dark gradient while Radarr using green gradient for same component
- Fix: Standardize styling across all apps for similar UI elements
### Logs Pagination Conflict Issues
- Logs show correct total count briefly (e.g., "Page 1 of 365") but flash back to "Page 1 of 1"
- Next button gets disabled after the flash, preventing historical log access
- Root cause: Conflicting pagination systems between LogsModule and HTML template
- Pattern: Template has `updateLogsPagination()` function counting DOM elements and overriding API-based pagination
- Symptom: Console shows correct API response (totalLogs=7291, totalPages=365) but UI resets to 1 page
- Fix: Remove all template pagination code, let LogsModule handle all pagination via API calls
- Files: `/frontend/templates/components/logs_section.html`, `/frontend/static/js/logs.js`
### GitHub Issue #641 Pattern (Lidarr AlbumSearch String/Integer Issue)
- AlbumSearch fails with 500 error: "The JSON value could not be converted to System.Collections.Generic.List[System.Int32]"
- Root cause: Album IDs converted to strings with `str(album.get("id"))` but API expects List[int]
- Pattern: `album_id = str(album.get("id"))` followed by passing to `search_albums(album_ids_to_search)`
- Symptom: Lidarr returns 500 Internal Server Error for AlbumSearch command
- Fix: Keep album IDs as integers, only convert to string for processed checks: `album_id = album.get("id")` and `is_processed("lidarr", instance_name, str(album_id))`
- Files: `/src/primary/apps/lidarr/missing.py`, `/src/primary/apps/lidarr/upgrade.py`
### GitHub Issue #591 Pattern (Lidarr No Items Found Processing Logic)
- Large libraries (264k+ missing albums) report "No items found to process. Items tracked: 0"
- Root cause: Unreachable else clause in conditional logic flow after elif for artist mode
- Pattern: `if hunt_missing_mode == "album":` followed by `elif hunt_missing_mode == "artist":` followed by unreachable `else:` for album processing
- Symptom: Album mode processing falls through to wrong code path, no items processed
- Fix: Restructure conditional logic to properly handle both album and artist modes with explicit checks
- Files: `/src/primary/apps/lidarr/missing.py`
### GitHub Issue #628 Pattern (Hunt Manager Link Issues)
- Movie links redirect incorrectly to Radarr causing "Sorry, we could not find that movie" errors
- Root cause: All apps made clickable but only Sonarr title-based slugs work properly
- Pattern: `formatProcessedInfo()` making all app types clickable with external linking
- Symptom: Radarr/Lidarr/other app links fail with 404 or wrong movie pages
- Fix: Only make Sonarr entries clickable (`entry.app_type === 'sonarr'`), show other apps as plain text with tooltips
- Radarr expects movie IDs in URLs but Hunt Manager uses title-based slugs which don't match
- Files: `/frontend/static/js/hunt_manager.js` (history.js already correctly implemented)
### Settings Forms Initialization Pattern (Critical)
- **Problem**: Settings sections showing empty content despite having proper HTML templates and JavaScript functions
- **Root Cause**: Initialization functions checking for content but HTML comments count as "content"
- **Pattern**: `if (container.innerHTML.trim() !== '') { return; }` fails when container has `<!-- Content will be loaded here -->`
- **Symptom**: Console shows "already initialized, skipping" but form never generates
- **Critical Fix**: Check for actual content, not just any content including comments
- **Solution Pattern**:
```javascript
const currentContent = container.innerHTML.trim();
if (currentContent !== '' && !currentContent.includes('<!-- Content will be loaded here -->')) {
console.log('[huntarrUI] Already initialized, skipping');
return; // Already initialized
}
```
- **Files Affected**: `/frontend/static/js/new-main.js` (all `initialize*` functions)
- **Form Generation Flow**:
1. `initializeNotifications()` → checks container content → calls API → calls `SettingsForms.generateNotificationsForm()`
2. `initializeSettings()` → checks container content → calls API → calls `SettingsForms.generateGeneralForm()`
3. Similar pattern for all settings sections
- **Required Functions in SettingsForms**: `generateNotificationsForm()`, `generateGeneralForm()`, etc.
- **API Endpoints**: `/api/settings` (general), `/api/settings/general` (specific)
- **Template Containers**: `notificationsContainer`, `generalSettings`, etc.
- **Debug Logging**: Always add comprehensive console.log statements to track initialization flow
- **Testing**: Refresh page, navigate to section, check browser console for proper initialization sequence
### Sidebar Implementation Pattern (Critical)
- **Problem**: Multiple sidebars showing simultaneously causing visual clutter and navigation confusion
- **Root Cause**: Flash prevention script in `new-main.js` showing main sidebar on page load before specialized sidebar logic runs
- **Pattern**: Flash prevention checks localStorage but doesn't account for specialized sidebars (Requestarr, Settings)
- **Symptom**: Both main sidebar and specialized sidebar visible at same time, especially on mobile
- **Critical Fix**: Update flash prevention to hide main sidebar when specialized sidebar should be active
- **Solution Pattern**:
```javascript
// In flash prevention script (around line 90-120 in new-main.js)
// Check if we should show a specialized sidebar instead of main sidebar
const currentSection = localStorage.getItem('huntarrCurrentSection') || 'home';
const requestarrSections = ['requestarr-home', 'requestarr-history'];
const settingsSections = ['settings', 'scheduling'];
if (requestarrSections.includes(currentSection)) {
// Show Requestarr sidebar, hide main sidebar
document.getElementById('sidebar').style.display = 'none';
document.getElementById('requestarrSidebar').style.display = 'block';
} else if (settingsSections.includes(currentSection)) {
// Show Settings sidebar, hide main sidebar
document.getElementById('sidebar').style.display = 'none';
document.getElementById('settingsSidebar').style.display = 'block';
} else {
// Show main sidebar, hide specialized sidebars
document.getElementById('sidebar').style.display = 'block';
document.getElementById('requestarrSidebar').style.display = 'none';
document.getElementById('settingsSidebar').style.display = 'none';
}
```
- **Files Affected**: `/frontend/static/js/new-main.js` (flash prevention script)
- **Implementation Requirements**:
1. Always check localStorage section before showing any sidebar
2. Hide all other sidebars when showing one specific sidebar
3. Use consistent section naming: `requestarr-home`, `requestarr-history`, `settings`, `scheduling`
4. Test on both desktop and mobile to ensure no double sidebars
5. Ensure return buttons properly switch back to main sidebar
- **Mobile Compatibility**: Flash prevention must work on mobile where sidebar space is limited
- **Testing**: Navigate between sections, refresh page, check that only one sidebar shows at a time
### Page Refresh Pattern for Caching Issues (Critical)
- **Problem**: Frontend caching causing stale data display, especially toggle visibility issues
- **Root Cause**: Complex cache management systems are error-prone and difficult to maintain
- **Solution**: Simple page refresh on section changes eliminates all caching issues
- **Implementation Pattern**:
```javascript
// In switchSection function - frontend/static/js/new-main.js
switchSection: function(section) {
// Only refresh if this is a user-initiated section change (not initial page load)
// and we're switching to a different section
if (this.isInitialized && this.currentSection && this.currentSection !== section) {
console.log(`[huntarrUI] User switching from ${this.currentSection} to ${section}, refreshing page...`);
// Store the target section in localStorage so we can navigate to it after refresh
localStorage.setItem('huntarr-target-section', section);
location.reload();
return;
}
// ... rest of section switching logic
}
```
- **Initialization Flag Pattern**:
```javascript
// In init function - mark as initialized after setup complete
setTimeout(() => {
this.showDashboard();
// Mark as initialized after everything is set up to enable refresh on section changes
this.isInitialized = true;
console.log('[huntarrUI] Initialization complete - refresh on section change enabled');
}, 50);
```
- **Target Section Restoration**:
```javascript
// In init function - check for stored target section after refresh
const targetSection = localStorage.getItem('huntarr-target-section');
if (targetSection) {
console.log(`[huntarrUI] Found target section after refresh: ${targetSection}`);
localStorage.removeItem('huntarr-target-section');
// Navigate to the target section
this.switchSection(targetSection);
} else {
// Initial navigation based on hash
this.handleHashNavigation(window.location.hash);
}
```
- **Benefits**:
1. Eliminates ALL caching issues with zero complexity
2. Ensures fresh data on every section change
3. Solves toggle visibility problems automatically
4. No cache invalidation logic needed
5. Works consistently across all browsers
6. Simple to understand and maintain
- **Critical Requirements**:
1. MUST use `isInitialized` flag to prevent endless refresh loops
2. MUST store target section in localStorage for navigation after refresh
3. MUST clean up localStorage after navigation
4. MUST only trigger on user-initiated section changes, not initial page load
- **Files**: `/frontend/static/js/new-main.js`
- **Testing**: Verify no endless refresh loops, smooth navigation, fresh data display
### Endless Refresh Loop Prevention Pattern (Critical)
- **Problem**: Page refreshes continuously every 0.5 seconds due to improper refresh logic
- **Root Cause**: Refresh logic triggers on every `switchSection` call including initial page load
- **Symptom**: Infinite refresh loop making the application unusable
- **Critical Fix**: Use `isInitialized` flag to distinguish user navigation from initialization
- **Pattern to Avoid**:
```javascript
// ❌ WRONG - causes endless refresh loops
if (this.currentSection && this.currentSection !== section) {
location.reload(); // Triggers on initial page load!
}
```
- **Correct Pattern**:
```javascript
// ✅ CORRECT - only refreshes on user navigation
if (this.isInitialized && this.currentSection && this.currentSection !== section) {
location.reload(); // Only after initialization complete
}
```
- **Debugging**: If endless refresh occurs, check browser console for rapid section switching logs
- **Prevention**: Always test page load behavior, not just navigation behavior
## 🎯 DEBUGGING APPROACH
### Systematic Issue Discovery
1. Don't guess - scan systematically first
2. Use grep to find exact error patterns
3. Check browser console for JavaScript errors
4. Verify database operations in both environments
5. Test cross-platform compatibility
### Database Debugging
```bash
# Docker environment
docker exec huntarr ls -la /config/huntarr.db
docker exec huntarr sqlite3 /config/huntarr.db ".tables"
# Local environment
ls -la ./data/huntarr.db
sqlite3 ./data/huntarr.db ".tables"
# Test DatabaseManager operations
python3 -c "from src.primary.utils.database import DatabaseManager; db = DatabaseManager(); print('Database path:', db.db_path)"
# Synology-specific debugging
docker exec huntarr python3 -c "from src.primary.utils.database import HuntarrDatabase; db = HuntarrDatabase(); print('Synology detected:', db._detect_synology_nas())"
docker logs huntarr | grep -i "synology\|optimization"
docker exec huntarr sqlite3 /config/huntarr.db "PRAGMA synchronous; PRAGMA cache_size; PRAGMA mmap_size;"
```
### Subpath Deployment Debugging
- Check browser network tab for 404s on absolute URLs
- Search for absolute patterns: `grep -r "fetch('/api" frontend/`
- Check redirects: `grep -r "window.location.href.*= '/" frontend/`
- Verify all URLs are relative: `./api/` not `/api/`
### Frontend-Documentation Link Debugging
- Extract frontend anchor references: `grep -r "href.*#" frontend/static/js/ | grep -o "#[^\"]*"`
- Extract doc anchors: `grep -r 'id="[^"]*"' docs/ | grep -o 'id="[^"]*"'`
- Compare lists to find mismatches
### Log Issues Debugging
1. Check logs in database: `docker exec huntarr python3 -c "import sys; sys.path.insert(0, '/app/src'); from primary.utils.logs_database import get_logs_database; db = get_logs_database(); logs = db.get_logs(limit=10); [print(f'{log["timestamp"]} - {log["app_type"]} - {log["level"]} - {log["message"]}') for log in logs]"`
2. Test backend streaming: `curl -N -s "http://localhost:9705/logs?app=[app]"`
3. Check browser console for JavaScript errors
4. Verify regex patterns in `new-main.js`
### Settings Issues Debugging
1. Check form generation functions in `/frontend/static/js/settings_forms.js`
2. Verify initialization functions in `/frontend/static/js/new-main.js` (e.g., `initializeNotifications()`)
3. **Critical**: Check for HTML comment interference in container content checks
4. Test API endpoints: `/api/settings`, `/api/settings/general`
5. Verify container elements exist: `notificationsContainer`, `generalSettings`
6. Check browser console for initialization flow logs
7. Test save/load cycle and auto-save functionality
8. Verify info icon links point to existing documentation anchors
9. **Settings Forms Debug Pattern**:
```javascript
// Add to initialization functions for debugging
console.log('[huntarrUI] initializeX called');
console.log('[huntarrUI] container found:', container);
console.log('[huntarrUI] Current container content:', container.innerHTML.trim());
console.log('[huntarrUI] SettingsForms available:', typeof SettingsForms !== 'undefined');
console.log('[huntarrUI] generateXForm available:', typeof SettingsForms.generateXForm === 'function');
```
### CSS Issues Debugging
1. Check browser console for errors
2. Add debug borders: `border: 2px solid lime !important;`
3. Verify CSS loading order (external files vs inline)
4. Test specificity with `!important` declarations
5. Search for conflicting rules: `grep -r "className" frontend/static/css/`
### Documentation Issues Debugging
1. Test all links manually or with link checker
2. Verify features mentioned actually exist in codebase
3. Check frontend alignment with documentation
4. Audit FAQ against real support requests
### State Management Issues Debugging
1. Check database locks: `docker exec huntarr sqlite3 /config/huntarr.db "SELECT * FROM stateful_instance_locks;"`
2. Verify per-instance vs global locks in database schema
3. Test frontend instance name consistency across API calls
4. Monitor browser console for time calculation overrides
5. Check event listener patterns: `grep -r "Date.now.*hours.*60.*1000" frontend/`
### Frontend Time Display Issues Debugging
1. Compare database time vs displayed time on page reload
2. Check event listeners for time calculations in form generation
3. Verify API responses contain locked times from database
4. Test with browser cache cleared to rule out caching issues
5. Monitor network tab for API calls during page interactions
### App Styling Consistency Debugging
1. Search for styling patterns: `grep -r "background.*linear-gradient" frontend/static/js/`
2. Compare CSS classes between similar components across apps
3. Check for hard-coded styles vs CSS classes
4. Verify color consistency: `grep -r "rgba.*185.*129" frontend/`
5. Test visual consistency across all app settings forms
### Logs Pagination Conflict Debugging
1. Check browser console for pagination updates: Look for `[LogsModule] Updated pagination` messages
2. Verify API responses: Monitor network tab for `/api/logs` calls with correct `total` counts
3. Search for conflicting pagination: `grep -r "updateLogsPagination\|updatePagination" frontend/`
4. Check for DOM element conflicts: `grep -r "logsCurrentPage\|logsTotalPages" frontend/`
5. Test pagination elements: Verify only one system updates pagination DOM elements
6. Monitor for template interference: Look for template event listeners overriding LogsModule
7. Debug pagination state: Add console.log to see which system is updating pagination last
### Page Refresh System Debugging
1. Check for endless refresh loops: Monitor browser console for rapid section switching messages
2. Verify initialization flag: `console.log` the `isInitialized` state during section switches
3. Test localStorage cleanup: Verify `huntarr-target-section` is removed after navigation
4. Monitor refresh triggers: Look for `[huntarrUI] User switching from X to Y, refreshing page...` messages
5. Test initial page load: Ensure no refresh triggers during initialization
6. Verify section preservation: Check that target section is correctly restored after refresh
7. **Debug Pattern**:
```javascript
// Add to switchSection function for debugging
console.log('[huntarrUI] switchSection called:', {
section: section,
currentSection: this.currentSection,
isInitialized: this.isInitialized,
willRefresh: this.isInitialized && this.currentSection && this.currentSection !== section
});
```
### Caching Issues Debugging
1. **Simple Solution**: Instead of debugging complex cache issues, implement page refresh pattern
2. Check browser network tab for stale API responses
3. Verify localStorage is not holding outdated data
4. Test toggle visibility after section changes
5. Monitor console for cache-related error messages
6. **Remember**: Page refresh eliminates need for complex cache debugging
## 📝 MEMORY CREATION GUIDELINES
Create memories for:
- ✅ Bug fixes with root cause analysis
- ✅ New features and their implementation patterns
- ✅ Cross-platform compatibility fixes
- ✅ Performance improvements
- ✅ Database migration insights
## 🚀 DEPLOYMENT RULES
### Branch Management
- Work on feature branches
- Deploy to `dev` branch first
- Merge `dev` to `main` after testing
- Always pull latest changes before merging
### Testing Requirements
- Test in Docker environment
- Test in local development environment
- Test cross-platform paths
- Test subpath deployment scenarios
- Verify database persistence
## 📋 FOLLOW .github/listen.md GUIDELINES
This file automatically enforces the patterns from `.github/listen.md`. The user should not need to remind you about:
- Using DatabaseManager instead of direct SQLite
- Using relative URLs instead of absolute URLs
- Testing in both Docker and local environments
- Following cross-platform compatibility requirements
- Getting approval before committing changes
- Using proper documentation links with verified anchors
- Proactive violation scanning before commits
- Systematic debugging approaches
- Database-first development patterns
- Cross-platform path handling
---
**REMEMBER: These rules are automatically applied. Follow them without being reminded.**