SpaceX-Launch-Tracker: SpaceX Launch Tracker: How a Tiny Favorites Layer Turns a Public API Into a Personal Mission Control
A React and Node app that keeps the SpaceX feed public, keeps user data minimal, and uses just enough backend logic to make the experience feel tailored.
- This repo is less a launch tracker than a personalization layer that makes public SpaceX data feel privately owned.
- The backend stays lean by storing only the minimum favorite state and merging it back into the public feed at read time.
- The UI does product work by using theme-synced video backgrounds to turn a utility into a branded experience.
- Its value sits between a demo and a polished tracker, which makes it a strong example of how small systems can feel complete.
The interesting move here is not the SpaceX data. It is the tiny private layer wrapped around it. SpaceX Launch Tracker lets a user favorite launches, then stitches that personal state back onto a public API so the experience feels owned without copying the whole universe into its own database.
SpaceX Launch Tracker: Stay up-to-date with the latest and past SpaceX launches.
The real product is not the launch feed
Most launch trackers are variations on the same idea: fetch missions, render cards, add filters. This one is different because it gives the user a way to say, in effect, "this launch matters to me." That is a small product decision with a large effect. The feed stops feeling like a catalog and starts feeling like a collection.
That is why the favorites feature matters more than the rocket data. It turns a generic dashboard into a personal mission control panel, and it does it with almost no extra surface area.
A minimal backend that only stores what it must
The backend behaves like a personalization service, not a warehouse. It keeps user accounts, JWT auth, and a small favorites record that stores only what is needed to reconstruct intent later: a user, a launch, and a bit of metadata for display.
favoriteSchema.index({ userId: 1, launchId: 1 }, { unique: true });
const { data: rocket } = useFetch(
launch?.rocket ? `https://api.spacexdata.com/v4/rockets/${launch.rocket}` : null
);
That unique compound index is the kind of detail that quietly makes the whole product feel disciplined. It prevents duplicate favorites at the database level, so the app can stay simple everywhere else. The frontend then reads like a projection of two sources, not a pile of stateful exceptions.
How the app fetches one thing, then the next
The data flow is deliberately reactive. A launch detail page fetches the launch first, then conditionally fetches the related rocket only if the first request returns a rocket ID. That keeps the code small, but it also avoids guessing about downstream data before it exists.
The custom `useFetch` hook centralizes loading and error state, so the rest of the UI can stay focused on composition. In practice, that means the app is not over-engineered, just well partitioned.
| Approach | What happens | Trade-off |
|---|---|---|
| Naive fetch-all | Pull launch and rocket data together up front | Simple, but wastes requests and makes dependency chains harder to reason about |
| Reactive fetch | Fetch the launch first, then fetch the rocket only if needed | Slightly more logic, much cleaner data flow |
That pattern matters because launch data is nested and uneven. Reactive fetching keeps the interface honest about what it knows and when it knows it.
The UI is doing product work, not decoration
The dual-video background and theme context are not just style flourishes. They make the app feel like a place with a point of view. Dark mode reads like deep space. Light mode reads like Mars. The interface is doing branding through state.
That matters because the app is small. A large product can lean on breadth. A compact one needs atmosphere, and this repo gets that from a few well-placed visual decisions.
This sits between a demo and a real product
Compared with the raw SpaceX API, this repo adds interpretation. Compared with more polished launch products, it stays narrow and teachable. That is its lane: a clean example of how to personalize a public feed without turning it into a sprawling platform.
| Layer | Data source | Personalization | UI polish | Scope |
|---|---|---|---|---|
| SpaceX API | Public launch data | None | None | Source only |
| This repo | SpaceX API plus private favorites | Lightweight user overlay | Strong for a small app | Focused and readable |
| Next Spaceflight | Multiple data sources and product curation | High | High | Broad and feature rich |
The point is not to beat bigger launch apps at their own game. The point is to show how a public data feed can become personal with a minimal backend, a disciplined fetch strategy, and a visual system that knows exactly what story it is telling.