Deficit
locked in.
1,305 kcal and 92 g of protein left today. One Home Screen widget keeps you honest, 82.6 kg headed for 80.0.
Add the widgetweight
82.6 kg · target 80.0
left today
1305 kcal · 92g
Today at a glance
Each number is the live value your widget pulls from the endpoint below. They all come from the same source, so the dashboard, the API, and the widget can't disagree.
The data behind the widget
A tiny JSON endpoint serves the exact same numbers the page shows, so your Scriptable widget always reads fresh, consistent values.
{
"calories": 695,
"calorieTarget": 2000,
"caloriesRemaining": 1305,
"protein": 48,
"proteinTarget": 140,
"proteinRemaining": 92,
"weight": 82.6,
"weightTarget": 80,
"status": "Deficit locked in"
}Single source
The page and the widget both read this endpoint. Change one number here and both update together.
Grab the widget
Paste this script into Scriptable and it fetches the endpoint to render a clean widget on your Home Screen.
// Kaan - Deficit Widget
// Fetches live stats from the dashboard and renders a clean iOS widget.
// Learn how to add this widget at the bottom of the dashboard page.
const ENDPOINT = "https://widget.decidueye.poke.site/api/stats";
async function loadStats() {
const req = new Request(ENDPOINT);
req.headers = { "Content-Type": "application/json" };
return await req.loadJSON();
}
function drawProgress(rect, from, to, color, bgColor, radius) {
const ctx = new DrawContext();
ctx.size = new Size(rect.width * 2, rect.height * 2);
ctx.opaque = false;
ctx.setFillColor(bgColor);
ctx.addRoundedRect(new Rect(0, 0, rect.width * 2, rect.height * 2), radius * 2);
ctx.fillPath();
const width = Math.max(rect.width * 2 * to, radius * 2);
ctx.setFillColor(color);
ctx.addRoundedRect(new Rect(0, 0, width, rect.height * 2), radius * 2);
ctx.fillPath();
return ctx.getImage();
}
function addBar(widget, value, max, label, color) {
const pct = Math.max(0, Math.min(1, value / max));
const stack = widget.addStack();
stack.layoutHorizontally();
stack.addSpacer();
const val = stack.addText(value.toString());
val.font = Font.blackRoundedSystemFont(22);
val.textColor = Color.white();
stack.addSpacer(8);
const of = stack.addText("/ " + max);
of.font = Font.regularSystemFont(12);
of.textColor = new Color("#8A9590");
stack.addSpacer();
const labelStack = stack.addStack();
labelStack.layoutVertically();
labelStack.bottomAlignContent();
const lbl = labelStack.addText(label);
lbl.font = Font.semiboldSystemFont(11);
lbl.textColor = color;
widget.addSpacer(4);
const barTop = 96;
const barH = 6;
const track = new Color("#232A27", 1);
const bar = new Rect(16, barTop, 274, barH);
const img = drawProgress(bar, 0, pct, color, track, 3);
const imgNode = widget.addImage(img);
imgNode.imageSize = new Size(bar.width, bar.height);
imgNode.centerAlignImage();
widget.addSpacer(14);
}
async function createWidget() {
const data = await loadStats();
const widget = new ListWidget();
widget.backgroundColor = new Color("#0E1110");
widget.setPadding(14, 16, 14, 16);
const header = widget.addStack();
header.layoutHorizontally();
const title = header.addText("Kaan · Deficit");
title.font = Font.semiboldSystemFont(13);
title.textColor = new Color("#8A9590");
header.addSpacer();
const statusDot = header.addText("●");
statusDot.font = Font.heavySystemFont(11);
statusDot.textColor = new Color("#34D399");
widget.addSpacer(14);
addBar(widget, data.calories, data.calorieTarget, "calories", new Color("#34D399"));
addBar(widget, data.protein, data.proteinTarget, "protein", new Color("#7AA7D6"));
widget.addSpacer(6);
const foot = widget.addStack();
foot.layoutHorizontally();
const w = foot.addText(
"Weight " + data.weight + " kg · target " + data.weightTarget + " kg"
);
w.font = Font.regularSystemFont(11);
w.textColor = new Color("#8A9590");
foot.addSpacer();
const rem = foot.addText(
data.caloriesRemaining + " kcal left · " + data.proteinRemaining + "g protein left"
);
rem.font = Font.mediumSystemFont(11);
rem.textColor = new Color("#F2F5F3");
return widget;
}
const widget = await createWidget();
if (config.runsInWidget) {
Script.setWidget(widget);
} else {
widget.presentMedium();
}
Script.complete();
Set it up on iOS
Three quick steps and your deficit is on your Home Screen, at a glance.
- 1
Install Scriptable
Download Scriptable from the App Store, open it, and tap the plus icon to create a new script.
- 2
Paste the script
Copy the code below, open your new script in Scriptable, paste, and rename it (for example “Deficit Widget”).
- 3
Add to your Home Screen
Long-press your home screen, tap the plus, search for Scriptable, and pick the medium widget. Edit it, tap the script, choose “Deficit Widget”, and place it.