Skip to content

Build a Nutrition App with Next.js

Next.js route handlers are a natural fit for the Calorie API: the API key lives in server-only environment variables, and fetch caching gives you request deduplication and revalidation for free.

Server-side search route

app/api/food-search/route.ts
import { NextRequest, NextResponse } from 'next/server'

const API_BASE = 'https://calorieapiadmin.com/api/v1'

export async function GET(req: NextRequest) {
  const q = req.nextUrl.searchParams.get('q') ?? ''

  const upstream = await fetch(
    `${API_BASE}/search/foods?q=${encodeURIComponent(q)}&limit=20`,
    {
      headers: { 'X-API-Key': process.env.CALORIE_API_KEY! },
      // Identical searches within 5 minutes hit the cache, not your quota
      next: { revalidate: 300 },
    }
  )

  return NextResponse.json(await upstream.json(), { status: upstream.status })
}

Server components for food pages

For food detail pages, fetch directly inside a server component, no client JavaScript needed and the page is fully rendered for crawlers.

app/foods/[id]/page.tsx
export default async function FoodPage({
  params,
}: {
  params: Promise<{ id: string }>
}) {
  const { id } = await params
  const res = await fetch(`https://calorieapiadmin.com/api/v1/foods/${id}`, {
    headers: { 'X-API-Key': process.env.CALORIE_API_KEY! },
    next: { revalidate: 3600 },
  })
  if (!res.ok) notFound()
  const food = await res.json()

  return (
    <article>
      <h1>{food.name}</h1>
      <p>{food.calories} kcal per 100g</p>
    </article>
  )
}

Caching strategy

  • Suggest calls: keep them client → route handler with short (or no) caching; they are user-specific and cheap.
  • Food details: revalidate: 3600 or longer, nutrition data for a given ID changes rarely.
  • Popular searches: revalidate: 300 turns repeated queries into cache hits instead of quota spend.

Environment setup

.env.local
# Server-only, never expose with NEXT_PUBLIC_
CALORIE_API_KEY=your_api_key_here

Frequently asked questions

Should the API key be a NEXT_PUBLIC_ variable?

No, NEXT_PUBLIC_ variables are embedded in client bundles. Use a plain server-side env var and only reference it in route handlers or server components.

Does fetch caching count against my API quota?

Cache hits are served by Next.js without contacting the API, so they cost nothing. Only cache misses and revalidations spend quota.

Related resources