🌐 Web App: https://grocerly.serraos.tech/
💬 WhatsApp Bot: +94 70 335 1444
An AI-powered multichannel platform for meal planning, catalog-backed supermarket price comparison, and optimized shopping lists in Sri Lanka.
Sri Lankan households shop across supermarkets and online platforms with fragmented pricing. Grocerly currently uses catalog data from Cargills, SPAR2U, Keells, Glomark, and Lassana; pola, Arpico, and seasonal-data integrations are future work.
A conversational AI agent that connects meal planning to real-time pricing data:
"Plan 5 dinners for a family of 4 under LKR 5,000"
The system retrieves current prices across stores, substitutes expensive items with cheaper local alternatives, and produces a ranked shopping list organized by which store combination gives the best total cost.
┌─────────────────────────────────────────────────────────────┐
│ User Channels │
├──────────┬─────────────┬────────────────────────────────────┤
│ WhatsApp │ Telegram │ Web App │
└────┬─────┴──────┬──────┴────────────┬───────────────────────┘
│ │ │
▼ ▼ ▼
┌─────────────────────────────────────────────────────────────┐
│ Orchestrator (Elysia/Bun — Port 3000) │
│ Normalize → Detect Language → Persist → Route → Respond │
└──────────────────────────┬──────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Routing Agent (Port 3001) │
│ LLM intent classification → delegate to specialist │
└─────┬──────────┬──────────┬─────────────┬───────────────────┘
│ │ │ │
▼ ▼ ▼ ▼
┌──────────┐ ┌────────┐ ┌──────────┐ ┌────────────────┐
│ Meal │ │ Price │ │ Product │ │ Recommendation │
│ Planner │ │ Engine │ │ Catalog │ │ Agent │
│ :3002 │ │ :3003 │ │ :3004 │ │ :3005 │
└──────────┘ └────────┘ └──────────┘ └────────────────┘
│
▼
┌───────────────┐
│ Scrapers │
│ (Cargills, │
│ Keells, etc) │
└───────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Unified SQLite catalog + generated vector artifacts │
└─────────────────────────────────────────────────────────────┘
grocerly/
├── apps/
│ ├── orchestrator/ # Messaging gateway (webhooks, WS, routing)
│ ├── routing-agent/ # LLM intent classifier → dispatches to agents
│ ├── meal-planner/ # Meal plan generation + basket optimization
│ ├── price-engine/ # Price scraping, comparison, basket optimizer
│ ├── product-catalog/ # Unified grocery catalog + hybrid search
│ ├── recommendation-agent/ # Alternatives, substitutes, savings tips
│ └── frontend-web/ # React web app (chat, meal planner, prices)
├── packages/
│ ├── types/ # Shared TypeScript types (Zod schemas)
│ ├── utils/ # Logger, language detection, helpers
│ └── config/ # Shared ESLint/TS config
├── docker/
│ └── docker-compose.yml # Development compose (not production-verified)
├── other/
│ └── CargillsScraper/ # Existing Cargills scraping work
├── infra/ # DB init scripts
└── docs/ # Architecture docs
- Bun >= 1.2
- Docker (or Podman)
# Install dependencies
bun install
# Configure environment
cp .env.example .env
# Add bot tokens only when testing those channels
# Run all services in dev mode
bun run devcd apps/orchestrator && bun run dev # Port 3000
cd apps/routing-agent && bun run dev # Port 3001
cd apps/meal-planner && bun run dev # Port 3002
cd apps/price-engine && bun run dev # Port 3003
cd apps/product-catalog && bun run dev # Port 3004
cd apps/frontend-web && bun run dev # Port 5173bun run scrape # All scrapers
cd apps/price-engine && bun run scrape:cargills
cd apps/price-engine && bun run scrape:keells| Member | Service | Focus Area |
|---|---|---|
| Dev 1 | apps/orchestrator/ + apps/routing-agent/ |
Messaging, webhooks, intent routing |
| Dev 2 | apps/meal-planner/ |
LLM meal planning, recipe DB, quantity calc |
| Dev 3 | apps/price-engine/ |
Scrapers, price DB, basket optimization |
| Dev 4 | apps/product-catalog/ + apps/recommendation-agent/ |
Catalog, hybrid search, alternatives |
| Dev 5 | apps/frontend-web/ + packages/ |
Web UI, shared types, infra |
User: "Plan meals for 4 people, budget LKR 5000, 5 dinners"
→ Routing Agent: intent = meal_planning
→ Meal Planner:
1. LLM generates 5 Sri Lankan dinner recipes
2. Extracts all ingredients + quantities
3. Queries Price Engine for available SQLite catalog prices
4. Optimizes the available store combination
→ Returns: meal plan + shopping list sorted by store + total cost + savings tips
User: "How much is 1kg chicken at different stores?"
→ Routing Agent: intent = price_comparison
→ Price Engine: looks up latest scraped prices
→ Returns grounded matches from stores present in the catalog, or a clear no-match response
User: "What's cheaper than imported olive oil for cooking?"
→ Recommendation Agent: finds alternatives (coconut oil, sesame oil)
→ Returns: local alternatives with current prices and use cases
| Layer | Technology |
|---|---|
| Runtime | Bun |
| Backend Framework | Elysia |
| AI/LLM | Gemini via @google/genai and Vertex AI ADC; deterministic fallback locally |
| Product/price data | SQLite unified catalog |
| Scraping | Cheerio + Puppeteer |
| Frontend | React 19 + Vite + Tailwind CSS |
| Monorepo | Turborepo |
| Containers | Docker Compose |
| Validation | Zod |
| Languages | English, Sinhala, Tamil |
| Channels | WhatsApp, Telegram, Web |
POST /chat
{ message, user_id, platform, language, conversation_history }
→ { success, messages: [{ type: "text"|"interactive", content }] }
Same contract — each agent exposes POST /chat with the same schema.
GET /api/prices/compare?product=chicken
POST /api/prices/batch { items: ["rice", "dhal", "coconut"] }
POST /api/basket/optimize { items: [...], location: "colombo" }
GET /api/deals?store=keells
GET /api/products/search?q=rice&category=rice_grains
GET /products/supersearch?q=rice
GET /categories
Vertex-backed services use keyless Application Default Credentials on the VM. Local development does not require GEMINI_API_KEY; classification and generation degrade to deterministic fallback on unavailable credentials, quota, or timeout. Vector artifacts are generated on the VM and gitignored.
Nearby-store locations are curated approximations. The embedded map cascades through optional Google Maps and Mapbox credentials, then the keyless OpenStreetMap/Leaflet fallback. Store lists and Google Maps directions links remain available if all interactive providers fail.
- Branching:
feature/<service>-<description>(e.g.feature/price-engine-cargills-scraper) - Shared packages: Changes to
packages/need PR review - Types first: Define Zod schemas in
packages/typesbefore implementing - Health checks: Every service must expose
GET /health
AGENTRIX26 TEAM34 — Grocerly