# Free Alberta Food Resources - Project Documentation ## Original Requirements Build a webapp for freealberta.org to display free food resources in Alberta. Pull data from various sources, store in PostgreSQL, and serve via Cloudflare tunnel at food.freealberta.org. ### Data Sources - InformAlberta (5 zones - North, Edmonton, Calgary, Central, South) - Edmonton's Food Bank PDF (community meals) - 211 Alberta (Cloudflare protected - requires manual data or API access) ## Implementation Status: COMPLETE ### Technology Stack - **Backend**: Express.js (Node.js) - **Frontend**: HTML, CSS, vanilla JavaScript - **Database**: PostgreSQL 17 (dedicated container) - **Maps**: Leaflet.js with OpenStreetMap (100% FOSS) - **Routing**: OSRM (Open Source Routing Machine) - **Geocoding**: Nominatim + Photon (OpenStreetMap-based) - **Containerization**: Docker ### Project Structure ``` freealberta-food/ ├── app/ │ ├── public/ │ │ ├── css/styles.css │ │ ├── js/app.js │ │ └── index.html │ ├── routes/api.js │ ├── controllers/ │ │ ├── resourceController.js │ │ ├── scraperController.js │ │ ├── geocodingController.js │ │ └── routingController.js │ ├── models/ │ │ ├── db.js │ │ └── init-db.js │ ├── services/ │ │ ├── geocoding.js │ │ └── routing.js │ ├── scrapers/ │ │ ├── informalberta.js │ │ ├── ab211.js │ │ ├── pdf-parser.js │ │ └── run-all.js │ ├── utils/logger.js │ ├── server.js │ ├── package.json │ └── Dockerfile ├── docker-compose.yml ├── .env └── .env.example ``` ### Features Implemented - Full-featured frontend with map view and list view - Search functionality (by name, address, services) - Filters by city and resource type - Geolocation support (find nearby resources) - **Turn-by-turn directions** from user location to any resource - **Multiple travel modes**: Driving, Walking, Cycling - **Printable directions** with step-by-step instructions - **Automatic geocoding** of addresses during data scrape - Resource detail modal - Pagination - Mobile responsive design ### Mapping Features (100% FOSS) - **Base Map**: OpenStreetMap tiles via Leaflet.js - **Geocoding**: Multi-provider with Nominatim and Photon fallback - **Routing**: OSRM (Open Source Routing Machine) for directions - **Directions**: Turn-by-turn navigation with distance/duration - **Print**: Printable directions with full step list ### Resource Types - Food Bank - Community Meal - Food Hamper - Food Pantry - Soup Kitchen - Mobile Food - Grocery Program ### API Endpoints **Resources** - `GET /api/resources` - List resources with filters - `GET /api/resources/search` - Text search - `GET /api/resources/nearby` - Location-based search - `GET /api/resources/:id` - Single resource details - `GET /api/cities` - Available cities - `GET /api/types` - Resource types - `GET /api/stats` - Statistics **Geocoding** - `GET /api/geocode?address=...` - Forward geocode address to coordinates - `GET /api/geocode/reverse?lat=...&lng=...` - Reverse geocode coordinates **Routing/Directions** - `GET /api/directions?startLat=...&startLng=...&endLat=...&endLng=...&profile=driving` - Get turn-by-turn directions **Admin** - `POST /api/scrape` - Trigger manual scrape - `GET /api/scrape/status` - Scrape status - `GET /api/scrape/logs` - Scrape history ### Data Refresh - Weekly automated scrape (Sundays at 2 AM) - Manual trigger via `/api/scrape` - Automatic geocoding of new addresses during scrape ## Deployment Instructions ### 1. Start the Application ```bash cd freealberta-food docker compose up -d ``` ### 2. Initialize the Database ```bash docker exec -it freealberta-food-app npm run db:init ``` ### 3. Run Initial Data Scrape ```bash docker exec -it freealberta-food-app npm run scrape ``` ### 4. Configure Cloudflare Tunnel Add to your Cloudflare tunnel configuration: ```yaml - hostname: food.freealberta.org service: http://freealberta-food-app:3003 ``` ## Port Configuration - Application: 3003 (configured in main .env as FOOD_PORT) - Database: Internal only (within Docker network) ## Known Limitations 1. **211 Alberta**: Cloudflare protection blocks automated scraping. Data must be entered manually or via API access request. 2. **PDF Parsing**: The Edmonton Food Bank PDF structure may vary; manual review recommended. 3. **Geocoding Rate Limits**: Nominatim has a 1 request/second limit. Scraping with geocoding takes longer. 4. **OSRM Public Server**: Using the public demo server which has rate limits. For production, consider self-hosting OSRM. ## Future Enhancements - Request API access from 211 Alberta - Self-host OSRM for faster routing - Add admin panel for manual data management - Connect to NocoDB for form-based data entry - Add analytics tracking - Cache route calculations ## Environment Variables See `.env.example` for all configuration options.