EduPets is intentionally lean on the server side. The Python process does exactly one job — receive an HTTP request, pick the right HTML template, render it, and send it back. Everything that makes the platform feel like a game — pet stats, animated backgrounds, exercise scoring, task tracking — happens in vanilla JavaScript running in the child’s browser. There is no database, no session middleware, and no server-side business logic.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/Edupets-Studio/Edu-pets/llms.txt
Use this file to discover all available pages before exploring further.
Stack overview
| Layer | Technology | Role |
|---|---|---|
| HTTP server | FastAPI (Python) | Routing and template rendering only |
| Templates | Jinja2 | Produces the HTML sent to the browser |
| Static assets | FastAPI StaticFiles at /static/** | CSS, JavaScript, and images |
| Game state | Browser localStorage | All pet progress — no database |
| Deployment | Vercel (Python runtime + static CDN) | Hosting and edge delivery |
templates.TemplateResponse(...) and returns HTML.
Jinja2 templates produce the HTML for each page. They are used almost exclusively to generate correct {{ url_for('static', ...) }} URLs for CSS, JS, and image assets — there is no dynamic data injected from Python.
StaticFiles is mounted at /static and serves CSS, JavaScript, and image files directly from the static/ directory. Vercel’s static CDN layer handles these in production.
localStorage is the only persistence layer. Pet names, stat levels, and the active task are all written and read by JavaScript running in the browser. Clearing browser storage resets all progress.
Vercel hosts the application using the @vercel/python builder for main.py and @vercel/static for everything under static/. All requests not matching /static/** are forwarded to main.py.
Project structure
Request flow
Vercel routes to main.py
The
vercel.json routing rules match all non-static paths to main.py via the @vercel/python builder.FastAPI matches the route
app.add_api_route has registered a handler for the path. The handler calls render_page(request, template_name).Jinja2 renders the HTML template
templates.TemplateResponse(...) resolves {{ url_for('static', ...) }} expressions to absolute /static/... paths and returns the complete HTML string.Browser executes JavaScript
The page’s
<script> tag loads the page-specific JS file (e.g., mascota.js, Suma.js). All game logic runs from here — no further server communication is required.main.py walkthrough
The entire server is under 60 lines of Python.main.py
BASE_DIRusesPath(__file__).resolve().parentso that file paths work correctly both locally and on Vercel, regardless of the working directory the process starts in.app.mount("/static", ...)delegates all requests to/static/**directly to the filesystem — no Python code runs per static file request.Jinja2Templatesis configured with thetemplates/directory. CallingTemplateResponsewithout extra context means no dynamic data is injected; onlyurl_forresolution happens.PAGESdict maps clean URL paths (e.g.,/mascota) to Jinja2 template filenames.LEGACY_PAGESdict maps.html-suffixed and capitalized variants to the same templates for backwards compatibility with old bookmarks or links.- Dynamic route registration — the
forloop callsapp.add_api_routefor every entry in the mergedPAGES + LEGACY_PAGESdict. Thepage_handler(template_name)factory uses a closure to correctly capturetemplate_nameper iteration. /healthendpoint returns{"status": "ok"}and is used for uptime monitoring and load-balancer health checks.
Dependencies
requirements.txt
| Package | Purpose |
|---|---|
fastapi[standard] | The web framework. The [standard] extra bundles uvicorn (ASGI server for local development), pydantic (request/response validation), python-multipart, and other commonly needed extras. |
jinja2 | The HTML templating engine used to render .html templates from the templates/ directory. |
The
/login and /registro pages render client-side forms only — there is no backend user authentication in FastAPI. Form submissions are handled by Login.js and registro.js respectively, which call an external Google Apps Script endpoint directly from the browser. Python never sees the credentials.