- README.md: Add comprehensive build system section explaining TypeScript backend/frontend compilation, esbuild usage, and development commands - CLAUDE.md: Update architecture documentation to reflect TypeScript frontend with shared components and esbuild compilation - scripts/deploy.sh: Update deployment instructions to use new unified build command 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
317 lines
10 KiB
Markdown
317 lines
10 KiB
Markdown
# 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:**
|
|
```bash
|
|
git clone https://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 (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
|
|
```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
|
|
```
|
|
|
|
### Build System
|
|
|
|
This project uses TypeScript for both backend and frontend code, with SCSS for styling.
|
|
|
|
**Backend (TypeScript → Node.js):**
|
|
```bash
|
|
npm run build:ts # Compile TypeScript backend
|
|
npm run dev:ts # TypeScript development with auto-reload
|
|
```
|
|
|
|
**Frontend (TypeScript → Browser JavaScript):**
|
|
```bash
|
|
npm run build:frontend # Compile frontend TypeScript with esbuild
|
|
npm run watch:frontend # Watch frontend TypeScript for changes
|
|
```
|
|
|
|
**CSS (SCSS → CSS):**
|
|
```bash
|
|
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:**
|
|
```bash
|
|
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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
### Quick Deployment (Recommended)
|
|
|
|
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)**
|
|
```bash
|
|
# 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**
|
|
```bash
|
|
# 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:**
|
|
```bash
|
|
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:**
|
|
```bash
|
|
cp .env.example .env
|
|
nano .env # Add your API keys
|
|
```
|
|
|
|
4. **Create databases and set permissions:**
|
|
```bash
|
|
touch icewatch.db profanity.db
|
|
sudo chown -R icewatch:icewatch /opt/icewatch
|
|
```
|
|
|
|
5. **Start services:**
|
|
```bash
|
|
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.
|