Aniworld/docs/instructions.md

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

  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:

/* 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):

// 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:

// 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:

// 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)
    <!-- 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>
    
  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
    <!-- 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>
    
  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:

    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
    /**
     * 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.
     */
    
  4. Update infrastructure.md (if exists):

    • Document new file structure
    • Document module dependencies
  5. 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.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 <script> tags, avoiding the need for bundlers like Webpack or Vite.

  3. Load Order Matters: Scripts must be loaded in dependency order. Shared modules first, then page-specific modules, then the main entry point.

  4. Backward Compatibility: All existing HTML element IDs and class names must be preserved. Only the JavaScript and CSS organization changes, not the API.

  5. Incremental Approach: Complete one task fully before moving to the next. Verify functionality after each major step.

  6. Rollback Plan: Keep the original files until all verification is complete. Only delete originals after confirming everything works.