How it works
A slow, rate-limited API, made to feel instant. A chain of caches sits between you and NASA. Each layer only asks the next when it is empty, and fills itself on the way back, so a request stops at the first warm layer.
- Vue Queryclient cache
Holds a copy in your browser. A repeat view renders instantly, with no network at all. Invalidate it to force a fresh look at the server chain.
Docs ↗ - Nitroserver cache · SWR
An in-process, in-memory stale-while-revalidate cache in front of Redis. A warm hit never leaves the server process, so it beats the Redis network hop; while fresh (30s) it answers directly, and once stale it serves the old value instantly AND refreshes in the background, so no request waits for a refresh. It doesn't survive serverless cold starts; then the request simply falls through to Redis.
Docs ↗ - Redisserver cache
The persistent store, shared by every visitor and kept for 24 hours. A plain cache-aside store with no revalidation of its own: when an entry is gone, the next request blocks and refetches, which is exactly the wait that Nitro's SWR avoids. Nitro falls through to Redis on a miss.
Docs ↗ - NASA APOD APIorigin
The single source of truth. Rate-limited and slow (the better part of a second per request), which is exactly why the caches exist.
Docs ↗
Try it yourself
The controls in the footer work on every page. Here is what to watch.
The footer shows the chain with a dot per layer; filled means that cache holds data. The badge on each card and the hero shows which layer is the current active source.
Revalidates the browser cache and refetches from the server chain: Nitro if warm, else Redis, else NASA. The footer reports the source and how long it took.
Empties a server layer. The badge flips instantly to the next layer down. Delete both and the next request goes all the way to NASA: a genuine, rate-limited cold start.
What this is not
Every layer here caches data on its way from NASA to the page. The rendered HTML is a separate question, answered per route: the three static pages let the CDN serve them for an hour, while the APOD routes allow nothing and are rendered per request. A cached page could not honestly report which cache answered, because its labels would be as old as the copy. Route rules, prerendering and ISR are real and useful layers, just not the ones this project is about.
The chain is also more elaborate than most projects need. A Nitro SWR cache in front of Redis earns its place here because you can watch a request stop at it and see what that saves; in production you would usually pick one server cache and move on. Read this as an X-ray of the layers, not as a blueprint to copy.