- Add S3 bucket support with fallback to ice-puremichigan-lol - Update deployment script to handle both S3 and local file copying - Support custom S3 bucket via S3_BUCKET_NAME environment variable - Update HTTPS clone URL in README and deploy.sh - Improve CLAUDE.md with single test execution instructions - Update deployment paths to use /opt/icewatch 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
253 lines
No EOL
10 KiB
Markdown
253 lines
No EOL
10 KiB
Markdown
# CLAUDE.md
|
|
|
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
|
|
## Development Commands
|
|
|
|
### Running the Application
|
|
```bash
|
|
# Install dependencies
|
|
npm install
|
|
|
|
# Start the server (production mode - TypeScript)
|
|
npm start
|
|
|
|
# Development mode options:
|
|
npm run dev # TypeScript development with auto-reload
|
|
npm run dev:js # Legacy JavaScript development mode
|
|
npm run dev-with-css:ts # TypeScript + CSS watching (recommended)
|
|
npm run dev-with-css # Legacy JS + CSS watching
|
|
```
|
|
|
|
The application runs on port 3000 by default. Visit http://localhost:3000 to view the website.
|
|
|
|
### API Documentation
|
|
Interactive OpenAPI/Swagger documentation is available at `/api-docs` when the server is running:
|
|
- **Development**: http://localhost:3000/api-docs
|
|
- **Production**: https://yourapp.com/api-docs
|
|
|
|
The documentation includes:
|
|
- Complete API endpoint specifications
|
|
- Request/response schemas and examples
|
|
- Authentication requirements
|
|
- Interactive testing interface
|
|
|
|
### TypeScript Development
|
|
The backend is written in TypeScript and compiles to `dist/` directory.
|
|
```bash
|
|
# Build TypeScript (production)
|
|
npm run build:ts
|
|
|
|
# Build everything (TypeScript + CSS)
|
|
npm run build
|
|
|
|
# Development with TypeScript watching
|
|
npm run dev:ts
|
|
```
|
|
|
|
### CSS Development
|
|
CSS is generated from SCSS and should NOT be committed to git.
|
|
```bash
|
|
# Build CSS once (compressed for production)
|
|
npm run build-css
|
|
|
|
# Build CSS with source maps (for development)
|
|
npm run build-css:dev
|
|
|
|
# Watch SCSS files and auto-compile changes
|
|
npm run watch-css
|
|
```
|
|
|
|
### Code Quality
|
|
```bash
|
|
# Run ESLint to check code style and quality
|
|
npm run lint
|
|
|
|
# Auto-fix ESLint issues where possible
|
|
npm run lint:fix
|
|
```
|
|
|
|
### Testing
|
|
```bash
|
|
# Run all tests (128+ tests with TypeScript)
|
|
npm test
|
|
|
|
# Run tests with coverage report (76% overall coverage)
|
|
npm run test:coverage
|
|
|
|
# Run a single test file
|
|
npm test -- tests/unit/models/Location.test.ts
|
|
|
|
# Run tests matching a pattern
|
|
npm test -- --testNamePattern="should create a new location"
|
|
|
|
# Run tests in watch mode for a specific file
|
|
npx jest --watch tests/unit/models/Location.test.ts
|
|
|
|
# Run with debugging
|
|
node --inspect-brk ./node_modules/.bin/jest --runInBand tests/unit/models/Location.test.ts
|
|
```
|
|
|
|
**Test Structure:**
|
|
- **Unit tests**: `tests/unit/` (models, services)
|
|
- **Integration tests**: `tests/integration/` (routes)
|
|
- **Test setup**: `tests/setup.ts`
|
|
- **Mocks**: `tests/__mocks__/`
|
|
|
|
**Test Coverage:**
|
|
- **Unit Tests:** Location/ProfanityWord models, DatabaseService, ProfanityFilterService
|
|
- **Integration Tests:** Public API routes, Admin API routes with authentication
|
|
- **Security Tests:** Rate limiting, input validation, authentication flows
|
|
- **Coverage:** 76% statements, 63% branches, 78% lines
|
|
|
|
### Environment Setup
|
|
Before running the application, you must configure environment variables:
|
|
```bash
|
|
cp .env.example .env
|
|
# Edit .env to add your Mapbox token and admin password
|
|
```
|
|
|
|
Required environment variables:
|
|
- `MAPBOX_ACCESS_TOKEN`: Mapbox API token for geocoding and static map generation (get free token at https://account.mapbox.com/access-tokens/)
|
|
- **Important**: For server-side static map generation, use an unrestricted token (no URL restrictions)
|
|
- `ADMIN_PASSWORD`: Password for admin panel access at /admin
|
|
- `PORT`: Server port (default: 3000)
|
|
|
|
## Architecture Overview
|
|
|
|
### Backend (Node.js/Express + TypeScript)
|
|
- **src/server.ts**: Main Express server with modular route architecture (compiles to `dist/server.js`)
|
|
- Uses two SQLite databases: `icewatch.db` (locations) and `profanity.db` (content moderation)
|
|
- Automatic cleanup of reports older than 48 hours via node-cron
|
|
- Bearer token authentication for admin endpoints
|
|
- Environment variable configuration via dotenv
|
|
- Full TypeScript with strict type checking
|
|
|
|
### Route Architecture
|
|
Routes are organized as factory functions accepting dependencies with full TypeScript typing:
|
|
|
|
- **src/routes/config.ts**: Public API configuration endpoints
|
|
- **src/routes/locations.ts**: Location submission and retrieval with profanity filtering
|
|
- **src/routes/admin.ts**: Admin panel functionality with authentication middleware
|
|
|
|
### Models & Services (TypeScript)
|
|
- **src/models/Location.ts**: Type-safe database operations for location data
|
|
- **src/models/ProfanityWord.ts**: Type-safe database operations for profanity words
|
|
- **src/services/DatabaseService.ts**: Centralized database connection management
|
|
- **src/services/ProfanityFilterService.ts**: Content moderation with type safety
|
|
- **src/services/MapImageService.ts**: Server-side static map generation using Mapbox Static Images API
|
|
- **src/types/index.ts**: Shared TypeScript interfaces and type definitions
|
|
|
|
### Database Schema
|
|
**Main Database (`icewatch.db`)**:
|
|
```sql
|
|
CREATE TABLE locations (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
address TEXT NOT NULL,
|
|
latitude REAL,
|
|
longitude REAL,
|
|
timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
description TEXT,
|
|
persistent INTEGER DEFAULT 0,
|
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
```
|
|
|
|
**Profanity Database (`profanity.db`)**:
|
|
Managed by the `ProfanityFilter` class for content moderation.
|
|
|
|
### Frontend (Progressive Web App + Progressive Enhancement)
|
|
The application is a full Progressive Web App with offline capabilities and progressive enhancement:
|
|
|
|
**PWA Features:**
|
|
- **public/manifest.json**: Web app manifest for installation
|
|
- **public/sw.js**: Service worker for offline functionality and caching
|
|
- **public/icons/**: Complete icon set for all device sizes (72px to 512px)
|
|
- **public/offline.html**: Offline fallback page when network is unavailable
|
|
- **PWA Meta Tags**: Added to all HTML files for proper app behavior
|
|
|
|
**JavaScript-Enhanced Experience:**
|
|
- **public/app.js**: Main implementation using Leaflet.js
|
|
- Auto-detects available geocoding services (Mapbox preferred, Nominatim fallback)
|
|
- Interactive map with real-time updates
|
|
- Autocomplete and form validation
|
|
|
|
- **public/app-mapbox.js**: Mapbox GL JS implementation for enhanced features
|
|
- **public/app-google.js**: Google Maps implementation (alternative)
|
|
- **public/admin.js**: Admin panel functionality
|
|
- **public/utils.js**: Shared utilities across implementations
|
|
|
|
**Non-JavaScript Fallback:**
|
|
- **Server-side /table route**: Complete HTML table view of all locations
|
|
- **HTML form submission**: Works via POST to /submit-report endpoint
|
|
- **Static map generation**: Auto-fitted Mapbox static images showing all report locations
|
|
- **Progressive enhancement**: noscript tags and "Basic View" button for accessibility
|
|
|
|
**Offline Capabilities:**
|
|
- **Service Worker Caching**: Essential files cached for offline access
|
|
- **Offline Page**: Custom offline experience with automatic reconnection
|
|
- **Install Prompt**: Automatic PWA installation prompts on compatible devices
|
|
|
|
### API Endpoints
|
|
|
|
**Public endpoints:**
|
|
- `GET /api/config`: Returns Mapbox token for frontend geocoding
|
|
- `GET /api/locations`: Active locations (< 48 hours old or persistent)
|
|
- `POST /api/locations`: Submit new location report (rate limited: 10/15min per IP)
|
|
- **Input Validation:** Address ≤500 chars, Description ≤1000 chars, coordinate validation
|
|
- **Profanity Filtering:** Automatic content moderation with rejection
|
|
- **Security:** Rate limiting prevents spam and DoS attacks
|
|
|
|
**Server-side routes (Progressive Enhancement):**
|
|
- `GET /`: Main application page with JavaScript-enhanced features
|
|
- `GET /table`: Non-JavaScript table view with static map and HTML forms
|
|
- `POST /submit-report`: Server-side form submission for non-JavaScript users
|
|
- `GET /map-image.png`: Dynamic static map generation using Mapbox Static Images API
|
|
- **Auto-fit positioning:** Centers on actual location coordinates
|
|
- **Numbered pins:** Color-coded markers (red=regular, orange=persistent)
|
|
- **Query parameters:** `?width=800&height=600&padding=50` for customization
|
|
|
|
**Admin endpoints (require Bearer token):**
|
|
- `POST /api/admin/login`: Authenticate and receive token
|
|
- `GET /api/admin/locations`: All locations including expired
|
|
- `PUT /api/admin/locations/:id`: Update location details
|
|
- `PATCH /api/admin/locations/:id/persistent`: Toggle persistent status
|
|
- `DELETE /api/admin/locations/:id`: Delete location (admin-only)
|
|
- **Profanity management:** `/api/admin/profanity-words` (GET, POST, PUT, DELETE)
|
|
|
|
**Security Features:**
|
|
- **Rate Limiting:** Express-rate-limit middleware on public endpoints
|
|
- **Authentication:** Bearer token authentication for admin routes
|
|
- **Input Validation:** Strict length limits and type checking
|
|
- **Audit Logging:** Suspicious activity detection and logging
|
|
|
|
### SCSS Organization
|
|
SCSS files are in `src/scss/`:
|
|
- `main.scss`: Entry point importing all other files
|
|
- `_variables.scss`: Theme colors and configuration
|
|
- `_mixins.scss`: Reusable style patterns
|
|
- `pages/`: Page-specific styles (home, admin, privacy)
|
|
- `components/`: Component styles (navbar, map, cards, forms)
|
|
|
|
### Key Design Patterns
|
|
|
|
1. **TypeScript-First Architecture**: Full type safety with strict type checking
|
|
2. **Progressive Web App**: Installable, offline-capable with service worker caching
|
|
3. **Progressive Enhancement**: Works completely without JavaScript via server-side rendering
|
|
4. **Security-by-Design**: Rate limiting, input validation, and authentication built into core routes
|
|
5. **Modular Route Architecture**: Routes accept dependencies as parameters for testability
|
|
6. **Dual Database Design**: Separate databases for application data and content moderation
|
|
7. **Type-Safe Database Operations**: All database interactions use typed models
|
|
8. **Comprehensive Testing**: 125+ tests covering units, integration, and security scenarios
|
|
9. **Graceful Degradation**: Fallback geocoding providers and error handling
|
|
10. **Automated Maintenance**: Cron-based cleanup of expired reports
|
|
11. **Accessibility-First**: noscript fallbacks and server-side static map generation
|
|
12. **Offline-First Design**: Service worker caching with automatic updates
|
|
|
|
### Deployment
|
|
- Automated deployment script for Debian 12 (ARM64/x86_64) in `scripts/deploy.sh`
|
|
- Caddy reverse proxy configuration in `scripts/Caddyfile`
|
|
- Systemd service files for process management
|
|
- Application directory: `/opt/icewatch`
|
|
- System user: `icewatch`
|
|
- Public repository: https://git.deco.sh/deco/ice.git |