This repo contains Val Town-ready scripts that:
- fetch Notion entries for the last 7 days (UTC)
- send a weekly blood sugar rollup via email
- enrich food log entries with estimated macros and write them back to Notion
Think of this as two simple helpers:
- You write down blood sugar readings in Notion.
- Once a week, the script looks at the last 7 days and emails you a summary.
- You write down foods you ate in another Notion database.
- The food script estimates macros and fills them in.
Even though this feels simple, it uses a few classic CS ideas:
- Data modeling: you define what a “reading” is (date, time, value).
- Filtering: you only look at a specific window of time (last 7 days).
- Aggregation: you summarize many values into a few stats (avg/min/max).
- Automation: a scheduled job runs the same steps every week.
If you can build or understand this, you’re already practicing real CS thinking—just without the scary jargon.
This project includes playful, Praise Cage-themed badges:
- “Mandy-Mode Consistency”
- “Cage Match: Full Week”
- “Cage Match: Double-Check Champion”
- “National Treasure: Healthy Average”
You can rename or swap these in collectors/blood_sugar_report.cron.tsx.
This report is for informational purposes only and is not medical advice. Healthy blood sugar ranges referenced here come from: https://www.ynhhs.org/articles/what-is-healthy-blood-sugar
Create a new database in Notion (table view is easiest) with these properties:
- Entry (Title)
- Created time (Created time)
- Blood Sugar Level (Number)
You can name the database anything (e.g., "Blood Sugar Log").
Create another Notion database with these properties (exact names expected):
food(Title or Text)Created time(Created time)event type(Select)eating window(Select)normalized items json(Text)enrichment confidence(Number)enrichment source(Text)calories(Number)protein(Number)carbs(Number)fats(Number)fiber(Number)sugar(Number)sodium(Number)
Only food and Created time are required for reading. The enrichment val will create/update the event metadata
properties automatically on the Notion database if they are missing.
The food val now treats each row as an eating event, stores normalized item JSON plus an enrichment confidence score,
and uses a simpler enrichment flow: heuristic item parsing first, OpenAI only when needed, then a cached FatSecret lookup.
Macros are scaled by the inferred serving size using FatSecret's default serving.
Example:
- Input:
shrimp lo mein - OpenAI normalization:
{ "items": [{ "name": "shrimp lo mein", "servings": 1 }] } - FatSecret returns macros per default serving, and the val writes those directly.
- Input:
2 slices pepperoni pizza and salad - OpenAI normalization:
{ "items": [{ "name": "pepperoni pizza", "servings": 2 }, { "name": "salad", "servings": 1 }] } - The val scales each item's macros by its servings and sums the results.
- Go to https://www.notion.so/my-integrations and create a new integration.
- Copy the Internal Integration Token.
- Open your database in Notion, click Share, and invite the integration.
Open each database in the browser and copy the 32‑character ID in the URL.
Create new Vals with the vt CLI, then sync from this repo:
vt create blood_sugar_report
vt create food_report
vt create monthly_report_page
vt create blood_sugar_live_dashboard
vt create food_blood_sugar_correlation
Replace each generated Val file with the corresponding script from this repo:
collectors/blood_sugar_report.cron.tsxcollectors/food_report.cron.tsxservices/monthly_report_page.http.tsxservices/blood_sugar_live_dashboard.http.tsxservices/food_blood_sugar_correlation.http.tsx
Then push each Val:
vt push
Shared:
NOTION_TOKEN
Blood sugar val:
NOTION_BLOOD_SUGAR_DB_IDREPORT_FROM_EMAIL(optional, must beyour_username.valname@valtown.email)REPORT_FROM_NAME(optional)REPORT_REPLY_TO(optional)
Food log val:
NOTION_FOOD_DB_ID
Free tier note: the blood sugar val emails the account owner by default.
The food val uses Val Town's std/openai proxy with gpt-5-nano, so no OpenAI API key is required.
The monthly report val renders a Memphis-inspired report page from SQLite rollups, with a month selector and partial-week toggle (auto-refresh). The blood sugar live dashboard val queries Notion in real time and shows all-time averages, AM/PM averages, and a consistency score across your full tracking history. The food correlation dashboard val queries both Notion databases live and compares eating-event rhythm, late-night intake, and daily spread against blood sugar readings.
In Val Town, schedule the Val to run weekly at 9:30am on Tuesdays (EST).
Suggested cron (set Val Town timezone to EST):
30 9 * * 2
Cron is a simple way to say “run this on a schedule.” It has five fields:
minute hour day-of-month month day-of-week
So 30 9 * * 2 means:
- minute = 30
- hour = 9
- day-of-month = * (every day of the month)
- month = * (every month)
- day-of-week = 2 (Tuesday)
In other words: every Tuesday at 9:30am.
- Adjust the stats, date range, or email formatting in
collectors/blood_sugar_report.cron.tsx. - If you prefer different property names, update them in the script.
- Weekly rollups for both categories are persisted to Val Town SQLite for monthly/quarterly summaries.
- Monthly report page supports query params:
?month=YYYY-MM(defaults to previous month)?partial=trueto include overlapping weeks
- Blood sugar live dashboard is real time: each request re-reads the blood sugar Notion database and recalculates all-time stats.
- Food correlation dashboard is real time: each request re-reads food and blood sugar entries from Notion and recalculates the correlation view.
Run tests:
deno test --allow-import --allow-env=VAL_TOWN_API_KEY --reporter=dot
Run lint:
deno lint
Made with 🖖 by Paul Chin Jr. and Markal.
