Track ration shop (Fair Price Shop) stock delivery status for Kerala citizens check if this month's commodities (rice, wheat, sugar, etc.) have arrived at your shop.
🔗 Live: rationundo.onrender.com
- The official portal (
epos.kerala.gov.in) is slow and indexes data only by District → Taluk → Shop number. - A daily scraper pulls all shop stock data into PostgreSQL.
- The web app serves every user search from the local DB zero external calls at request time, sub-200ms responses.
User → FastAPI → PostgreSQL (Supabase) → Response
↑
GitHub Actions (daily 2 AM IST) → httpx scraper → epos.kerala.gov.in
- Search by shop number, pincode, or place name (fuzzy autocomplete via
pg_trgm) - Near me GPS search nearest shops sorted by distance (km) via haversine
- Browse by District → Taluk → Shop
- Per-commodity allocated vs received quantities with progress bars
- Malayalam-first UI
- Installable PWA with offline app shell (service worker)
- Covers all 14 districts · 14,000+ shops · 5,000+ pincodes
- Backend: FastAPI + SQLAlchemy (async) + asyncpg
- Database: PostgreSQL with
pg_trgm(Supabase in production) - Scraper: httpx + BeautifulSoup, run as a daily GitHub Actions cron
- Frontend: TailwindCSS, vanilla JS
- Hosting: Render (web) + Supabase (DB) + GitHub Actions (scraper) all free tier
# 1. Start local Postgres (port 5433)
docker compose up -d
# 2. Install deps
pip install -e .
# 3. Create tables
alembic upgrade head
# 4. Seed pincodes (downloads Kerala data from open dataset)
python scripts/seed_pincodes.py
# 5. Discover all shops (one-time; District → Taluk → Shop)
python scripts/discover_shops.py
# 6. Link shops to pincodes (fuzzy match)
python scripts/fuzzy_match.py
# 7. Scrape stock data
python scripts/scrape_all.py
# 8. Run the server
uvicorn app.main:app --reload --port 8000Configure .env from .env.example (set DATABASE_URL).
See DEPLOY.md for the full Supabase + Render + GitHub Actions setup.
The scraper runs automatically every day at 2 AM IST via GitHub Actions
(.github/workflows/scrape.yml). It refreshes pending/partial shops, skips
fully-received ones, and prunes data older than 3 months. Manual workflow runs
can run only the daily scrape, only the weekly geo refresh, or both.
app/
├── main.py # FastAPI app entry + /health
├── config.py # Settings (pydantic-settings)
├── database.py # Async engine (Supabase pooler-aware)
├── schemas.py # Pydantic response models
├── api/routes.py # Thin JSON API endpoints
├── api/htmx_routes.py # Thin HTMX fragment endpoints
├── services/ # Business logic shared by API, HTMX, and workers
├── repositories/ # Database query helpers
├── models/models.py # SQLAlchemy ORM models
└── worker/
├── scraper.py # ePOS fetch + parser helpers
└── time_utils.py # IST month-cycle helpers
scripts/
├── seed_pincodes.py # Load pincode master data
├── discover_shops.py # One-time shop registry builder
├── fuzzy_match.py # Link shops to pincodes
├── scrape_all.py # Daily stock scraper (used by CI cron)
├── sync_to_supabase.py # One-time local → Supabase migration
└── verify.py # DB + API smoke test
templates/ # Page shell + HTMX partials
static/ # app.js, service worker, manifest, favicon.svg
Not affiliated with the Government of Kerala. Data sourced from the public
epos.kerala.gov.in portal. Some shop data may be unavailable or incomplete
contact your ration shop for the most accurate information.
MIT © 2026 Jithin