27 KiB
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
# 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
- Incremental Development: Implement features incrementally, testing each component thoroughly before moving to the next
- Code Review: Review all generated code for adherence to project standards
- Documentation: Document all public APIs and complex logic
- Testing: Maintain test coverage above 80% for all new code
- Performance: Profile and optimize critical paths, especially download and streaming operations
- Security: Regular security audits and dependency updates
- Monitoring: Implement comprehensive monitoring and alerting
- 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/, andutilities/directories styles.cssnow 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
AniWorldnamespace 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 JSqueue.html- Updated script tags for modular JStest_static_files.py- Updated tests for modular architecturetest_template_integration.py- Updated tests for new JS structureARCHITECTURE.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:
- Open and read
src/server/web/static/css/styles.css - Open and read
src/server/web/static/js/app.js - Open and read
src/server/web/static/js/queue.js - Open and read
src/server/web/templates/index.html - Open and read
src/server/web/templates/queue.html - Open and read
src/server/web/templates/login.html - Document all CSS sections (look for comment headers)
- Document all JavaScript functions and their dependencies
- 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:
- Create directory:
src/server/web/static/css/base/ - Create directory:
src/server/web/static/css/components/ - Create directory:
src/server/web/static/css/pages/ - 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:
-
Extract variables.css:
- Find all
:rootCSS custom properties - Extract color variables, font variables, spacing variables
- Include dark mode variables (
.dark-modeor[data-theme="dark"])
- Find all
-
Extract reset.css:
- Extract
*,body,htmlbase resets - Extract box-sizing rules
- Extract default margin/padding resets
- Extract
-
Extract typography.css:
- Extract
h1-h6styles - Extract paragraph, link, text styles
- Extract font-related utility classes
- Extract
-
Extract buttons.css:
- Find all
.btn,button,.buttonrelated styles - Include hover, active, disabled states
- Include button variants (primary, secondary, danger, etc.)
- Find all
-
Extract cards.css:
- Extract
.card,.panel,.boxrelated styles - Include card headers, bodies, footers
- Extract
-
Extract forms.css:
- Extract
input,select,textareastyles - Extract
.form-group,.form-controlstyles - Extract validation states (error, success)
- Extract
-
Extract modals.css:
- Extract
.modal,.overlay,.dialogstyles - Include backdrop styles
- Include modal animations
- Extract
-
Extract navigation.css:
- Extract
header,nav,.navbarstyles - Extract menu and navigation link styles
- Extract
-
Extract progress.css:
- Extract
.progress,.progress-barstyles - Extract loading spinners and indicators
- Extract
-
Extract notifications.css:
- Extract
.toast,.alert,.notificationstyles - Include success, error, warning, info variants
- Extract
-
Extract tables.css:
- Extract
table,.tablestyles - Extract list styles if table-like
- Extract
-
Extract page-specific styles:
login.css: Styles only used on login pageindex.css: Styles only used on index/library page (series cards, search)queue.css: Styles only used on queue page (queue items, download status)
-
Extract animations.css:
- Extract all
@keyframesrules - Extract animation utility classes
- Extract all
-
Extract responsive.css:
- Extract all
@mediaqueries - Organize by breakpoint
- Extract all
-
Extract helpers.css:
- Extract utility classes (.hidden, .flex, .text-center, etc.)
- Extract spacing utilities
-
Update main styles.css:
- Replace all content with
@importstatements - Order imports correctly (variables first, then reset, then components)
- Replace all content with
Import Order in styles.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:
- Create directory:
src/server/web/static/js/shared/ - Create directory:
src/server/web/static/js/index/ - 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:
-
Create constants.js:
- Extract API endpoint URLs
- Extract localStorage keys
- Extract any magic strings or numbers
-
Create auth.js:
- Extract
checkAuth()function - Extract
logout()function - Extract
getAuthHeaders()or token retrieval logic - Extract token storage/retrieval from localStorage
- Extract
-
Create api-client.js:
- Extract
fetchWithAuth()wrapper function - Handle automatic token injection
- Handle 401 redirect to login
- Handle common error responses
- Extract
-
Create websocket-client.js:
- Extract WebSocket connection setup
- Extract message handling dispatcher
- Extract reconnection logic
- Extract connection state management
-
Create theme.js:
- Extract
initTheme()function - Extract
toggleTheme()function - Extract
setTheme()function - Extract theme persistence to localStorage
- Extract
-
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
- Extract
Pattern to Use (IIFE with Global Namespace):
// 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:
-
Create series-manager.js:
- Extract series loading from API
- Extract series filtering logic
- Extract series rendering/DOM updates
- Extract series card click handlers
-
Create search.js:
- Extract search input handling
- Extract search API calls
- Extract search results rendering
- Extract search result selection
-
Create scan-manager.js:
- Extract scan initiation logic
- Extract scan progress overlay
- Extract scan progress updates (WebSocket)
- Extract scan completion handling
-
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
-
Create selection.js:
- Extract episode selection logic
- Extract "select all" functionality
- Extract selection state management
- Extract "add to queue" from selection
-
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:
// 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:
-
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
- Extract
-
Create queue-renderer.js:
- Extract
renderActiveDownload()function - Extract
renderPendingQueue()function - Extract
renderCompletedList()function - Extract
renderFailedList()function - Extract
updateQueueCounts()function - Extract queue item template generation
- Extract
-
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
-
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:
// 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:
-
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)
<!-- Shared Modules --> <script src="/static/js/shared/constants.js"></script> <script src="/static/js/shared/auth.js"></script> <script src="/static/js/shared/api-client.js"></script> <script src="/static/js/shared/websocket-client.js"></script> <script src="/static/js/shared/theme.js"></script> <script src="/static/js/shared/ui-utils.js"></script> <!-- Index Page Modules --> <script src="/static/js/index/series-manager.js"></script> <script src="/static/js/index/search.js"></script> <script src="/static/js/index/scan-manager.js"></script> <script src="/static/js/index/config-manager.js"></script> <script src="/static/js/index/selection.js"></script> <!-- Main Entry Point --> <script src="/static/js/app.js"></script> -
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
<!-- Shared Modules --> <script src="/static/js/shared/constants.js"></script> <script src="/static/js/shared/auth.js"></script> <script src="/static/js/shared/api-client.js"></script> <script src="/static/js/shared/websocket-client.js"></script> <script src="/static/js/shared/theme.js"></script> <script src="/static/js/shared/ui-utils.js"></script> <!-- Queue Page Modules --> <script src="/static/js/queue/queue-api.js"></script> <script src="/static/js/queue/queue-renderer.js"></script> <script src="/static/js/queue/progress-handler.js"></script> <!-- Main Entry Point --> <script src="/static/js/queue.js"></script> -
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:
-
Start the server:
conda run -n AniWorld python -m uvicorn src.server.fastapi_app:app --host 127.0.0.1 --port 8000 --reload -
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
-
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
-
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
-
Test Responsive Design:
- All pages work on mobile viewport
- All pages work on tablet viewport
- All pages work on desktop viewport
-
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:
-
Remove backup files (if any were created)
-
Verify file sizes:
- No file should exceed 500 lines
- If any file exceeds, split further
-
Add file headers:
- Add comment header to each new file explaining its purpose
/** * 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 *//** * AniWorld - Button Styles * * All button-related styles including variants, * states, and sizes. */ -
Update infrastructure.md (if exists):
- Document new file structure
- Document module dependencies
-
Commit changes:
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.csscss/base/reset.csscss/base/typography.csscss/components/buttons.csscss/components/cards.csscss/components/forms.csscss/components/modals.csscss/components/navigation.csscss/components/progress.csscss/components/notifications.csscss/components/tables.csscss/pages/login.csscss/pages/index.csscss/pages/queue.csscss/utilities/animations.csscss/utilities/responsive.csscss/utilities/helpers.css
JavaScript Files (15 files):
js/app.js(entry point for index)js/queue.js(entry point for queue)js/shared/constants.jsjs/shared/auth.jsjs/shared/api-client.jsjs/shared/websocket-client.jsjs/shared/theme.jsjs/shared/ui-utils.jsjs/index/series-manager.jsjs/index/search.jsjs/index/scan-manager.jsjs/index/config-manager.jsjs/index/selection.jsjs/queue/queue-api.jsjs/queue/queue-renderer.jsjs/queue/progress-handler.js
Important Notes
-
IIFE Pattern: Use the IIFE (Immediately Invoked Function Expression) pattern with a global namespace (
AniWorld) for browser compatibility without requiring a build step. -
No Build Tools Required: This approach uses native CSS
@importand multiple<script>tags, avoiding the need for bundlers like Webpack or Vite. -
Load Order Matters: Scripts must be loaded in dependency order. Shared modules first, then page-specific modules, then the main entry point.
-
Backward Compatibility: All existing HTML element IDs and class names must be preserved. Only the JavaScript and CSS organization changes, not the API.
-
Incremental Approach: Complete one task fully before moving to the next. Verify functionality after each major step.
-
Rollback Plan: Keep the original files until all verification is complete. Only delete originals after confirming everything works.