← Back to portfolio
Case Study · 17 / 17
Full-Stack · Django + React · 2025

One number,
done the right way.

TempTracker shows the current temperature for a city — that's it. The value of building it was everything around that number: keeping the API key on the server, drawing a clean Django/React boundary, and handling the failure cases a "simple" app quietly hides.

Role
Solo — full-stack build
Purpose
Clean frontend/backend split
Stack
Django · React · Tailwind · OpenWeatherMap
Status
Open-source project
Fig. 17 · request → API → degrees
17
The secret to a "simple" app is where you decide to hide the API key.
§ 01 — The intent

A tiny app is the honest place to learn a pattern.

Fetching a temperature is trivial. Fetching it properly — without leaking an API key into the browser, with a clean split between the React client and the Django server — is the reusable skill, and a one-number app is the cheapest place to practise it without any other complexity in the way.

So TempTracker is small on purpose: a focused exercise in the frontend-calls-backend-calls-third-party pattern that every real integration repeats.

If the browser can see your API key, it isn't a secret.

§ 02 — Constraints

The rules that made it worth building.

§ 03 — Architecture

React asks Django, Django asks the world.

The flow is a clean relay: the React app requests the Django endpoint on load, Django calls OpenWeatherMap with the secret key, and the temperature and city come back as JSON the client renders.

01 — Client
React
On load, requests /api/temperature/ — no third-party knowledge.
02 — API
Django view
Reads the secret key from env and calls OpenWeatherMap server-side.
03 — Source
OpenWeatherMap
Returns live conditions for the requested city.
04 — Render
JSON out
Temperature + city returned as JSON and shown in the Tailwind UI.

Routing the call through Django rather than fetching OpenWeatherMap straight from React is the whole lesson: it's the one place the API key can live without being shipped to every visitor's browser.

§ 04 — What broke first

CORS is the tax on a split stack.

The predictable first wall was CORS. React on one origin and Django on another means the browser blocks the request until the server explicitly allows it — the classic "it works in the terminal but fails in the browser" moment. Installing and configuring django-cors-headers was the fix, and understanding why it was needed was the actual value.

The second was configuration hygiene: an app that silently fails when the key is missing is worse than one that says so, which is why the error path got as much attention as the happy one.

1
JSON endpoint the frontend depends on
0
API keys shipped to the browser
2
Origins the CORS config has to reconcile
§ 05 — Design

Readable at a glance.

The interface is a single responsive card — temperature, city, and nothing competing for attention — styled with Tailwind. For an app whose entire job is to surface one number, the design brief was simply to make that number unmissable and the whole thing pleasant to look at.

§ 06 — What I'd do differently

Three things, next time.