JPT Logo
Jose Paulo Timbang
All posts
ProjectsAI Engineering

Building pamangan.com: An AI-Powered Recipe Platform

May 15, 20268 min readJose Paulo Timbang

The Idea

Filipino cuisine is underrepresented online. Most recipe platforms focus on Western food, and AI-powered tools are even worse. I wanted to build something that celebrated Filipino food — and used it as an opportunity to learn AI integration in a production context.

pamangan.com was born from that goal: a full-stack recipe platform where you can search existing recipes, generate new ones via AI, build grocery lists, and get nutritional breakdowns — all powered by Google Gemini with a Groq fallback.

Architecture Decisions

The first major decision was the database strategy. Rather than calling the AI on every search, I implemented a database-first approach:

  1. Search MongoDB text index for the query
  2. If found → return from DB immediately (fast, free)
  3. If not found → call Gemini AI to generate the recipe
  4. Save the AI result to DB (so the next search hits the cache)

This design cut AI API costs dramatically while making the app feel fast.

def search_recipe(query: str) -> dict:
    # Try DB first
    cached = recipe_service.search_by_name(query)
    if cached:
        return cached

    # Fall back to AI generation
    recipe = ai_service.generate_recipe(query)
    recipe_service.save(recipe)
    return recipe

The AI Fallback System

Gemini is excellent but not 100% reliable — rate limits, timeouts, and API errors happen. Rather than showing users an error, I built a transparent fallback to Groq's llama-3.1-8b-instant model:

def generate_recipe(dish_name: str) -> dict:
    try:
        return self._call_gemini(dish_name)
    except Exception:
        return self._call_groq(dish_name)  # Silent fallback

The user never sees an error message. They just get a recipe — from whichever provider worked.

What I Learned

1. AI reliability is not guaranteed. Design for graceful fallback from day one. Never let a single provider failure surface to the user.

2. Cache aggressively. Every AI-generated recipe gets saved. The second person to search for "Adobo" gets an instant database result, not an API call.

3. Separation of concerns saves you. By keeping AI logic in ai_service.py, I could swap providers, add fallbacks, and tune prompts without touching any route handlers.

4. MongoDB text indexes are powerful. A properly indexed search across name, cuisine, and tags is fast enough to be invisible to users.

Deployment

  • Frontend: React static build → Hostinger (rsync via GitHub Actions)
  • Backend: Flask on Koyeb (free tier)
  • Database: MongoDB Atlas (free M0 cluster)

The whole production stack costs $0/month beyond the Hostinger domain.

Tags

ReactFlaskMongoDBGemini AIPython
JP

Jose Paulo Timbang

Full Stack Developer & AI Engineer

Self-taught developer from the Philippines. Building web applications and AI-powered tools. Learn more →

P

Paulo's AI Assistant

Online