No description
Find a file
Claude Code a8f2078e5b
All checks were successful
CI / Lint Code (push) Successful in 1m39s
CI / Security Checks (push) Successful in 1m30s
CI / Validate i18n Files (push) Successful in 9s
CI / TypeScript Type Check (push) Successful in 1m49s
CI / Build Project (push) Successful in 1m59s
CI / Run Tests (Node 18) (push) Successful in 2m8s
Auto Tag Release / Create Auto Tag (push) Successful in 2m22s
CI / Run Tests (Node 20) (push) Successful in 2m18s
CI / Test Coverage (push) Successful in 3m13s
Deploy Scripts to S3 / deploy-scripts (push) Successful in 34s
Add server update scripts and fix repository URLs
- Add scripts/server-update.sh for production deployments
- Add scripts/dev-update.sh for development updates
- Update repository URLs to signal-works/icewatch
- Document update scripts in CLAUDE.md

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-08 21:27:11 -04:00
.forgejo/workflows Add .zip extension to coverage report artifact name 2025-07-07 21:58:21 -04:00
.github Add GitHub mirror README and remove workflows 2025-07-07 19:30:05 -04:00
docs Sync all deployment documentation and remove manual database creation 2025-07-06 18:37:48 -04:00
public Add version footer and disable map scroll wheel zoom 2025-07-07 22:37:20 -04:00
scripts Add server update scripts and fix repository URLs 2025-07-08 21:27:11 -04:00
src Fix double dots in privacy policy disclaimer 2025-07-07 22:54:26 -04:00
tests Fix TypeScript linting issues and test failures 2025-07-07 21:14:54 -04:00
.env.example Update HTML files to use Bunny.net CDN for static assets 2025-07-03 20:44:16 -04:00
.gitignore Add TypeScript frontend build system with shared components 2025-07-07 19:46:19 -04:00
CLAUDE.md Add server update scripts and fix repository URLs 2025-07-08 21:27:11 -04:00
eslint.config.mjs Fix ESLint issues in TypeScript codebase 2025-07-07 20:05:27 -04:00
jest.config.js Add comprehensive tests for i18n routes and fix route ordering 2025-07-07 20:50:34 -04:00
original-style.css Remove unused Sass/SCSS setup 2025-07-03 21:56:26 -04:00
package-lock.json Add TypeScript frontend build system with shared components 2025-07-07 19:46:19 -04:00
package.json Add version footer and disable map scroll wheel zoom 2025-07-07 22:37:20 -04:00
README.md Update documentation for TypeScript frontend build system 2025-07-07 20:36:58 -04:00
s3-bucket-policy.json Update HTML files to use Bunny.net CDN for static assets 2025-07-03 20:44:16 -04:00
tsconfig.json Exclude frontend from main TypeScript build 2025-07-07 20:21:01 -04:00

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
  • 📱 Progressive Web App - Install on mobile home screen, works offline
  • 🚫 JavaScript-Free Mode - Complete functionality without JavaScript via server-side rendering
  • 🖼️ Static Maps - Auto-generated Mapbox static images for non-JS users
  • 🔄 Auto-Expiration - Reports automatically removed after 48 hours
  • 👨‍💼 Admin Panel - Manage and moderate location reports
  • 📱 Responsive Design - Works on desktop and mobile devices
  • Accessibility First - Progressive enhancement with noscript fallbacks
  • 🔒 Privacy-Focused - No user tracking, community safety oriented
  • 🛡️ Enhanced Security - Coordinate validation, rate limiting, and content filtering
  • 🌐 Internationalization - Full i18n support with English and Spanish (Mexico) languages

Quick Start

Prerequisites

  • Node.js 18+
  • Mapbox API token (free tier available)
    • Important: For server-side static maps, use an unrestricted token (no URL restrictions)

Local Development

  1. Clone the repository:

    git clone https://git.deco.sh/deco/ice.git
    cd ice
    
  2. Install dependencies:

    npm install
    

    Note: CSS is automatically built via the postinstall script

  3. Configure environment variables:

    cp .env.example .env
    # Edit .env with your Mapbox token
    
  4. Start the server:

    npm start              # Production mode (builds everything)
    npm run dev:ts         # TypeScript development mode
    npm run dev-with-css:ts # TypeScript + CSS watching (recommended)
    npm run dev:full       # Full development (TypeScript + frontend + CSS)
    

Development Commands

Code Quality

# Run ESLint to check code style and quality
npm run lint

# Auto-fix ESLint issues where possible
npm run lint:fix

Testing

# Run all tests (128+ tests with TypeScript)
npm test

# Run tests with coverage report (76% overall coverage)
npm run test:coverage
  1. Visit the application:
    http://localhost:3000
    

Build System

This project uses TypeScript for both backend and frontend code, with SCSS for styling.

Backend (TypeScript → Node.js):

npm run build:ts        # Compile TypeScript backend
npm run dev:ts          # TypeScript development with auto-reload

Frontend (TypeScript → Browser JavaScript):

