Project 7
Project 7 · Capstone
Dashboard Capstone — React Query, Next.js, Charts
Pulling together routing, server data, and visualization into one real-feeling application
Difficulty: Capstone
Introduces: React Query, Next.js, Recharts
Skills This Project Exercises
React Query (useQuery)
Next.js file-based routing
Dynamic routes
Charting (Recharts)
Loading/error states, simplified
Next.js — the minimum you need for this project
Scaffold with npx create-next-app@latest. The headline difference from Vite: pages are defined by the file system rather than by code you write yourself — a file at app/page.js becomes the / route, and a folder named app/coin/[id]/page.js becomes a dynamic route matching /coin/anything, with anything readable inside that page via Next's routing hooks. Everything learned about components, props, and state still applies unchanged — Next.js only changes how a component becomes a "page."
React Query — the minimum you need for this project
Install with npm install @tanstack/react-query, and wrap the app once in a <QueryClientProvider>. From there, useQuery replaces the entire "useState + useEffect + manual loading/error flags" pattern from earlier projects in one hook call:
const { data, isLoading, isError } = useQuery({
queryKey: ["coins"],
queryFn: () => fetch("https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd").then((r) => r.json()),
});
React Query handles the loading/error state, caches the result under queryKey, and can automatically refetch it later — all without a single useEffect written by hand.
Suggested Data Source
The CoinGecko API is free and needs no API key for its public market-data endpoints — a good fit for a dashboard with multiple live-updating widgets and a price history chart per item.
Requirements
- An overview page listing several items (e.g. top cryptocurrencies) with at least name, current price, and 24h change, fetched with
useQuery. - Clicking an item navigates (via Next.js routing) to a detail page for that specific item, at a dynamic URL.
- The detail page fetches and renders a price-history chart using Recharts (a line chart is enough).
- Loading and error states on both pages are handled entirely through React Query's
isLoading/isErrorflags — no manually-managed loading state alongside it. - The overview page's data refreshes automatically after some interval (React Query's
refetchIntervaloption) without a manual page reload. - The layout reads reasonably on both a desktop-width and a narrow/mobile-width viewport.
Suggested Component Breakdown
app/layout.js // wraps everything in QueryClientProvider
app/page.js // route "/" — DashboardPage
└── DashboardPage
└── CoinList // useQuery — list of coins
└── CoinCard (×N) // Link to /coin/[id]
app/coin/[id]/page.js // route "/coin/:id" — CoinDetailPage
└── CoinDetailPage
└── PriceChart // useQuery — price history; Recharts LineChart
A Reasonable Build Order
- Scaffold the Next.js app and confirm the default starter page runs, before changing anything.
- Install React Query, set up
QueryClientProviderin the root layout, and get oneuseQuerycall successfully logging fetched data to the console. - Build
CoinList/CoinCard, rendering real data from that query, each card linking to its own dynamic detail route. - Build the dynamic route page, reading the id from the URL and firing a second
useQueryfor that specific item's history data. - Install Recharts and get a
<LineChart>rendering the fetched price-history data on the detail page. - Add
refetchIntervalto the overview query last, and confirm (via the network tab) that it's actually refetching on its own over time.
Don't re-introduce manual loading state on top of React Query
A common mistake when first adopting React Query is keeping an old habit alive — adding a separate useState for loading/error on top of the isLoading/isError React Query already provides. That duplicates logic React Query is specifically meant to remove; lean entirely on the flags useQuery returns instead.
Stretch Goals
- Add a Next.js API route as a thin proxy to the external API, avoiding any rate-limit/CORS concerns on the client.
- Add a search/filter box on the overview page.
- Add a second chart type (e.g. a bar chart comparing 24h change across items).
- Add a dark/light theme toggle, persisted across visits.
- Deploy the finished app to Vercel — Next.js's own hosting platform, built for exactly this kind of project.
This project has no single solution file — the requirements above and your own judgment are the spec. This also wraps up the React Projects course: seven briefs, beginner through capstone, covering everything from a first todo list to a real multi-tool dashboard.