Nutrition Facts Template
- Next.js
- TypeScript
Calories and macros for any food, scaled to a real serving, with a running total for your plate.
A Next.js nutrition app. Search a food such as banana or brown rice, pick a serving size from the list the data provides, and see its calories with a ring showing how much comes from protein, carbs and fat, plus fiber and sugars. Add foods to a plate for a meal total kept on the device. Use it as a food tracker, or lift the route to add nutrition data to a recipe or fitness app.

What it does
- Real serving sizes
- Choose 100 g or a serving like one medium banana; every number rescales to match.
- Where calories come from
- A ring splits the calories between protein, carbs and fat, with each macro in grams beside it.
- My plate
- Add foods for a running meal total with its macro split, saved in the browser on that device.
- Phone and desktop
- Designed phone-first; on a wide screen the plate sits beside the food card.
- Keeps your key private
- The browser only calls your own API route, which checks the search, caches foods for a day and limits each visitor to 10 lookups a minute.
How it works
The API route: it checks the food, answers from the cache when it can, and calls Nutrition.
/** GET /api/nutrition?food=...: nutrition per 100 g, with serving sizes, from the Nutrition API. */
export async function GET(request: Request) {
const food = str(new URL(request.url).searchParams.get('food'), 60).toLowerCase();
if (!food) return fail('Type a food, like “banana” or “brown rice”');
if (!/^[\p{L}0-9' ,.&-]+$/u.test(food)) return fail('Use letters and spaces only');
const key = `nutrition:${food}`;
const hit = fromCache(key, TTL_MS);
if (hit) return Response.json(hit);
const blocked = guard(request);
if (blocked) return blocked;
return respond(async () => {
const data = await callApi('nutrition', { query: { food } });
toCache(key, data);
return data;
});
}Deploy it
- Get a free API key
The free plan includes 200 credits a month, no card needed. Create your key.
- Deploy it
Click Deploy to Vercel. Vercel copies the repo to your GitHub account and asks for
APIVERVE_API_KEY: paste your key there. - Open your app
Vercel builds it and gives you a live URL, usually in about a minute. Every push to the repo redeploys it.
Try the Nutrition API — the call this template makes
No key required to try it. Get a key to use it in your app.
{
"status": "ok",
"error": null,
"data": {
"food": "Bananas, raw",
"fdcId": 173944,
"category": "Fruits and Fruit Juices",
"basis": "per 100g",
"servingSizes": [
{
"label": "1 NLEA serving",
"grams": 126
},
{
"label": "1 extra large (9\" or longer)",
"grams": 152
},
{
"label": "1 large (8\" to 8-7/8\" long)",
"grams": 136
}
],
"nutrition": {
"calories": 89,
"protein": 1.09,
"totalFat": 0.33,
"carbohydrates": 22.8,
"fiber": 2.6,
"sugars": 12.2
},
"micronutrients": {
"sodium": 1,
"potassium": 358,
"cholesterol": 0,
"saturatedFat": 0.112,
"transFat": 0,
"monounsaturatedFat": 0.032,
"polyunsaturatedFat": 0.073,
"calcium": 5,
"iron": 0.26,
"magnesium": 27,
"phosphorus": 22,
"zinc": 0.15,
"vitaminC": 8.7,
"vitaminA": 3,
"vitaminD": 0,
"vitaminE": 0.1,
"vitaminK": 0.5,
"thiamin": 0.031,
"riboflavin": 0.073,
"niacin": 0.665,
"vitaminB6": 0.367,
"folate": 20,
"vitaminB12": 0,
"water": 74.9
},
"analytics": {
"caloriesPerGram": 0.89,
"proteinCaloriePercent": 4.4,
"fatCaloriePercent": 3,
"carbCaloriePercent": 92.6,
"proteinPer100Calories": 1.22
},
"dailyValues": {
"protein": 2.2,
"totalFat": 0.4,
"saturatedFat": 0.6,
"cholesterol": 0,
"sodium": 0,
"carbohydrates": 8.3,
"fiber": 9.3,
"potassium": 7.6,
"calcium": 0.4,
"iron": 1.4,
"magnesium": 6.4,
"phosphorus": 1.8,
"zinc": 1.4,
"vitaminC": 9.7,
"vitaminA": 0.3,
"vitaminD": 0,
"vitaminE": 0.7,
"vitaminK": 0.4,
"thiamin": 2.6,
"riboflavin": 5.6,
"niacin": 4.2,
"vitaminB6": 21.6,
"folate": 5,
"vitaminB12": 0
},
"dietaryFlags": {
"highProtein": false,
"goodSourceOfProtein": false,
"highFiber": false,
"goodSourceOfFiber": false,
"lowSodium": true,
"lowFat": true,
"lowSaturatedFat": true,
"lowCholesterol": true,
"lowCalorie": false
}
}
}