# SportPulse - Project Tasks

Last updated: 2026-01-26

This document tracks all tasks for the SportPulse Widget API and Admin Tool projects.

**Projects covered:**
- **SportPulse Widget API** (`sportpulse-internal-apis`) - Tasks #1-18
- **SportPulse Admin Tool** (`sportpulse-admin`) - Phases 1-5

---

## Status Legend

| Status | Meaning |
|--------|---------|
| `NOT STARTED` | Feature/fix has not been worked on |
| `PARTIAL` | Some work done but incomplete |
| `BLOCKED` | Waiting on external dependency or decision |

---

## Critical Issues

These should be addressed before production deployment.

### 1. Empty Participants Data
- **Status**: `NOT STARTED`
- **Priority**: Critical
- **File**: `sportpulse_widgets_seed.json`
- **Description**: The seed file contains 0 participants despite the API fully supporting the participants endpoint. The `/leagues/{leagueId}/participants` endpoint works but returns empty results.
- **Action Required**: Populate the `participants` array in the seed file with teams, players, and drivers corresponding to existing sports and leagues.
- **Acceptance Criteria**:
  - [ ] Add team participants for soccer, basketball, hockey, baseball, american-football leagues
  - [ ] Add driver participants for motorsport leagues (F1, NASCAR)
  - [ ] Each participant should have: `id`, `leagueId`, `participantName`, `participantType` (TEAM/DRIVER/PLAYER), `teamLogo`, `isActive`

### 2. Duplicate Mongoose Index Warnings
- **Status**: `NOT STARTED`
- **Priority**: Critical
- **Files**:
  - `src/models/sport.model.ts`
  - `src/models/api-key.model.ts`
- **Description**: Mongoose throws warnings about duplicate schema indexes. Indexes are declared using both `index: true` in the schema field and `schema.index()` method.
- **Action Required**: Remove duplicate index declarations - keep only one method.
- **Acceptance Criteria**:
  - [ ] No Mongoose warnings on server startup
  - [ ] No Mongoose warnings when running tests

### 3. No Seed Data Validation
- **Status**: `NOT STARTED`
- **Priority**: Critical
- **File**: `scripts/seed-data.ts`
- **Description**: The seed script inserts data into MongoDB without validating the structure of `sportpulse_widgets_seed.json` first. Invalid data could corrupt the database.
- **Action Required**: Add Zod validation using the existing `seedDataSchema` before inserting data.
- **Acceptance Criteria**:
  - [ ] Seed script validates JSON structure before database operations
  - [ ] Clear error messages if validation fails
  - [ ] Script exits with non-zero code on validation failure

---

## High Priority

Should be completed for production readiness.

### 4. No Pagination Support
- **Status**: `NOT STARTED`
- **Priority**: High
- **Files**:
  - `src/services/*.service.ts`
  - `src/controllers/*.controller.ts`
  - `src/validation/schemas.ts`
  - `openapi.yaml`
- **Description**: All list endpoints return complete datasets without pagination. This is a performance risk for large datasets.
- **Affected Endpoints**:
  - `GET /sports`
  - `GET /sports/:sportId/leagues`
  - `GET /leagues/:leagueId/participants`
  - `GET /leagues/:leagueId/widget-types` (returns 61+ items)
  - `GET /templates` (returns 105+ items)
- **Action Required**: Add `page` and `limit` query parameters with metadata in responses.
- **Acceptance Criteria**:
  - [ ] All list endpoints support `page` (default: 1) and `limit` (default: 20, max: 100) parameters
  - [ ] Responses include `meta` object with `total`, `page`, `limit`, `totalPages`
  - [ ] OpenAPI spec updated with pagination parameters
  - [ ] Tests updated for pagination

