KaanDecidueye

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 widget
Deficit locked in82.6 kg
Kaan · Deficitlive
695/ 2000
calories
48/ 140
protein

weight

82.6 kg · target 80.0

left today

1305 kcal · 92g

●updated just now
01

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.

Calories
1,305 kcal remaining
695/ 2,000 kcal
Protein
92 g remaining
48/ 140 g
Weight
target 80.0 kg
82.6kg
82.6 kgtarget 80.0
02

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.

GET https://widget.decidueye.poke.site/api/stats
{
  "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.

03

Grab the widget

Paste this script into Scriptable and it fetches the endpoint to render a clean widget on your Home Screen.

scriptable.jsfetches https://widget.decidueye.poke.site/api/stats
// 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();
04

Set it up on iOS

Three quick steps and your deficit is on your Home Screen, at a glance.

  1. 1

    Install Scriptable

    Download Scriptable from the App Store, open it, and tap the plus icon to create a new script.

  2. 2

    Paste the script

    Copy the code below, open your new script in Scriptable, paste, and rename it (for example “Deficit Widget”).

  3. 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.