🕵️ SicherheitslückenHak5: Hackers Just Poisoned the Rust Supply Chain | Threat Wire(01.09.2026 um 14:00 Uhr)
🕵️ SicherheitslückenHak5: Hackers Found a Way Into Humanoid Robots | Threat Wire(04.09.2026 um 15:04 Uhr)
🔧 AI Nachrichten Bits und so #1021 (Passwort für Laufwerk)(31.08.2026 um 22:15 Uhr)
🔧 AI Nachrichten Bits und so #1022 (Wie Weißbier)(06.09.2026 um 20:39 Uhr)
🍏 iOS / Mac OSHue-App 6.0 ist da: das sind die Neuerungen(07.09.2026 um 17:21 Uhr)
🕵️ SicherheitslückenHak5: Hackers Just Poisoned the Rust Supply Chain | Threat Wire(01.09.2026 um 14:00 Uhr)
🕵️ SicherheitslückenHak5: Hackers Found a Way Into Humanoid Robots | Threat Wire(04.09.2026 um 15:04 Uhr)
🔧 AI Nachrichten Bits und so #1021 (Passwort für Laufwerk)(31.08.2026 um 22:15 Uhr)
🔧 AI Nachrichten Bits und so #1022 (Wie Weißbier)(06.09.2026 um 20:39 Uhr)
🍏 iOS / Mac OSHue-App 6.0 ist da: das sind die Neuerungen(07.09.2026 um 17:21 Uhr)

🔧 Programmierung 🕛 kürzlich 5 Min Lesezeit
0

Build a Calorie Tracker with DietlyAPI

↗ Quelle (dev.to)
🗣️ Stimme:
📑 Inhaltsübersicht




Build a calorie-tracker web app in a weekend



A useful calorie tracker needs three things: a food search, a daily list, and an explainable per-serving calculation. You can build all three as a single client-side page backed by DietlyAPI and the browser's local storage, with no server and no build step. This guide walks the whole app end to end, then shows where to grow it once people actually use it.






What you are building



One HTML file. A search box calls GET /search as the user types. Tapping a result adds it to today's log with an editable gram amount. A running total sums every entry using the same math. Everything persists in localStorage, so a refresh keeps the day. That is a genuinely usable tracker, and it never exposes a privileged key because the read endpoint is public.






1. Search foods as the user types



