175 lines
5.0 KiB
Markdown
175 lines
5.0 KiB
Markdown
# 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.
|