### 5. No Rate Limiting
- **Status**: `NOT STARTED`
- **Priority**: High
- **File**: New middleware needed - `src/middleware/rate-limit.middleware.ts`
- **Description**: No rate limiting exists. Anyone with a valid API key can make unlimited requests, risking DoS.
- **Action Required**: Implement rate limiting middleware (consider `express-rate-limit` package).
- **Acceptance Criteria**:
  - [ ] Rate limit middleware added (suggest: 100 requests per minute per API key)
  - [ ] Returns 429 Too Many Requests when limit exceeded
  - [ ] Rate limit headers included in responses (`X-RateLimit-Limit`, `X-RateLimit-Remaining`)
  - [ ] Different limits configurable per API key tier (future enhancement)

### 6. No Request Size Limits
- **Status**: `NOT STARTED`
- **Priority**: High
- **File**: `src/app.ts`
- **Description**: No explicit limits on request body size configured in Express.
- **Action Required**: Configure Express body parser limits.
- **Acceptance Criteria**:
  - [ ] JSON body limit set (suggest: 10kb for this read-only API)
  - [ ] URL-encoded limit set
  - [ ] Returns 413 Payload Too Large when exceeded

### 7. Environment Variable Validation
- **Status**: `PARTIAL`
- **Priority**: High
- **File**: `src/config/env.ts`
- **Description**: Basic config exists but no validation that required environment variables are set correctly.
- **Action Required**: Add startup validation for required env vars.
- **Acceptance Criteria**:
  - [ ] Server fails fast with clear error if required vars missing
  - [ ] Validate `API_PORT` is a valid port number
  - [ ] Validate `MONGODB_URI` format when `USE_JSON_STORE=false`
  - [ ] Log which configuration mode is active on startup

### 8. Missing Sports Widget URLs
- **Status**: `BLOCKED`
- **Priority**: High
- **File**: `sportpulse_widgets_seed.json`
- **Description**: Several sports/leagues have placeholder entries in the seed data without actual widget URLs. These were added as placeholders from the `Sports Widget URLs - 2026-01-26.numbers` file.
- **Blocked By**: Waiting for widget URLs to be provided by the SportPulse team.
- **Missing URLs**:

| Sport | League | Widgets Needed |
|-------|--------|----------------|
| Soccer | MLS | standings, schedule, results, match-events |
| Motorsport | NASCAR | standings, schedule, lineup, results |
| Basketball | NBA | playoffs-bracket (dark), awards (dark), season-leaders (dark), league-leaders (dark) |

- **Action Required**: Once URLs are provided, update `sportpulse_widgets_seed.json` with the actual URLs.
- **Acceptance Criteria**:
  - [ ] All MLS widgets have valid dark/light theme URLs
  - [ ] All NASCAR widgets have valid dark/light theme URLs
  - [ ] All NBA placeholder widgets have dark theme URLs added
  - [ ] Templates have `isActive: true` once URLs are populated
  - [ ] API returns valid embed codes for all widgets

---

## Medium Priority

Improvements for code quality and maintainability.

### 9. Enhanced Request Logging
- **Status**: `PARTIAL`
- **Priority**: Medium
- **File**: `src/middleware/request-logger.middleware.ts`
- **Current State**: Only logs HTTP method and path with timestamp.
- **Missing Features**:
  - Response status code
  - Request duration (ms)
  - Request ID for tracing
  - Structured JSON logging for production
- **Action Required**: Enhance logging middleware.
- **Acceptance Criteria**:
  - [ ] Log format: `[timestamp] [requestId] METHOD /path STATUS duration_ms`
  - [ ] Add `X-Request-ID` header to responses
  - [ ] Optional JSON format when `NODE_ENV=production`

### 10. MongoDB Mode Test Coverage
- **Status**: `NOT STARTED`
- **Priority**: Medium
- **File**: `src/routes/api.test.ts`, `src/services/*.test.ts`
- **Description**: All 49 tests use JSON store mode. No tests verify MongoDB mode works correctly.
- **Action Required**: Add test suite for MongoDB mode.
- **Acceptance Criteria**:
  - [ ] Separate test suite or test flag for MongoDB mode
  - [ ] Tests use test database (not production)
  - [ ] Database cleaned up after tests
  - [ ] CI pipeline can run both test modes