Wait for at least two characters (the API's minimum for q), debounce so you are not firing a request per keystroke, then render name, brand and the per-100 g calories. Remember the response is a JSON array.




CODE
const API = 'https://api.getdietly.com';
let timer;

function onType(e) {
clearTimeout(timer);
const query = e.target.value.trim();
if (query.length < 2) return;
timer = setTimeout(() => runSearch(query), 250);
}

async function runSearch(query) {
const url = new URL(API + '/search');
url.search = new URLSearchParams({ q: query, limit: '8' });
const res = await fetch(url);
if (!res.ok) { showError(res.status); return; }
const foods = await res.json();
render(foods); // foods is [] when nothing matched
}









2. Store log entries, not search results



When a person adds a food, keep the ID, a display name, the grams, and a snapshot of the per-100 g calories used in the calculation. The snapshot keeps a past day readable even if the catalog record later changes, and you can always re-fetch the live record with GET /food/{id} when editing.




CODE
function addFood(food) {
const entries = load();
entries.push({
id: food.id,
name: food.name,
grams: 100,
kcal100: food.calories_kcal, // per 100 g snapshot
protein100: food.protein_g
});
save(entries);
draw();
}

const KEY = 'dietly-log';
const load = () => JSON.parse(localStorage.getItem(KEY) || '[]');
const save = (e) => localStorage.setItem(KEY, JSON.stringify(e));









3. Make totals inspectable



Sum every entry with one grams-to-100 g formula, round only for display, and let the total open into the entries that produced it. A missing nutrient is unavailable, not zero, so skip nulls in the sum instead of coercing them.




CODE
function totals(entries) {
return entries.reduce((acc, e) => {
if (e.kcal100 != null) acc.kcal += e.kcal100 * e.grams / 100;
if (e.protein100 != null) acc.protein += e.protein100 * e.grams / 100;
return acc;
}, { kcal: 0, protein: 0 });
}

function draw() {
const entries = load();
const t = totals(entries);
document.querySelector('#total').textContent =
`${Math.round(t.kcal)} kcal, ${Math.round(t.protein)} g protein`;
}









4. Let people edit grams without a new search



Editing the gram amount is the single most-used action in any tracker. Change it in place and redraw. No network call is needed because you already stored the per-100 g snapshot.




CODE
function setGrams(index, grams) {
const entries = load();
entries[index].grams = Math.max(0, Number(grams) || 0);
save(entries);
draw();
}









5. Handle the ordinary failure states




  • An empty search array is a normal no-match state, not an error. Show "no close match", not a spinner forever.


  • For a 429 response, honor the Retry-After header and never retry in a tight loop.


  • A 404 from /food/{id} means the record is gone; drop the entry gracefully.


  • Explain to users that the log lives in this browser and clearing site data removes it.







6. Wire up the page and ship it



The whole app is one static file: a search input, a results list, and a log with a total. Because there is no build step and no server, you can host it free on any static host (GitHub Pages, Cloudflare Pages, Netlify) by uploading a single index.html. The markup below is all the structure the functions above need.




CODE
<input id="q" oninput="onType(event)" placeholder="Search a food">
<ul id="results"></ul>
<h2>Today</h2>
<ul id="log"></ul>
<p id="total">0 kcal</p>
<script src="app.js"></script>






Render search results as buttons that call addFood, and render the log with a number input bound to setGrams. Call draw() once on load so a returning visitor sees yesterday's total immediately. Keep every DOM update in one draw function; a single render path is far easier to reason about than scattered updates, and it makes the total and the list impossible to get out of sync.



One accessibility note worth the two minutes: give the search input a real <label>, mark the results list as a live region so screen readers announce matches, and keep focus on the input after adding a food so fast entry keeps working. None of this costs performance, and it makes the tracker usable one-handed on a phone, which is where most people log meals.






Where to grow it next



The prototype above is deliberately keyless and local. When you need a shared log across devices, add accounts and server-side storage on your own backend, and move any account-level Dietly calls behind that server so a privileged key never ships in the browser bundle. At that point, create a free key in the rather than reimplementing goal math yourself.



Build contract: use the for rate limits and attribution, and treat every nutrient as possibly null.

Vollständiger Original-Bericht
Ausführliche Details, Code-Beispiele & Hersteller-Stellungnahme auf dev.to.
↗ Original-Artikel auf dev.to lesen
Wie bewertest du diesen Beitrag?
1 Klick Feedback
Teilen mit Netzwerk & Team:

Community-Analysen & Experten-Meinungen 0

Verfasse deine eigene Analyse, teile Workarounds oder diskutiere diesen Vorfall im Blog.
Noch keine Community-Analyse verfasst. Markiere einen Textabschnitt oder klicke oben auf Eigene Analyse verfassen“!
Community Pulse: Relevanz-Einschätzung
1 Klick Experten-Votum
🔴 Akute Relevanz 0%
🟡 In Evaluierung 0%
🟢 Keine Auswirkung 0%
Spannende Innovation 0%
Verwandte Story-Cluster & Quellen (Vektor-KI)
Port 8095 Engine
1 Quelle
Hackers Just Poisoned the Rust Supply Chain | Threat Wire
1 Quelle
Hackers Found a Way Into Humanoid Robots | Threat Wire
1 Quelle
Bits und so #1021 (Passwort für Laufwerk)
Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten Build a Calorie Tracker with DietlyAPI

Thematisch verwandte Begriffe: Build, Calorie, Tracker, with · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...