Big-Banana-Studios/Controlled-Burn

A Anger Managment App

0

stars

4

commits

HTML

primary language

Aug 26, 2026

updated

README

Controlled Burn

v3.1 — Big Banana Studios / Lewis Family

Biofeedback-informed emotional regulation. A Polar H10 chest strap feeds heart rate to the browser over Bluetooth; the app learns a calm baseline and steps in at three escalating thresholds — notice, breathe, leave the room — based on Dr. John Gottman's research on Diffuse Physiological Arousal.

Everything runs on the device. There is no server, no API key, and no request that carries anything typed into it. The model is downloaded once and then runs locally on the GPU.


Deploying to GitHub Pages

git init
git add .
git commit -m "Controlled Burn v3.1"
git branch -M main
git remote add origin https://github.com/<you>/controlled-burn.git
git push -u origin main

Then Settings → Pages → Source: Deploy from a branch → main / (root).

It will be live at https://<you>.github.io/controlled-burn/ in a minute or two.

Nothing here needs a build step. Every path in the app is relative (./sw.js, ./assets/…), which is what lets a project site work from /controlled-burn/ rather than the domain root.

.nojekyll is intentional — it stops GitHub running the files through Jekyll, which would otherwise ignore anything beginning with an underscore.


It has to be served over HTTPS

Opening index.html from the file system will not work. file:// is not a secure context, so the service worker will not register, the module worker cannot import the library, and Web Bluetooth is unavailable.

GitHub Pages is HTTPS, so the deployed app is fine. For local work:

npx http-server . -p 8080
# then open http://127.0.0.1:8080/

localhost counts as a secure context, so everything works there too.


Offline

The app is installable and works with no signal, but the model has to be downloaded once while online. Open the app on wifi, go to any of the AI tabs and press Wake it. That pulls roughly 800 MB.

After that, two separate caches keep it working offline:

WhatWhereManaged by
App shell — HTML, worker, icons, manifestcontrolled-burn-shell-<version>sw.js
Transformers.js library + ONNX Runtime binariescontrolled-burn-shell-<version>sw.js
Model weights (~800 MB)transformers-cacheTransformers.js

sw.js deliberately does not cache the model. Transformers.js already has a better cache for it, and duplicating 800 MB on a phone would be rude. The service worker also never deletes a cache it did not create, so a deploy can never cost you that download.

Heart rate monitoring, the alerts, the notifications and the breathing exercise have no network dependency at all and work offline from the first load.


Browser support

Chrome or Edge on desktop or Android.

  • Web Bluetooth (the Polar H10) — Chrome and Edge only. Not Safari, not Firefox, not any browser on iOS.
  • WebGPU (the model) — needs hardware acceleration switched on.

Without WebGPU the heart rate side still works in full; only the five AI tabs go quiet, and the app says so rather than failing silently. Try Demo simulates a strap if you want to see the thresholds fire without wearing one.


Files

index.html              the whole app - markup, styles, logic
worker.js               LFM2.5 inference, off the main thread
sw.js                   offline cache
manifest.webmanifest    install metadata
assets/                 icons
.nojekyll               tell GitHub Pages not to run Jekyll

The model worker is a separate file for two reasons: generation holds a thread for tens of seconds and would otherwise stall the heart rate listener, and a same-origin worker inherits the page's service worker, which is what lets its library import come from cache when there is no signal.


Releasing a change

Bump VERSION in sw.js. The old shell cache is dropped on activate and the new files take over; the model cache is untouched.

Anyone with the app open sees a quiet update ready link next to the version number rather than being reloaded underneath them — this app can be mid-alert, and nothing should interrupt that.


A trap worth knowing about — manifest id

Every Big Banana app is published on the same origin (big-banana-studios.github.io), which makes the manifest id member load-bearing.

id resolves against the origin, not against the manifest URL. start_url and scope resolve the way you would expect; id does not.

manifest at  https://big-banana-studios.github.io/Controlled-Burn/manifest.webmanifest

"start_url": "./"                  ->  .../Controlled-Burn/     correct
"id":        "./"                  ->  https://big-banana-studios.github.io/    WRONG
"id":        "/Controlled-Burn/"   ->  .../Controlled-Burn/     correct

Two apps on this domain that both say "id": "./" claim the same identity, and the browser treats installing the second as an update to the first — same window, same icon, one app where there should be two.

So: either give id an absolute path, or leave it out entirely, in which case it falls back to the fully-resolved start_url and is unique automatically.

Configuration

Thresholds live in the TH object near the top of the script block in index.html:

TierTriggerSustainCooldown
Yellowbaseline + 8 bpm6s45s
Amberbaseline + 16 bpm8s60s
Redbaseline + 24 bpm, or 100 bpm12s120s

A tier only fires after the heart rate has held above its line for the sustain window. A high water mark stops lower alerts re-firing on the way back down; it clears only when the heart rate drops under the yellow line.

Note that a fast climb still rings all three on the way up — 70 to 96 bpm in one step gives yellow at 6s, amber at 8s, red at 12s. That is deliberate and pinned by a test.


Privacy

Nothing typed into the app leaves the device. The only thing written to disk is an optional resting heart rate — one number, in localStorage, offered on the connect screen and never applied without being chosen. No text, no history, no analytics.


Thinking tool, not a replacement for real conversation.

Contributors

Lilrobodue

4 commits

Big-Banana-Studios/Controlled-Burn