### 11. Validation Schema Field Name Consistency
- **Status**: `NOT STARTED`
- **Priority**: Medium
- **Files**:
  - `src/validation/schemas.ts`
  - `src/data/json-store.ts`
- **Description**: Validation schemas use different field names than API responses (e.g., `teamLogoUrl` vs `teamLogo`). Works due to mapper functions but creates confusion.
- **Action Required**: Align field names across validation schemas, models, and responses.
- **Acceptance Criteria**:
  - [ ] Consistent field naming convention documented
  - [ ] Validation schemas match API response structure
  - [ ] No silent field transformations

### 12. Comprehensive Error Handling
- **Status**: `PARTIAL`
- **Priority**: Medium
- **File**: `src/middleware/error.middleware.ts`
- **Current State**: Handles 404s and Zod validation errors.
- **Missing**:
  - Database connection error recovery
  - Timeout handling
  - Request ID in error responses
  - Graceful degradation
- **Action Required**: Enhance error middleware.
- **Acceptance Criteria**:
  - [ ] All errors include `requestId` for debugging
  - [ ] Database errors return 503 Service Unavailable
  - [ ] Timeout errors handled gracefully
  - [ ] Error responses follow consistent format

### 13. Complete OpenAPI Specification
- **Status**: `PARTIAL`
- **Priority**: Medium
- **File**: `openapi.yaml`
- **Description**: OpenAPI spec may be incomplete - missing detailed response examples and some field descriptions.
- **Action Required**: Review and complete the specification.
- **Acceptance Criteria**:
  - [ ] All endpoints have complete request/response examples
  - [ ] All fields have descriptions
  - [ ] Error response schemas documented
  - [ ] Spec validates against OpenAPI 3.0 standard

### 14. Widget Screenshot Capture Script
- **Status**: `NOT STARTED`
- **Priority**: Medium
- **File**: New script needed - `scripts/capture-widget-screenshots.ts`
- **Description**: Create an automated script to capture screenshots of all sports widgets for documentation, thumbnails, and preview purposes.
- **Requirements**:
  - Capture each widget URL from the seed data
  - Generate screenshots in FullHD resolution (1920x1080)
  - Support two viewport aspect ratios:
    - **16:9 (landscape)**: 1920x1080
    - **9:16 (portrait)**: 1080x1920
  - Save screenshots with descriptive filenames
- **Suggested Implementation**:
  - Use Puppeteer or Playwright for headless browser automation
  - Read widget URLs from `sportpulse_widgets_seed.json`
  - Skip placeholders (entries with null URLs)
  - Output to `screenshots/` directory
- **Action Required**: Write and test the screenshot capture script.
- **Acceptance Criteria**:
  - [ ] Script reads all widget URLs from seed data
  - [ ] Generates 16:9 landscape screenshots (1920x1080) for each widget
  - [ ] Generates 9:16 portrait screenshots (1080x1920) for each widget
  - [ ] Skips widgets without URLs (placeholders)
  - [ ] Saves files with naming convention: `{sport}-{league}-{widget}-{theme}-{aspect}.png`
  - [ ] Handles errors gracefully (timeout, network issues)
  - [ ] Outputs summary of captured vs skipped widgets
  - [ ] Can be run via `npm run capture-screenshots`

**Example Output Structure**:
```
screenshots/
├── 16x9/
│   ├── soccer-premier-league-standings-dark-16x9.png
│   ├── soccer-premier-league-standings-light-16x9.png
│   ├── nfl-standings-afc-dark-16x9.png
│   └── ...
└── 9x16/
    ├── soccer-premier-league-standings-dark-9x16.png
    ├── soccer-premier-league-standings-light-9x16.png
    ├── nfl-standings-afc-dark-9x16.png
    └── ...
```

---

## Low Priority

Nice-to-have improvements.

