# Research: Christmas Checker Website **Date**: 2025-11-11 **Feature**: Christmas Checker Website **Branch**: 001-christmas-checker ## Research Questions Based on the Technical Context, the following areas required research: 1. Best approach for minimal Java HTTP server (no frameworks) 2. JavaScript snow animation best practices for performance 3. Docker Compose setup for Java + static files 4. Date handling in Java for timezone-aware date comparison 5. Frontend-backend communication patterns ## Findings ### 1. Minimal Java HTTP Server **Decision**: Use `com.sun.net.httpserver.HttpServer` from Java standard library **Rationale**: - Built into Java SE since Java 6, no external dependencies - Sufficient for simple REST endpoints - Lightweight and easy to configure - Supports both HTTP and HTTPS - Perfect for minimal dependency requirement **Alternatives Considered**: - **Spring Boot**: Rejected - too heavy for this simple use case, violates "minimal dependencies" requirement - **Jetty embedded**: Rejected - external dependency, overkill for single endpoint - **Undertow**: Rejected - external dependency - **Raw sockets**: Rejected - too low-level, would require manual HTTP parsing **Implementation Approach**: ```java HttpServer server = HttpServer.create(new InetSocketAddress(8080), 0); server.createContext("/api/christmas", new ChristmasHandler()); server.start(); ``` ### 2. JavaScript Snow Animation **Decision**: Use Canvas API with RequestAnimationFrame for snow particles **Rationale**: - Canvas provides excellent performance for particle effects - RequestAnimationFrame ensures smooth 60fps animation - No external libraries needed (vanilla JS) - Can easily optimize particle count based on screen size - Respects `prefers-reduced-motion` for accessibility **Alternatives Considered**: - **CSS animations**: Rejected - limited control over particle physics, harder to optimize particle count - **SVG**: Rejected - poor performance with many particles (hundreds of snowflakes) - **WebGL**: Rejected - overkill for 2D particles, complexity violation - **Libraries (particles.js, etc.)**: Rejected - violates "minimal dependencies" **Implementation Approach**: - Create canvas overlay covering full viewport - Generate 100-200 snowflake particles (adjust based on screen size) - Use simple physics: constant downward velocity + slight horizontal wobble - Recycle particles when they fall off screen - Clear and redraw on each frame using requestAnimationFrame **Performance Optimizations**: - Limit particle count on mobile (50-100 vs 150-200 on desktop) - Use simple circles instead of complex shapes - Batch drawing operations - Pause animation when page not visible (Page Visibility API) ### 3. Docker Compose Architecture **Decision**: Two-service architecture with nginx for frontend, Java for backend **Rationale**: - Separation of concerns: static files vs dynamic API - nginx excellent for serving static files efficiently - Java service only handles API endpoint - Both services lightweight and minimal - Easy to scale independently if needed **Alternatives Considered**: - **Single Java service serving both**: Rejected - mixing concerns, Java not optimized for static file serving - **Node.js for frontend**: Rejected - introduces another language/runtime unnecessarily - **Apache instead of nginx**: Rejected - nginx lighter and more modern **Docker Compose Structure**: ```yaml services: backend: build: ./docker/backend ports: - "8080:8080" frontend: build: ./docker/frontend ports: - "80:80" depends_on: - backend ``` ### 4. Java Date/Time Handling **Decision**: Use `java.time.LocalDate` for date comparisons **Rationale**: - Modern Java 8+ time API (java.time package) - Immutable and thread-safe - Clear separation of date (LocalDate) vs time (LocalTime) - Easy comparison: `LocalDate.now().getMonthValue() == 12 && LocalDate.now().getDayOfMonth() == 25` **Alternatives Considered**: - **java.util.Date**: Rejected - deprecated, mutable, poor API design - **java.util.Calendar**: Rejected - verbose, mutable, confusing API - **Joda-Time**: Rejected - external dependency, java.time is standard now **Implementation Approach**: ```java LocalDate today = LocalDate.now(); boolean isChristmas = today.getMonthValue() == 12 && today.getDayOfMonth() == 25; ``` **Timezone Consideration**: - Backend uses server's local timezone (acceptable for simple deployment) - Frontend could alternatively check date client-side for user's local timezone - Decision: Frontend checks date client-side using JavaScript `Date()` object - Backend endpoint becomes optional/redundant but kept for architecture demonstration ### 5. Frontend-Backend Communication **Decision**: Simple REST GET endpoint returning JSON **Rationale**: - RESTful pattern is standard and well-understood - GET request is idempotent and cacheable - JSON is lightweight and universally supported - CORS headers allow cross-origin requests if needed **Endpoint Design**: ``` GET /api/christmas Response: { "isChristmas": true|false, "date": "2025-12-25" } ``` **Alternatives Considered**: - **WebSocket**: Rejected - overkill for simple one-time check - **GraphQL**: Rejected - too complex for single field - **Plain text response**: Rejected - JSON is more structured and extensible **CORS Configuration**: - Allow all origins (`Access-Control-Allow-Origin: *`) since this is a public API - No authentication needed ### 6. Client-Side vs Server-Side Date Check **Decision**: Implement BOTH with client-side as primary **Rationale**: - Client-side JS can check date using user's local timezone (matches spec requirement FR-001) - Server-side endpoint demonstrates backend capability and provides fallback - Offline capability: once page loads, works without backend - Simplifies architecture while meeting all requirements **Implementation Strategy**: 1. Frontend loads and immediately checks date client-side 2. Displays result without waiting for backend 3. Backend endpoint available but not strictly necessary for functionality 4. This approach satisfies the "offline-capable" requirement from spec ## Technology Stack Summary | Component | Technology | Version | Rationale | |-----------|-----------|---------|-----------| | Backend Language | Java | 21 (LTS) | User requirement, minimal dependencies | | Backend HTTP | com.sun.net.httpserver | Standard library | No external dependencies | | Backend Date/Time | java.time.LocalDate | Standard library | Modern, immutable, clear API | | Frontend HTML/CSS/JS | Vanilla (no frameworks) | ES6+ | User requirement: minimal dependencies | | Snow Animation | Canvas + RequestAnimationFrame | Browser standard | Best performance for particles | | Frontend Server | nginx | alpine | Lightweight static file serving | | Container Platform | Docker + Docker Compose | Latest | User requirement | | Testing | JUnit 5 | 5.10+ | Standard Java testing (if tests requested) | ## Open Questions Resolved All NEEDS CLARIFICATION items from Technical Context have been resolved: ✅ HTTP server approach: Java standard library HttpServer ✅ Snow animation: Canvas API with RequestAnimationFrame ✅ Docker structure: Two services (nginx + Java) ✅ Date handling: java.time.LocalDate ✅ Frontend-backend: REST JSON API (optional, client-side primary) ## Next Steps Proceed to Phase 1: 1. Generate data-model.md (minimal - just Date and ChristmasStatus entities) 2. Generate contracts/api.md (REST endpoint specification) 3. Generate quickstart.md (how to build and run) 4. Update agent context files