A Anger Managment App

0

stars

4

commits

HTML

primary language

Aug 26, 2026

updated

README

Controlled Burn

v3.1 — Big Banana Studios / Lewis Family

Biofeedback-informed emotional regulation. A Polar H10 chest strap feeds heart rate to the browser over Bluetooth; the app learns a calm baseline and steps in at three escalating thresholds — notice, breathe, leave the room — based on Dr. John Gottman's research on Diffuse Physiological Arousal.

Everything runs on the device. There is no server, no API key, and no request that carries anything typed into it. The model is downloaded once and then runs locally on the GPU.


Deploying to GitHub Pages

git init
git add .
git commit -m "Controlled Burn v3.1"
git branch -M main
git remote add origin https://github.com/<you>/controlled-burn.git
git push -u origin main

Then Settings → Pages → Source: Deploy from a branch → main / (root).

It will be live at https://<you>.github.io/controlled-burn/ in a minute or two.

Nothing here needs a build step. Every path in the app is relative (./sw.js, ./assets/…), which is what lets a project site work from /controlled-burn/ rather than the domain root.

.nojekyll is intentional — it stops GitHub running the files through Jekyll, which would otherwise ignore anything beginning with an underscore.


It has to be served over HTTPS

Opening index.html from the file system will not work. file:// is not a secure context, so the service worker will not register, the module worker cannot import the library, and Web Bluetooth is unavailable.

GitHub Pages is HTTPS, so the deployed app is fine. For local work:

npx http-server . -p 8080
# then open http://127.0.0.1:8080/

localhost counts as a secure context, so everything works there too.


Offline

The app is installable and works with no signal, but the model has to be downloaded once while online. Open the app on wifi, go to any of the AI tabs and press Wake it. That pulls roughly 800 MB.

After that, two separate caches keep it working offline:

WhatWhereManaged by
App shell — HTML, worker, icons, manifestcontrolled-burn-shell-<version>sw.js
Transformers.js library + ONNX Runtime binariescontrolled-burn-shell-<version>sw.js
Model weights (~800 MB)transformers-cacheTransformers.js

sw.js deliberately does not cache the model. Transformers.js already has a better cache for it, and duplicating 800 MB on a phone would be rude. The service worker also never deletes a cache it did not create, so a deploy can never cost you that download.

Heart rate monitoring, the alerts, the notifications and the breathing exercise have no network dependency at all and work offline from the first load.


Browser support

Chrome or Edge on desktop or Android.

  • Web Bluetooth (the Polar H10) — Chrome and Edge only. Not Safari, not Firefox, not any browser on iOS.
  • WebGPU (the model) — needs hardware acceleration switched on.

Without WebGPU the heart rate side still works in full; only the five AI tabs go quiet, and the app says so rather than failing silently. Try Demo simulates a strap if you want to see the thresholds fire without wearing one.


Files

index.html              the whole app - markup, styles, logic
worker.js               LFM2.5 inference, off the main thread
sw.js                   offline cache
manifest.webmanifest    install metadata
assets/                 icons
.nojekyll               tell GitHub Pages not to run Jekyll

The model worker is a separate file for two reasons: generation holds a thread for tens of seconds and would otherwise stall the heart rate listener, and a same-origin worker inherits the page's service worker, which is what lets its library import come from cache when there is no signal.


Releasing a change

Bump VERSION in sw.js. The old shell cache is dropped on activate and the new files take over; the model cache is untouched.

Anyone with the app open sees a quiet update ready link next to the version number rather than being reloaded underneath them — this app can be mid-alert, and nothing should interrupt that.


A trap worth knowing about — manifest id

Every Big Banana app is published on the same origin (big-banana-studios.github.io), which makes the manifest id member load-bearing.

id resolves against the origin, not against the manifest URL. start_url and scope resolve the way you would expect; id does not.

manifest at  https://big-banana-studios.github.io/Controlled-Burn/manifest.webmanifest

"start_url": "./"                  ->  .../Controlled-Burn/     correct
"id":        "./"                  ->  https://big-banana-studios.github.io/    WRONG
"id":        "/Controlled-Burn/"   ->  .../Controlled-Burn/     correct

Two apps on this domain that both say "id": "./" claim the same identity, and the browser treats installing the second as an update to the first — same window, same icon, one app where there should be two.

So: either give id an absolute path, or leave it out entirely, in which case it falls back to the fully-resolved start_url and is unique automatically.

Configuration

Thresholds live in the TH object near the top of the script block in index.html:

TierTriggerSustainCooldown
Yellowbaseline + 8 bpm6s45s
Amberbaseline + 16 bpm8s60s
Redbaseline + 24 bpm, or 100 bpm12s120s

A tier only fires after the heart rate has held above its line for the sustain window. A high water mark stops lower alerts re-firing on the way back down; it clears only when the heart rate drops under the yellow line.

Note that a fast climb still rings all three on the way up — 70 to 96 bpm in one step gives yellow at 6s, amber at 8s, red at 12s. That is deliberate and pinned by a test.


Privacy

Nothing typed into the app leaves the device. The only thing written to disk is an optional resting heart rate — one number, in localStorage, offered on the connect screen and never applied without being chosen. No text, no history, no analytics.


Thinking tool, not a replacement for real conversation.

Contributors

Lilrobodue

4 commits

Languages

HTML

85.7%

JavaScript

14.3%