The mistake worth avoiding before you write the fetch
The obvious Next.js odds page fetches on every request. With three visitors that is fine. With three hundred it fails in a nasty way: at a few credits per call, one request per view spends a free month's allowance in a few hundred page views. A link that does well does not slow your site down, it empties your key — and then every visitor gets a 402 at once, including the ones who were already reading.
The fix is one line of Next.js and it is the whole design: revalidate on a timer, not per request. One upstream call every N seconds, shared by every visitor, and traffic is decoupled from spend. A thousand visitors in a minute cost exactly what one visitor costs.
The second decision is what to do when the upstream call fails. Serving the last good snapshot with its age displayed beats serving an error page: a board that is ninety seconds old and says so is worth more than a blank one. Both patterns are in the deployable Cloudflare Worker starter, which is the same design in a different runtime.
- Server components and route handlers
- Timer-based revalidation, not per-request fetching
- Typed responses, so the JSX knows the shape
- Works on Vercel Edge as well as Node
- Free API key to build against
Example API calls
npm install puntersedge
// app/odds/page.tsx — a server component.
import { PuntersEdge } from "puntersedge";
// ONE upstream call per minute, shared by every visitor. Without this you are
// billed per page view, and a busy day costs more than a busy month should.
export const revalidate = 60;
export default async function OddsPage() {
const pe = new PuntersEdge({ apiKey: process.env.PUNTERSEDGE_API_KEY });
const races = await pe.racing.bestOdds({ numRaces: 6, categories: "horse" });
return (
<main>
{races.map((race) => (
<section key={race.race_id}>
<h2>{race.venue} R{race.race_number}</h2>
{race.runners.map((r) => (
<div key={r.name}>
{r.name} — {r.best_win?.price} @ {r.best_win?.bookmaker}
</div>
))}
</section>
))}
</main>
);
}
curl "https://api.puntersedge.online/v1/racing/next-to-go?num_races=5" \
-H "X-API-Key: YOUR_API_KEY"