This project is a full-stack Pokémon data application consisting of:
- A Python backend API (FastAPI) that fetches, normalizes, and validates Pokémon data from external sources
- A React frontend that queries the backend and renders a consistent Pokémon card UI
- A clearly defined data contract (
PokemonCard) shared implicitly between backend and frontend
The project emphasizes clear data modeling, strict contracts, and debuggable system flow over feature breadth.
Frontend (React)
↓ HTTP (fetch)
Backend API (FastAPI)
↓ Service Layer
External Pokémon APIs
- Frontend is stateless beyond UI state
- Backend owns data normalization and validation
- External APIs are treated as untrusted inputs
The canonical data structure for the entire application.
| Field | Type | Notes |
|---|---|---|
id |
int |
Pokémon ID |
name |
str |
Pokémon name |
types |
List[str] |
Flattened strings, not nested objects |
sprites |
SpriteUrls |
Image URLs |
evolution |
EvolutionInfo |
Evolution chain metadata |
| Field | Type |
|---|---|
default |
str | None |
official |
str | None |
| Field | Description |
|---|---|
root |
First Pokémon in the evolution chain |
stages |
Linear list of evolution names |
current_index |
Index of the current Pokémon in stages |
- Production:
https://pokemon-backend-wvbb.onrender.com - Local:
http://127.0.0.1:8000
All data routes must start with:
| Code | Meaning |
|---|---|
404 |
Pokémon not found (user error) |
500 |
Internal server error (code error) |
PokemonSearch.jsxis deprecated- Active search logic lives in
App.jsx - Do not add new features to
PokemonSearch.jsx
Use this section when debugging behavior, tracing failures, or onboarding.
- User submits a Pokémon name in
App.jsx - UI state changes to
"loading" fetchPokemon(name)is called- Builds URL using
API_BASE - Sends a
GETrequest
- Builds URL using
main.pyreceives the request- CORS middleware validates origin
api.pyroutes/pokemon/{name}- Delegates to
pokemon_service.get_pokemon_card()
- Delegates to
-
pokemon_service.pyorchestrates data retrieval- Fetch Pokémon stats
- Fetch species data
-
Evolution resolution
- Fetches evolution-chain URL
- Runs DFS over
evolves_to - Produces a linear evolution path
- Determines
current_index
-
Data normalization
- Flattens nested API responses
-
Contract enforcement
- Packs data into
PokemonCard - Applies defaults via Pydantic
- Packs data into
-
Response
200 OKon success404if Pokémon not found
-
Frontend receives JSON
-
PokemonCard.jsxrenders:
- Image fallback: Official → Default → Placeholder
- Evolution chain rendered as
a → b → c
- Backend normalizes, frontend renders
- External APIs are untrusted
- Data contracts are explicit
- Errors are translated at boundaries
- UI reflects async state explicitly
This project is feature-frozen.
Future work should:
- Respect existing data contracts
- Preserve system trace assumptions
- Avoid modifying legacy components unless refactoring intentionally