Build Cronometer Gold
KINDAreplaces $10.99/mosaves $131.88/yrback to the verdict
A food log backed by USDA FoodData Central, which is public domain data: search foods, record portions with real units, see full micronutrient totals rather than only calories, view trends over time in neutral language, and export everything you have logged.
Before step 1
Everything below is assumed from the first step. Tick each one when you actually have it, not when you plan to.
- installfree
Why Runs the build and the copy lint.
Get it nodejs.org, or nvm install 22. open ↗
Verify
node --version prints v22 or higher - API keyfree; roughly one thousand requests per hour per address
Why Without it there is no food data. The demo key exists but is rate limited far below anything usable.
Get it Sign up at fdc.nal.usda.gov/api-key-signup, which issues a free data.gov key by email in a few minutes. No payment details are required. open ↗
Verify
A search request returns results rather than a rate limit error - have readyfree
Why Logging happens away from a desk, and one-handed use and offline behaviour cannot be judged in a desktop browser.
Get it Serve over HTTPS to your phone with a tunnelling tool and install to the home screen.
Verify
It installs to the home screen and opens without browser chrome - decidefree
Why Phase 6 needs a second reader for tone. You cannot audit your own wording for pressure, and this subject matter makes that audit worth more than usual.
Get it Ask one person, hand them the printed strings, and ask specifically whether anything reads as judgement or instruction.
- decidefree
Why Showing population reference figures next to personal totals invites reading them as targets, which is exactly what this application refuses to do.
Get it Decide before Phase 5 whether to show them at all. Omitting them is simpler and safer; showing them requires careful labelling and no comparative colouring.
Verify
The decision and its reasoning are written in the README
Data model
Create these before the first phase that stores anything. Changing a table later is the expensive kind of change.
- foods(fdc_id, description, data_type, brand, serving_json, nutrients_json, cached_at) · cached from the API, keyed by its identifier - portions(id, fdc_id, label, gram_weight) · the named servings the database provides, plus any you add - entries(id, at, fdc_id, quantity, portion_id, grams, meal) · grams is always computed and stored, so a portion definition changing later does not rewrite history - recipes(id, name), recipe_items(recipe_id, fdc_id, grams) · a recipe is a food composed of other foods - nutrient_defs(id, name, unit, display_group) · so the interface can show a full panel rather than four headline numbers - Everything is stored in grams. Portions are an input convenience and a display preference, never the stored quantity.
Environment variables
These go in a .env file the app reads at startup. The pack's .env.example is this table as a file · copy it, never commit the filled-in version.
| Variable | Needed | Example | Where the value comes from |
|---|---|---|---|
VITE_FDC_API_KEYsecret | required | replace-with-your-data-gov-key | Issued free by fdc.nal.usda.gov/api-key-signup. Proxy requests through your own small endpoint if you deploy this anywhere public, so the key is not in the client bundle. |
VITE_FDC_CACHE_MAX | required | 5000 | How many foods to keep cached locally. Higher means fewer API calls and more storage. |
VITE_SEARCH_DEBOUNCE_MS | required | 400 | Search-as-you-type debounce. Lower values burn through the hourly rate limit. |
VITE_SHOW_REFERENCE_INTAKES | required | false | Whether population reference figures appear at all. False is the safer default and requires no careful labelling. |
VITE_EXPORT_REMINDER_DAYS | required | 30 | How often to prompt for an export, because browser storage can be evicted. |
The build, in order
Food data you can actually query
A search returns real foods with real nutrient data, and it works the second time without a network.
Sign up at api.data.gov for a free key. Then fetch one food of each data type and look at what is actually in it before designing anything.
terminalcurl 'https://api.nal.usda.gov/fdc/v1/foods/search?query=oats&api_key=YOUR_KEY'
Store every fetched food. Search the local cache before the network, which is both faster and how you stay under the rate limit.
Files
src/food-cache.tsA nutrient absent from a record is unknown, not zero. This distinction runs through every total you will compute later, so get it right here.
Files
src/nutrients.ts
done when · tick each as it passeswatch out- The API allows roughly a thousand requests an hour per address, which a search-as-you-type box will exhaust in an afternoon. Debounce properly, cache every result, and search the local cache first.
- The data types are not equivalent. Foundation and SR Legacy entries carry full laboratory micronutrient panels; Branded entries carry only what a manufacturer put on the label, which is usually a dozen nutrients. Showing a branded food's empty micronutrient panel as though it were zero is wrong and misleading.
Logging with units that make sense
You can log a cup of something and the grams are right.
Search, pick a portion, set a quantity, choose a meal. Few taps, large targets, because this happens at a table.
Files
src/log.tsGrams computed once at entry. The portion label is kept for display only.
Files
src/units.tsRepeating a previous entry is the most common action after the first week. Make it one tap.
Files
src/log.ts
done when · tick each as it passeswatch out- Storing quantity and portion rather than grams means a corrected portion definition silently rewrites every historical entry that used it. Compute grams at entry time and store them; keep the portion only for display.
Totals that are honest about what they do not know
The daily panel shows full micronutrients and is clear about coverage.
For each nutrient, accumulate the value and count how many entries supplied one. Both numbers go to the interface.
Files
src/totals.tsMacronutrients, vitamins, minerals. A flat list of eighty numbers is not information.
Files
src/nutrients.tsThree foods, computed by hand, asserted in a test. This is the arithmetic everything else depends on.
Files
src/totals.test.ts
done when · tick each as it passeswatch out- Treating a missing nutrient as zero produces a day that appears deficient in something because one branded food did not print it on a label. Track how many of the day's foods actually carried each nutrient and show that count next to the figure.
Recipes and repeated meals
The meal you make every week is logged in one action.
Ingredients in grams, plus a serving count. Grams throughout, exactly as with entries.
Files
src/recipes.tsStore the computed contribution with the entry. The recipe is a template, not a live reference.
Files
src/log.tsA recipe used as an ingredient. Resolve depth-first and guard against a recipe containing itself.
Files
src/recipes.ts
done when · tick each as it passeswatch out- Expanding a recipe by reference at display time means editing the recipe next month changes what you ate last month. Snapshot the nutrient contribution at log time, exactly as with portions and grams.
Neutral trends, enforced by a test
You can see change over time, and the application cannot start judging without a test failing.
Weekly averages per nutrient, gaps preserved. A day with no entries is missing data, not a zero intake day.
Files
src/charts.tsScan interface strings for judgement and diagnostic language: goal, target, over, under, exceeded, cheat, guilty, earned, burn off, good day, bad day, streak. Fail the build, not warn.
Files
scripts/copy-lint.tsscripts/banned-words.jsonIf you show them, label them as population references and never colour by comparison. Omitting them entirely is a legitimate and safer choice.
Files
src/reference.ts
done when · tick each as it passeswatch out- Reference intake figures are population averages for planning, not personal targets, and presenting one as a line labelled goal turns a reference into an instruction. If you show them at all, label them as population references and never colour a value red for falling below one.
Export, and a review by someone elseproduct builder
Your log is portable, and a second person has read what the application says.
JSON with a schema version for completeness, CSV for spreadsheets. Round-trip equality is the test worth having.
Files
src/export.tssrc/import.tsPrint every string. Ask specifically whether anything reads as judgement or instruction. Record what you changed.
Files
docs/tone-review.mdIf it leaves your own device, put a login in front of it. This data should not be reachable by a URL guess.
Files
src/auth.ts
done when · tick each as it passeswatch out- A food log is unusually sensitive personal data and, for some people, a record they would find distressing to see reflected back with any judgement attached. Treat both the data and the wording as things that need another person's eyes before release.
That is the whole plan for Cronometer Gold. What it deliberately does not cover is below · check the gaps before you call it a replacement.
- A curated and deduplicated food database with normalised portions.
- Barcode scanning against a commercial product catalogue.
- Wearable and health platform integrations.
- Any coaching, target setting or nutritional advice.
- curated food database, barcode data, device integrations, reports, and mobile apps
- wearable hardware data
- coach network
- clinical validation
- large content library and social network
- Offline barcode lookup against the branded subset you have already cached
- A weekly summary that reports coverage rather than performance
- Importing a log exported from another tracker, which is mostly a mapping exercise
Need the files? The project pack on the verdict page hands your agent the whole brief · more wellness.