Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/davidmpizarro/QuipuEco-Hackaton/llms.txt

Use this file to discover all available pages before exploring further.

QuipuEco’s backend is a lightweight FastAPI service that acts as the intelligence layer between the React PWA and Google Gemini. Every time a Lima resident photographs a piece of waste or speaks a question to the voice agent, one of two endpoints handles the heavy lifting: /clasificar runs the image through Gemini’s vision model and returns a structured recycling decision, while /chat maintains a stateless conversational turn and can instruct the frontend to navigate to the map or dashboard. Both endpoints are stateless — all session context (conversation history, classification result, and geolocation) is owned by the frontend and sent on each request.

Base URL

The frontend hardcodes the backend origin in both ImageCapture.jsx and AgenteVoz.jsx:
const API_URL = "http://localhost:8000";
When running locally, start the backend with:
uvicorn app.main:app --reload
The server binds to http://localhost:8000 by default. Update API_URL in both components if you deploy the backend to a remote host.
The frontend (Vite dev server) runs on http://localhost:5173. FastAPI must have CORS enabled for that origin, otherwise the browser will block all requests. Add http://localhost:5173 to the allow_origins list in your CORSMiddleware configuration.

Authentication

There is no client-side authentication. The Google Gemini API key is stored exclusively on the server as the GEMINI_API_KEY environment variable and is never exposed to the browser. Requests from the frontend carry no tokens or headers beyond Content-Type.
Do not expose GEMINI_API_KEY in frontend environment variables or commit it to version control. The backend reads it at startup via python-dotenv or your deployment platform’s secret store.

AI Model

Both endpoints use Google Gemini gemini-3.1-flash-lite — a multimodal model optimized for low-latency mobile use cases. /clasificar sends the image bytes alongside a structured classification prompt; /chat sends the conversation history and waste context alongside a conversational prompt. The backend constructs all prompts server-side (app/prompts.py) so the frontend never needs to know the prompt format.

Endpoints

POST /clasificar

Classify a waste image using Gemini vision. Accepts a multipart image upload and returns material type, CO₂ impact, weight, recycling instructions, and a TTS-ready voice response.

POST /chat

Send a conversational message to the QuipuEco voice agent. Accepts message text, conversation history, waste context, and optional geolocation. Returns a response and an optional app navigation action.

Interactive Docs

FastAPI auto-generates two interactive API explorers from the OpenAPI schema. Both are available immediately after starting the server:
InterfaceURL
Swagger UIhttp://localhost:8000/docs
ReDochttp://localhost:8000/redoc

Error Format

All errors follow FastAPI’s standard detail envelope. The frontend reads this field directly:
// ImageCapture.jsx
setError(e.response?.data?.detail || "Error al clasificar el residuo.");
A typical validation error looks like this:
{
  "detail": [
    {
      "type": "missing",
      "loc": ["body", "mensaje"],
      "msg": "Field required"
    }
  ]
}
Unhandled server-side exceptions (e.g., a Gemini API timeout) surface as 500 Internal Server Error with a plain string detail message.

Architecture Overview

The following diagram shows how a classification request flows from the PWA to Gemini and back:
User (Lima resident)
  ↓  photo or voice
React PWA (localhost:5173)
  ↓  POST /clasificar  or  POST /chat
FastAPI Backend (localhost:8000)
  ↓  image bytes + prompt  or  conversation + context
Google Gemini API  (gemini-3.1-flash-lite)
  ↓  structured JSON response
FastAPI → React → UI + TTS + Mapbox map
The backend performs no database writes. Recycling history, earned points, and CO₂ totals are accumulated entirely in the frontend via the useHistorial hook and persisted in localStorage.

Build docs developers (and LLMs) love