- Add web app manifest for home screen installation - Implement service worker with offline caching strategy - Create offline fallback page with auto-reconnect - Generate PWA icons in multiple sizes (72px-512px) - Add PWA meta tags and Apple Touch icons to all pages - Register service worker with graceful degradation - Update documentation with PWA installation instructions - Add browserconfig.xml for Windows tile support Features: - Installable on mobile and desktop - Offline functionality with cached resources - App-like experience in standalone mode - Automatic updates when online - Works seamlessly with existing progressive enhancement 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
250 lines
8.1 KiB
Markdown
250 lines
8.1 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
|
|
|
|
## 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 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 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
|
|
|
|
### 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
|
|
|
|
### 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.
|