7.4 KiB
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:
- Best approach for minimal Java HTTP server (no frameworks)
- JavaScript snow animation best practices for performance
- Docker Compose setup for Java + static files
- Date handling in Java for timezone-aware date comparison
- 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:
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-motionfor 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:
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:
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:
- Frontend loads and immediately checks date client-side
- Displays result without waiting for backend
- Backend endpoint available but not strictly necessary for functionality
- 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:
- Generate data-model.md (minimal - just Date and ChristmasStatus entities)
- Generate contracts/api.md (REST endpoint specification)
- Generate quickstart.md (how to build and run)
- Update agent context files