# Great Lakes Ice Report A community-driven web application for tracking winter road conditions and icy hazards in the Great Lakes region. Reports automatically expire after 48 hours to maintain current information. ## Features - πŸ—ΊοΈ **Interactive Map** - Real-time location tracking centered on Grand Rapids - ⚑ **Fast Geocoding** - Lightning-fast address lookup with MapBox API - πŸ”„ **Auto-Expiration** - Reports automatically removed after 48 hours - πŸ‘¨β€πŸ’Ό **Admin Panel** - Manage and moderate location reports - πŸ“± **Responsive Design** - Works on desktop and mobile devices - πŸ”’ **Privacy-Focused** - No user tracking, community safety oriented - πŸ›‘οΈ **Enhanced Security** - Coordinate validation, rate limiting, and content filtering ## Quick Start ### Prerequisites - Node.js 18+ - MapBox API token (free tier available) ### Local Development 1. **Clone the repository:** ```bash git clone git@git.deco.sh:deco/ice.git cd ice ``` 2. **Install dependencies:** ```bash npm install ``` *Note: CSS is automatically built via the `postinstall` script* 3. **Configure environment variables:** ```bash cp .env.example .env # Edit .env with your MapBox token ``` 4. **Start the server:** ```bash npm start # Production mode npm run dev # Development mode npm run dev-with-css # Development with CSS watching ``` ## Development Commands ### 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 ``` 5. **Visit the application:** ``` http://localhost:3000 ``` ### CSS Development This project uses SCSS for styling. The CSS is **generated** and should not be committed to git. - **Build CSS once:** `npm run build-css` - **Build CSS (dev mode):** `npm run build-css:dev` - **Watch CSS changes:** `npm run watch-css` - **Dev with CSS watching:** `npm run dev-with-css` SCSS files are organized in `src/scss/`: - `main.scss` - Main entry point - `_variables.scss` - Theme variables and colors - `_mixins.scss` - Reusable SCSS mixins - `pages/` - Page-specific styles - `components/` - Component-specific styles ## Environment Variables ```bash # Required for fast geocoding MAPBOX_ACCESS_TOKEN=pk.your_mapbox_token_here # Admin panel access ADMIN_PASSWORD=your_secure_password # Server configuration PORT=3000 ``` ## Deployment ### Automated Deployment (Debian 12 ARM64) 1. **Run the deployment script on your server:** ```bash curl -sSL https://ice-puremichigan-lol.s3.amazonaws.com/scripts/deploy.sh | bash ``` 2. **Deploy your application:** ```bash git clone git@git.deco.sh:deco/ice.git /opt/ice cd /opt/ice npm install # This automatically builds CSS via postinstall ``` 3. **Configure environment:** ```bash cp .env.example .env nano .env # Add your API keys ``` 4. **Start services:** ```bash sudo systemctl enable ice sudo systemctl start ice sudo systemctl enable caddy sudo systemctl start caddy ``` ### Manual Deployment See `docs/deployment.md` for detailed manual deployment instructions. ## API Endpoints ### Public Endpoints - `GET /api/locations` - Get active location reports - `POST /api/locations` - Submit new location report (rate limited: 10/15min per IP) - `GET /api/config` - Get API configuration ### Admin Endpoints (Authentication Required) - `GET /admin` - Admin panel (password protected) - `GET /api/admin/locations` - Get all location reports - `PUT /api/admin/locations/:id` - Update location report - `PATCH /api/admin/locations/:id/persistent` - Toggle persistent status - `DELETE /api/admin/locations/:id` - Delete location report - `GET /api/admin/profanity-words` - Manage profanity filter - `POST /api/admin/profanity-words` - Add custom profanity word - `PUT /api/admin/profanity-words/:id` - Update profanity word - `DELETE /api/admin/profanity-words/:id` - Delete profanity word ### API Documentation Interactive API documentation available at `/api-docs` when running the server. ## Technology Stack - **Backend:** Node.js, Express.js, SQLite, TypeScript - **Frontend:** Vanilla JavaScript, Leaflet.js - **Geocoding:** MapBox API (with Nominatim fallback) - **Security:** Rate limiting, input validation, authentication - **Testing:** Jest, TypeScript, 128+ tests with 76% coverage - **Reverse Proxy:** Caddy (automatic HTTPS) - **Database:** SQLite (lightweight, serverless) ## Contributing 1. Fork the repository 2. Create a feature branch 3. Make your changes 4. Test thoroughly 5. Submit a pull request ## Security - **Authentication:** Admin routes protected with bearer token authentication - **Rate Limiting:** Public endpoints limited to prevent abuse (10 requests/15min per IP) - **Input Validation:** Strict length limits and type checking on all user inputs - **Data Protection:** API keys stored in environment variables only - **Database Security:** Parameterized queries prevent SQL injection - **Content Filtering:** Built-in profanity filter with custom word management - **HTTPS:** Enforced in production via Caddy reverse proxy - **Audit Logging:** Suspicious activity and abuse attempts are logged ### Input Limits - **Address:** Maximum 500 characters - **Description:** Maximum 1000 characters - **Latitude:** Must be between -90 and 90 degrees - **Longitude:** Must be between -180 and 180 degrees - **Submissions:** 10 per 15 minutes per IP address ## License MIT License - see LICENSE file for details ## Support This is a community safety tool. For issues or questions: - Create an issue on our git repository - Check existing documentation - Review security guidelines --- **⚠️ Safety Notice:** This tool is for community awareness. Always prioritize personal safety and know your rights.