### 15. Health Check Endpoint Enhancement
- **Status**: `PARTIAL`
- **Priority**: Low
- **File**: `src/app.ts`
- **Current State**: Basic `/health` endpoint exists.
- **Missing**: Database connectivity check, version info, uptime.
- **Acceptance Criteria**:
  - [ ] Returns database connection status
  - [ ] Returns API version from package.json
  - [ ] Returns server uptime
  - [ ] Returns data store mode (JSON/MongoDB)

### 16. Structured Logging for Production
- **Status**: `NOT STARTED`
- **Priority**: Low
- **Description**: Add proper logging library (e.g., `pino` or `winston`) for production-ready logging.
- **Acceptance Criteria**:
  - [ ] JSON log format in production
  - [ ] Log levels (debug, info, warn, error)
  - [ ] Configurable log level via environment variable

### 17. Performance Metrics
- **Status**: `NOT STARTED`
- **Priority**: Low
- **Description**: Add basic performance monitoring.
- **Acceptance Criteria**:
  - [ ] Request duration tracking
  - [ ] Optional metrics endpoint (`/metrics`)
  - [ ] Memory usage monitoring

### 18. Documentation Improvements
- **Status**: `PARTIAL`
- **Priority**: Low
- **Missing Documentation**:
  - [ ] Deployment guide (Docker production setup)
  - [ ] Troubleshooting guide
  - [ ] Security best practices
  - [ ] API versioning strategy

---

## Future Features - Admin Tool

> **Reference PRD**: `SPORTPULSE_ADMIN_TOOL.md`
>
> **Note**: The Admin Tool is a **separate project** (`sportpulse-admin`) - not part of this API codebase.

### Tech Stack (Admin Tool)
- **Frontend**: React 18+ / TypeScript / SCSS / Vite
- **Backend**: Node.js 20+ / Express 5.x / TypeScript
- **Storage**: AWS S3 + CloudFront CDN
- **Auth**: JWT + Email/Password

---

### Phase 1: Foundation
- **Status**: `NOT STARTED`
- **Priority**: P0

| Task | Description | Status |
|------|-------------|--------|
| Project setup | Initialize frontend (React/Vite) + backend (Express/TS) repos | [ ] |
| Authentication system | JWT-based auth with refresh tokens | [ ] |
| Database connections | Connect to Widget Config DB + Sports Data DB | [ ] |
| Base UI components | Setup component library (shadcn/ui or similar) | [ ] |
| File upload infrastructure | S3 bucket setup, upload service, CDN config | [ ] |

---

### Phase 2: Widget Config CRUD
- **Status**: `NOT STARTED`
- **Priority**: P0

| Task | Description | Status |
|------|-------------|--------|
| Sports management | List, create, edit, delete sports + icon upload | [ ] |
| Leagues management | List, create, edit, delete leagues + logo upload | [ ] |
| Participants management | Teams/Players/Drivers CRUD + logo upload | [ ] |
| Widget Types management | Full CRUD for widget types | [ ] |

**API Endpoints Required**:
```
POST/PUT/DELETE /api/admin/sports
POST/PUT/DELETE /api/admin/sports/:sportId/leagues
POST/PUT/DELETE /api/admin/leagues/:leagueId/participants
POST/PUT/DELETE /api/admin/leagues/:leagueId/widget-types
```

---

### Phase 3: Templates Module
- **Status**: `NOT STARTED`
- **Priority**: P0

| Task | Description | Status |
|------|-------------|--------|
| Templates list/gallery view | Display templates with thumbnails, filters | [ ] |
| Template CRUD operations | Create, edit, delete templates | [ ] |
| Thumbnail uploads | Dark/light theme thumbnail upload | [ ] |
| Embed code generator | Generate iframe snippets with copy button | [ ] |
| Template preview | Inline iframe preview of widgets | [ ] |
| Featured toggle | Mark/unmark templates as featured | [ ] |

**API Endpoints Required**:
```
GET/POST/PUT/DELETE /api/admin/templates
POST /api/admin/templates/:id/thumbnail-dark
POST /api/admin/templates/:id/thumbnail-light
```

---