npm run build:frontend  # Compile frontend TypeScript with esbuild
npm run watch:frontend  # Watch frontend TypeScript for changes

CSS (SCSS → CSS):

npm run build-css       # Build CSS once (production)
npm run build-css:dev   # Build CSS with source maps
npm run watch-css       # Watch SCSS files for changes

Development Commands:

npm run dev:full        # Watch all: TypeScript backend + frontend + CSS
npm run dev-with-css:ts # Watch TypeScript backend + CSS
npm run build           # Build everything for production

File Organization:

  • src/ - TypeScript backend code
  • src/frontend/ - TypeScript frontend code (compiled to public/dist/)
  • src/scss/ - SCSS stylesheets (compiled to public/style.css)
  • dist/ - Compiled backend JavaScript
  • public/dist/ - Compiled frontend JavaScript

Note: Generated files (dist/, public/dist/, public/style.css) should not be committed to git.

Environment Variables

# Required for geocoding and static map generation
MAPBOX_ACCESS_TOKEN=pk.your_mapbox_token_here

# Admin panel access
ADMIN_PASSWORD=your_secure_password

# Server configuration
PORT=3000

Mapbox Token Requirements:

  • For interactive geocoding: Token can have URL restrictions
  • For server-side static maps: Must use unrestricted token (no URL restrictions)
  • Recommended: Use one unrestricted token for both features

Deployment

Deployment Scripts

The scripts/ directory contains all deployment-related files:

  • deploy.sh - Automated deployment script for Debian 12 (ARM64/x86_64)
  • icewatch.service - Systemd service file for the application
  • Caddyfile - Caddy reverse proxy configuration
  • generate-icons.js - Script to generate PWA icons

See docs/deployment-quickstart.md for a simplified deployment guide.

Automated Deployment (Debian 12 ARM64/x86_64)

  1. Run the deployment script on your server:

    Option A: Use the local deployment script (Recommended)

    # Clone the repository first
    git clone https://git.deco.sh/deco/ice.git
    cd ice
    
    # Run the local deployment script
    sudo bash scripts/deploy.sh
    

    Option B: Download from S3

    # Default: Downloads config from S3
    curl -sSL https://ice-puremichigan-lol.s3.amazonaws.com/scripts/deploy.sh | bash
    
    # Alternative: Use local files only (no S3)
    curl -sSL https://ice-puremichigan-lol.s3.amazonaws.com/scripts/deploy.sh | S3_BUCKET_NAME=none bash
    

    The deployment script (scripts/deploy.sh) automates the entire setup process including:

    • Installing required dependencies (Node.js, Git, Caddy)
    • Creating system user and directories
    • Setting up systemd services
    • Configuring Caddy reverse proxy
  2. Deploy your application:

    sudo git clone https://git.deco.sh/deco/ice.git /opt/icewatch
    cd /opt/icewatch
    sudo chown -R $USER:$USER /opt/icewatch
    npm install  # This automatically builds CSS via postinstall
    npm run build  # Build everything: TypeScript backend + frontend + CSS
    
  3. Configure environment:

    cp .env.example .env
    nano .env  # Add your API keys
    
  4. Create databases and set permissions:

    touch icewatch.db profanity.db
    sudo chown -R icewatch:icewatch /opt/icewatch
    
  5. Start services:

    sudo systemctl enable icewatch
    sudo systemctl start icewatch
    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

Progressive Enhancement Routes

  • 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
    • Query parameters: ?width=800&height=600&padding=50 for customization
    • Auto-fit positioning centers on actual location coordinates
    • Color-coded pins: red for regular reports, orange for persistent

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.

PWA Installation

Mobile Devices

  1. Open the app in your mobile browser
  2. Look for the "Add to Home Screen" prompt
  3. Tap "Add" to install the app on your home screen
  4. The app will work offline and behave like a native app

Desktop Browsers

  1. Visit the app in Chrome, Edge, or Safari
  2. Look for the install icon in the address bar
  3. Click "Install" to add the app to your desktop
  4. Launch from your applications folder or start menu

PWA Features

  • Offline Access: View cached reports when disconnected
  • App-like Experience: Standalone window, no browser UI
  • Home Screen Icon: Quick access like native apps
  • Automatic Updates: Always stay current when online

Technology Stack

  • Backend: Node.js, Express.js, SQLite, TypeScript
  • Frontend: Progressive Web App with Progressive Enhancement
    • PWA: Installable, offline-capable, service worker caching
    • Enhanced: Leaflet.js interactive maps with real-time updates
    • Fallback: Server-side HTML tables with static Mapbox images
  • Geocoding: Mapbox API (with Nominatim fallback)
  • Maps: Leaflet.js (interactive) + Mapbox Static Images API (server-side)
  • Security: Rate limiting, input validation, authentication
  • Testing: Jest, TypeScript, 128+ tests with 76% coverage
  • Reverse Proxy: Caddy (automatic HTTPS)
  • Database: SQLite (lightweight, serverless)
  • Accessibility: Full progressive enhancement with noscript support

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.