# Aniworld Web Application Development Instructions This document provides detailed tasks for AI agents to implement a modern web application for the Aniworld anime download manager. All tasks should follow the coding guidelines specified in the project's copilot instructions. ## Project Overview The goal is to create a FastAPI-based web application that provides a modern interface for the existing Aniworld anime download functionality. The core anime logic should remain in `SeriesApp.py` while the web layer provides REST API endpoints and a responsive UI. ## Architecture Principles - **Single Responsibility**: Each file/class has one clear purpose - **Dependency Injection**: Use FastAPI's dependency system - **Clean Separation**: Web layer calls core logic, never the reverse - **File Size Limit**: Maximum 500 lines per file - **Type Hints**: Use comprehensive type annotations - **Error Handling**: Proper exception handling and logging ## Additional Implementation Guidelines ### Code Style and Standards - **Type Hints**: Use comprehensive type annotations throughout all modules - **Docstrings**: Follow PEP 257 for function and class documentation - **Error Handling**: Implement custom exception classes with meaningful messages - **Logging**: Use structured logging with appropriate log levels - **Security**: Validate all inputs and sanitize outputs - **Performance**: Use async/await patterns for I/O operations ## 📞 Escalation If you encounter: - Architecture issues requiring design decisions - Tests that conflict with documented requirements - Breaking changes needed - Unclear requirements or expectations **Document the issue and escalate rather than guessing.** --- ## 📚 Helpful Commands ```bash # Run all tests conda run -n AniWorld python -m pytest tests/ -v --tb=short # Run specific test file conda run -n AniWorld python -m pytest tests/unit/test_websocket_service.py -v # Run specific test class conda run -n AniWorld python -m pytest tests/unit/test_websocket_service.py::TestWebSocketService -v # Run specific test conda run -n AniWorld python -m pytest tests/unit/test_websocket_service.py::TestWebSocketService::test_broadcast_download_progress -v # Run with extra verbosity conda run -n AniWorld python -m pytest tests/ -vv # Run with full traceback conda run -n AniWorld python -m pytest tests/ -v --tb=long # Run and stop at first failure conda run -n AniWorld python -m pytest tests/ -v -x # Run tests matching pattern conda run -n AniWorld python -m pytest tests/ -v -k "auth" # Show all print statements conda run -n AniWorld python -m pytest tests/ -v -s #Run app conda run -n AniWorld python -m uvicorn src.server.fastapi_app:app --host 127.0.0.1 --port 8000 --reload ``` --- ## Implementation Notes 1. **Incremental Development**: Implement features incrementally, testing each component thoroughly before moving to the next 2. **Code Review**: Review all generated code for adherence to project standards 3. **Documentation**: Document all public APIs and complex logic 4. **Testing**: Maintain test coverage above 80% for all new code 5. **Performance**: Profile and optimize critical paths, especially download and streaming operations 6. **Security**: Regular security audits and dependency updates 7. **Monitoring**: Implement comprehensive monitoring and alerting 8. **Maintenance**: Plan for regular maintenance and updates ## Task Completion Checklist For each task completed: - [ ] Implementation follows coding standards - [ ] Unit tests written and passing - [ ] Integration tests passing - [ ] Documentation updated - [ ] Error handling implemented - [ ] Logging added - [ ] Security considerations addressed - [ ] Performance validated - [ ] Code reviewed - [ ] Task marked as complete in instructions.md - [ ] Infrastructure.md updated and other docs - [ ] Changes committed to git; keep your messages in git short and clear - [ ] Take the next task --- ## Task: Refactor CSS & JavaScript Files (Single Responsibility Principle) ✅ COMPLETED ### Status: COMPLETED The CSS and JavaScript files have been successfully refactored into modular structures. ### Summary of Changes **CSS Refactoring:** - Created 17 modular CSS files organized into `base/`, `components/`, `pages/`, and `utilities/` directories - `styles.css` now serves as an entry point with @import statements - All CSS files under 500 lines (largest: helpers.css at 368 lines) - Total: 3,146 lines across 17 files **JavaScript Refactoring:** - Created 6 shared utility modules in `js/shared/` - Created 11 index page modules in `js/index/` - Created 5 queue page modules in `js/queue/` - Uses IIFE pattern with `AniWorld` namespace for browser compatibility - All JS files under 500 lines (largest: scan-manager.js at 439 lines) - Total: 4,795 lines across 22 modules **Updated Files:** - `index.html` - Updated script tags for modular JS - `queue.html` - Updated script tags for modular JS - `test_static_files.py` - Updated tests for modular architecture - `test_template_integration.py` - Updated tests for new JS structure - `ARCHITECTURE.md` - Added frontend architecture documentation **Old Files (kept for reference):** - `app.js` - Original monolithic file (can be deleted) - `queue.js` - Original monolithic file (can be deleted) ### Original Overview Split monolithic `styles.css` (~2,135 lines), `app.js` (~2,305 lines), and `queue.js` (~993 lines) into smaller, focused files following the Single Responsibility Principle. Maximum 500 lines per file. All changes must maintain full backward compatibility with existing templates. ### Prerequisites - Server is running and functional before starting - All existing functionality works (login, index, queue pages) - Backup current files before making changes --- ### Task 1: Analyze Current File Structure **Objective**: Understand the current codebase before making changes. **Steps**: 1. Open and read `src/server/web/static/css/styles.css` 2. Open and read `src/server/web/static/js/app.js` 3. Open and read `src/server/web/static/js/queue.js` 4. Open and read `src/server/web/templates/index.html` 5. Open and read `src/server/web/templates/queue.html` 6. Open and read `src/server/web/templates/login.html` 7. Document all CSS sections (look for comment headers) 8. Document all JavaScript functions and their dependencies 9. Identify shared utilities vs page-specific code **Deliverable**: A mental map of all functions, styles, and their relationships. --- ### Task 2: Create CSS Directory Structure **Objective**: Set up the new CSS file organization. **Steps**: 1. Create directory: `src/server/web/static/css/base/` 2. Create directory: `src/server/web/static/css/components/` 3. Create directory: `src/server/web/static/css/pages/` 4. Create directory: `src/server/web/static/css/utilities/` **File Structure to Create**: ``` src/server/web/static/css/ ├── styles.css # Main entry point with @import statements ├── base/ │ ├── variables.css # CSS custom properties (colors, fonts, spacing) │ ├── reset.css # CSS reset and normalize styles │ └── typography.css # Font styles, headings, text utilities ├── components/ │ ├── buttons.css # All button styles │ ├── cards.css # Card and panel components │ ├── forms.css # Form inputs, labels, validation styles │ ├── modals.css # Modal and overlay styles │ ├── navigation.css # Header, nav, sidebar styles │ ├── progress.css # Progress bars, loading indicators │ ├── notifications.css # Toast, alerts, messages │ └── tables.css # Table and list styles ├── pages/ │ ├── login.css # Login page specific styles │ ├── index.css # Index/library page specific styles │ └── queue.css # Queue page specific styles └── utilities/ ├── animations.css # Keyframes and animation classes ├── responsive.css # Media queries and breakpoints └── helpers.css # Utility classes (hidden, flex, spacing) ``` --- ### Task 3: Split styles.css into Modular Files **Objective**: Extract styles from `styles.css` into appropriate module files. **Steps**: 1. **Extract variables.css**: - Find all `:root` CSS custom properties - Extract color variables, font variables, spacing variables - Include dark mode variables (`.dark-mode` or `[data-theme="dark"]`) 2. **Extract reset.css**: - Extract `*`, `body`, `html` base resets - Extract box-sizing rules - Extract default margin/padding resets 3. **Extract typography.css**: - Extract `h1-h6` styles - Extract paragraph, link, text styles - Extract font-related utility classes 4. **Extract buttons.css**: - Find all `.btn`, `button`, `.button` related styles - Include hover, active, disabled states - Include button variants (primary, secondary, danger, etc.) 5. **Extract cards.css**: - Extract `.card`, `.panel`, `.box` related styles - Include card headers, bodies, footers 6. **Extract forms.css**: - Extract `input`, `select`, `textarea` styles - Extract `.form-group`, `.form-control` styles - Extract validation states (error, success) 7. **Extract modals.css**: - Extract `.modal`, `.overlay`, `.dialog` styles - Include backdrop styles - Include modal animations 8. **Extract navigation.css**: - Extract `header`, `nav`, `.navbar` styles - Extract menu and navigation link styles 9. **Extract progress.css**: - Extract `.progress`, `.progress-bar` styles - Extract loading spinners and indicators 10. **Extract notifications.css**: - Extract `.toast`, `.alert`, `.notification` styles - Include success, error, warning, info variants 11. **Extract tables.css**: - Extract `table`, `.table` styles - Extract list styles if table-like 12. **Extract page-specific styles**: - `login.css`: Styles only used on login page - `index.css`: Styles only used on index/library page (series cards, search) - `queue.css`: Styles only used on queue page (queue items, download status) 13. **Extract animations.css**: - Extract all `@keyframes` rules - Extract animation utility classes 14. **Extract responsive.css**: - Extract all `@media` queries - Organize by breakpoint 15. **Extract helpers.css**: - Extract utility classes (.hidden, .flex, .text-center, etc.) - Extract spacing utilities 16. **Update main styles.css**: - Replace all content with `@import` statements - Order imports correctly (variables first, then reset, then components) **Import Order in styles.css**: ```css /* Base */ @import "base/variables.css"; @import "base/reset.css"; @import "base/typography.css"; /* Components */ @import "components/buttons.css"; @import "components/cards.css"; @import "components/forms.css"; @import "components/modals.css"; @import "components/navigation.css"; @import "components/progress.css"; @import "components/notifications.css"; @import "components/tables.css"; /* Pages */ @import "pages/login.css"; @import "pages/index.css"; @import "pages/queue.css"; /* Utilities (load last to allow overrides) */ @import "utilities/animations.css"; @import "utilities/responsive.css"; @import "utilities/helpers.css"; ``` **Verification**: - Start the server - Check login page styling - Check index page styling - Check queue page styling - Verify dark mode toggle works - Verify responsive design works --- ### Task 4: Create JavaScript Directory Structure **Objective**: Set up the new JavaScript file organization. **Steps**: 1. Create directory: `src/server/web/static/js/shared/` 2. Create directory: `src/server/web/static/js/index/` 3. Create directory: `src/server/web/static/js/queue/` **File Structure to Create**: ``` src/server/web/static/js/ ├── app.js # Main entry point for index page ├── queue.js # Main entry point for queue page ├── shared/ │ ├── auth.js # Authentication utilities │ ├── api-client.js # HTTP request wrapper with auth │ ├── websocket-client.js # WebSocket connection management │ ├── theme.js # Dark/light mode management │ ├── ui-utils.js # Toast, loading overlay, formatters │ └── constants.js # Shared constants and config ├── index/ │ ├── series-manager.js # Series loading, filtering, rendering │ ├── search.js # Search functionality │ ├── scan-manager.js # Library scan operations │ ├── config-manager.js # Configuration modal handling │ └── selection.js # Series/episode selection logic └── queue/ ├── queue-api.js # Queue API operations ├── queue-renderer.js # Render queue items (pending, active, etc.) └── progress-handler.js # Real-time progress updates ``` --- ### Task 5: Extract Shared JavaScript Utilities **Objective**: Create reusable utility modules used by both index and queue pages. **Steps**: 1. **Create constants.js**: - Extract API endpoint URLs - Extract localStorage keys - Extract any magic strings or numbers 2. **Create auth.js**: - Extract `checkAuth()` function - Extract `logout()` function - Extract `getAuthHeaders()` or token retrieval logic - Extract token storage/retrieval from localStorage 3. **Create api-client.js**: - Extract `fetchWithAuth()` wrapper function - Handle automatic token injection - Handle 401 redirect to login - Handle common error responses 4. **Create websocket-client.js**: - Extract WebSocket connection setup - Extract message handling dispatcher - Extract reconnection logic - Extract connection state management 5. **Create theme.js**: - Extract `initTheme()` function - Extract `toggleTheme()` function - Extract `setTheme()` function - Extract theme persistence to localStorage 6. **Create ui-utils.js**: - Extract `showToast()` function - Extract `showLoadingOverlay()` / `hideLoadingOverlay()` - Extract `formatBytes()` function - Extract `formatDuration()` function - Extract `formatDate()` function - Extract any other shared UI helpers **Pattern to Use (IIFE with Global Namespace)**: ```javascript // Example: shared/auth.js var AniWorld = window.AniWorld || {}; AniWorld.Auth = (function () { "use strict"; const TOKEN_KEY = "auth_token"; function getToken() { return localStorage.getItem(TOKEN_KEY); } function setToken(token) { localStorage.setItem(TOKEN_KEY, token); } function removeToken() { localStorage.removeItem(TOKEN_KEY); } function getAuthHeaders() { const token = getToken(); return token ? { Authorization: "Bearer " + token } : {}; } async function checkAuth() { // Implementation } function logout() { removeToken(); window.location.href = "/login"; } // Public API return { getToken: getToken, setToken: setToken, getAuthHeaders: getAuthHeaders, checkAuth: checkAuth, logout: logout, }; })(); ``` --- ### Task 6: Split app.js into Index Page Modules **Objective**: Break down `app.js` into focused modules for the index/library page. **Steps**: 1. **Create series-manager.js**: - Extract series loading from API - Extract series filtering logic - Extract series rendering/DOM updates - Extract series card click handlers 2. **Create search.js**: - Extract search input handling - Extract search API calls - Extract search results rendering - Extract search result selection 3. **Create scan-manager.js**: - Extract scan initiation logic - Extract scan progress overlay - Extract scan progress updates (WebSocket) - Extract scan completion handling 4. **Create config-manager.js**: - Extract config modal open/close - Extract config loading from API - Extract config form handling - Extract config save logic - Extract scheduler configuration - Extract backup management 5. **Create selection.js**: - Extract episode selection logic - Extract "select all" functionality - Extract selection state management - Extract "add to queue" from selection 6. **Update main app.js**: - Import all modules via script tags - Initialize all modules on DOMContentLoaded - Wire up event listeners to module functions - Keep this file as thin as possible (orchestration only) **Example main app.js structure**: ```javascript // filepath: src/server/web/static/js/app.js document.addEventListener("DOMContentLoaded", async function () { "use strict"; // Initialize shared modules AniWorld.Theme.init(); // Check authentication const isAuth = await AniWorld.Auth.checkAuth(); if (!isAuth) return; // Initialize page-specific modules AniWorld.SeriesManager.init(); AniWorld.Search.init(); AniWorld.ScanManager.init(); AniWorld.ConfigManager.init(); AniWorld.Selection.init(); // Initialize WebSocket for real-time updates AniWorld.WebSocketClient.init(); // Load initial data AniWorld.SeriesManager.loadSeries(); }); ``` --- ### Task 7: Split queue.js into Queue Page Modules **Objective**: Break down `queue.js` into focused modules for the queue page. **Steps**: 1. **Create queue-api.js**: - Extract `loadQueueStatus()` API call - Extract `startDownload()` API call - Extract `stopDownload()` API call - Extract `removeFromQueue()` API call - Extract `clearCompleted()` API call - Extract `clearFailed()` API call - Extract `retryFailed()` API call 2. **Create queue-renderer.js**: - Extract `renderActiveDownload()` function - Extract `renderPendingQueue()` function - Extract `renderCompletedList()` function - Extract `renderFailedList()` function - Extract `updateQueueCounts()` function - Extract queue item template generation 3. **Create progress-handler.js**: - Extract WebSocket message handling for queue - Extract progress bar updates - Extract status text updates - Extract ETA calculations - Extract speed display formatting 4. **Update main queue.js**: - Import all modules via script tags - Initialize all modules on DOMContentLoaded - Wire up button click handlers to API functions - Set up WebSocket handlers for progress - Keep this file as thin as possible **Example main queue.js structure**: ```javascript // filepath: src/server/web/static/js/queue.js document.addEventListener("DOMContentLoaded", async function () { "use strict"; // Initialize shared modules AniWorld.Theme.init(); // Check authentication const isAuth = await AniWorld.Auth.checkAuth(); if (!isAuth) return; // Initialize queue modules AniWorld.QueueApi.init(); AniWorld.QueueRenderer.init(); AniWorld.ProgressHandler.init(); // Initialize WebSocket with queue-specific handlers AniWorld.WebSocketClient.init({ onProgress: AniWorld.ProgressHandler.handleProgress, onQueueUpdate: AniWorld.QueueRenderer.refresh, }); // Load initial queue status await AniWorld.QueueApi.loadStatus(); AniWorld.QueueRenderer.refresh(); // Wire up UI buttons document .getElementById("start-btn") ?.addEventListener("click", AniWorld.QueueApi.startDownload); document .getElementById("stop-btn") ?.addEventListener("click", AniWorld.QueueApi.stopDownload); document .getElementById("clear-completed-btn") ?.addEventListener("click", AniWorld.QueueApi.clearCompleted); document .getElementById("clear-failed-btn") ?.addEventListener("click", AniWorld.QueueApi.clearFailed); }); ``` --- ### Task 8: Update HTML Templates **Objective**: Update templates to load the new modular JavaScript files. **Steps**: 1. **Update index.html**: - Add script tags for shared modules (in order) - Add script tags for index-specific modules (in order) - Keep main app.js as the last script - Ensure correct load order (dependencies first) ```html ``` 2. **Update queue.html**: - Add script tags for shared modules (in order) - Add script tags for queue-specific modules (in order) - Keep main queue.js as the last script ```html ``` 3. **Update login.html** (if applicable): - Only include shared modules needed for login - Likely just theme.js and minimal utilities --- ### Task 9: Verification and Testing **Objective**: Ensure all functionality works after refactoring. **Steps**: 1. **Start the server**: ```bash conda run -n AniWorld python -m uvicorn src.server.fastapi_app:app --host 127.0.0.1 --port 8000 --reload ``` 2. **Test Login Page**: - [ ] Page loads with correct styling - [ ] Dark/light mode toggle works - [ ] Login form submits correctly - [ ] Error messages display correctly - [ ] Successful login redirects to index 3. **Test Index Page**: - [ ] Page loads with correct styling - [ ] Series list loads and displays - [ ] Series filtering works - [ ] Search functionality works - [ ] Series selection works - [ ] Episode selection works - [ ] Add to queue works - [ ] Scan library works - [ ] Scan progress displays - [ ] Config modal opens/closes - [ ] Config saves correctly - [ ] Dark/light mode toggle works - [ ] Logout works - [ ] WebSocket connection established 4. **Test Queue Page**: - [ ] Page loads with correct styling - [ ] Queue status loads - [ ] Pending items display - [ ] Active download displays - [ ] Completed items display - [ ] Failed items display - [ ] Start download works - [ ] Stop download works - [ ] Remove from queue works - [ ] Clear completed works - [ ] Clear failed works - [ ] Retry failed works - [ ] Progress updates in real-time - [ ] Dark/light mode toggle works - [ ] WebSocket connection established 5. **Test Responsive Design**: - [ ] All pages work on mobile viewport - [ ] All pages work on tablet viewport - [ ] All pages work on desktop viewport 6. **Browser Console Check**: - [ ] No JavaScript errors in console - [ ] No 404 errors for static files - [ ] No CSS loading errors --- ### Task 10: Cleanup and Documentation **Objective**: Finalize the refactoring with cleanup and documentation. **Steps**: 1. **Remove backup files** (if any were created) 2. **Verify file sizes**: - No file should exceed 500 lines - If any file exceeds, split further 3. **Add file headers**: - Add comment header to each new file explaining its purpose ```javascript /** * AniWorld - Series Manager Module * * Handles loading, filtering, and rendering of anime series * on the index/library page. * * Dependencies: auth.js, api-client.js, ui-utils.js */ ``` ```css /** * AniWorld - Button Styles * * All button-related styles including variants, * states, and sizes. */ ``` 4. **Update infrastructure.md** (if exists): - Document new file structure - Document module dependencies 5. **Commit changes**: ```bash git add . git commit -m "refactor: split CSS and JS into modular files (SRP)" ``` --- ### Summary of New Files **CSS Files (14 files)**: - `css/styles.css` (entry point with imports) - `css/base/variables.css` - `css/base/reset.css` - `css/base/typography.css` - `css/components/buttons.css` - `css/components/cards.css` - `css/components/forms.css` - `css/components/modals.css` - `css/components/navigation.css` - `css/components/progress.css` - `css/components/notifications.css` - `css/components/tables.css` - `css/pages/login.css` - `css/pages/index.css` - `css/pages/queue.css` - `css/utilities/animations.css` - `css/utilities/responsive.css` - `css/utilities/helpers.css` **JavaScript Files (15 files)**: - `js/app.js` (entry point for index) - `js/queue.js` (entry point for queue) - `js/shared/constants.js` - `js/shared/auth.js` - `js/shared/api-client.js` - `js/shared/websocket-client.js` - `js/shared/theme.js` - `js/shared/ui-utils.js` - `js/index/series-manager.js` - `js/index/search.js` - `js/index/scan-manager.js` - `js/index/config-manager.js` - `js/index/selection.js` - `js/queue/queue-api.js` - `js/queue/queue-renderer.js` - `js/queue/progress-handler.js` --- ### Important Notes 1. **IIFE Pattern**: Use the IIFE (Immediately Invoked Function Expression) pattern with a global namespace (`AniWorld`) for browser compatibility without requiring a build step. 2. **No Build Tools Required**: This approach uses native CSS `@import` and multiple `