### Phase 4: Sports Data Module
- **Status**: `NOT STARTED`
- **Priority**: P1
- **Dependency**: Requires Sports Data DB schema discovery first

| Task | Description | Status |
|------|-------------|--------|
| **Pre-task: DB Discovery** | Document existing Sports Data DB schema | [ ] |
| Team data editor | Edit team info (fullName, shortName, abbreviation, logo) | [ ] |
| Schedule/event management | Calendar view, create/edit/delete events | [ ] |
| Score entry system | Enter scores with period breakdown | [ ] |
| Live score entry | Real-time score updates during games | [ ] |

**API Endpoints Required**:
```
GET/PUT /api/admin/sports-data/teams
GET/POST/PUT/DELETE /api/admin/sports-data/events
GET/PUT /api/admin/sports-data/scores
```

---

### Phase 5: Polish & Deploy
- **Status**: `NOT STARTED`
- **Priority**: P1

| Task | Description | Status |
|------|-------------|--------|
| Role-based access control | Super Admin, Content Admin, Data Editor, Viewer roles | [ ] |
| Audit logging | Track all data modifications with user info | [ ] |
| Sync button with confirmation | Global sync with change tracking & confirmation modal | [ ] |
| Performance optimization | Caching, lazy loading, pagination | [ ] |
| Testing & QA | Unit tests, integration tests, E2E tests | [ ] |
| Production deployment | Docker, CI/CD, environment setup | [ ] |

---

### Admin Tool - File Upload Specifications

| Asset Type | Recommended Size | Max Size | Formats |
|------------|------------------|----------|---------|
| Sport Icon | 64x64 px | 256KB | PNG, SVG |
| League Logo | 200x200 px | 512KB | PNG, SVG |
| Team Logo | 512x512 px | 512KB | PNG, JPG, SVG |
| Template Thumbnail | 960x540 px | 1MB | PNG, JPG |
| Template Preview | 1920x1080 px | 2MB | PNG, JPG |

---

### Admin Tool - User Roles

| Role | Permissions |
|------|-------------|
| Super Admin | All operations + user management |
| Content Admin | Full CRUD on all config entities |
| Data Editor | Edit scores, schedules, team info only |
| Viewer | Read-only access |

---

## Future Features (Other)

### Write Operations for Public API (CRUD)
- **Status**: `NOT STARTED`
- **Description**: POST, PUT, DELETE endpoints for the public API. Currently read-only by design.
- **Note**: Only implement if business requirements change. Admin Tool handles internal CRUD.

### External Integrations
- **Status**: `NOT STARTED`
- **Description**: Webhook support for data changes, cache invalidation triggers.
- **Note**: Plan when scaling requirements are clearer.

---

## File Reference

Key files that will need modifications:

| File | Related Tasks |
|------|---------------|
| `sportpulse_widgets_seed.json` | #1, #8 |
| `src/models/sport.model.ts` | #2 |
| `src/models/api-key.model.ts` | #2 |
| `scripts/seed-data.ts` | #3 |
| `src/services/*.service.ts` | #4 |
| `src/controllers/*.controller.ts` | #4 |
| `src/validation/schemas.ts` | #4, #11 |
| `src/app.ts` | #6, #15 |
| `src/config/env.ts` | #7 |
| `src/middleware/request-logger.middleware.ts` | #9 |
| `src/middleware/error.middleware.ts` | #12 |
| `openapi.yaml` | #4, #13 |
| `src/routes/api.test.ts` | #10 |
| `scripts/capture-widget-screenshots.ts` | #14 (new file) |

---

## Getting Started

Recommended order to tackle these tasks:

1. **First**: Fix critical issues (#1, #2, #3) - these are quick wins
2. **Second**: Add pagination (#4) - impacts API contract, do early
3. **Third**: Security items (#5, #6) - required for production
4. **Fourth**: Update widget URLs (#8) when provided by SportPulse team
5. **Then**: Work through medium priority items as time allows (#9-#14)
6. **Finally**: Screenshot script (#14) once all widget URLs are populated

Questions? Contact the project owner.
