Prompt for AIHome

Kapsula bridge API

Kapsula runs your HTML in a sandboxed iframe and injects one global object, window.kapsula. Every method returns a Promise. The same file runs unchanged in a desktop browser — just check if (window.kapsula) before using it.

Quick facts

Reference

kapsula.app.info()

{ name, projectId, platform, version, lang, limits }. platform is 'android', 'ios' or 'web'; lang is the shell's interface language ('en', 'ru', 'es', …); limits.alarms is the alarm cap (16). The language is also available synchronously as window.__KAPSULA_PROJECT__.lang.

kapsula.notify.schedule({ at, title, body })

Schedules an exact OS alarm. at — epoch milliseconds or a Date, must be in the future; title ≤ 120 chars (defaults to the project name); body ≤ 300 chars. Returns { id }. On first use the system asks the user for notification permission; if denied, the Promise rejects. Sound and vibration are handled by Kapsula (a built-in alarm sound on both platforms), you don't configure them.

const { id } = await kapsula.notify.schedule({
  at: Date.now() + 25 * 60 * 1000,
  title: 'Break time',
  body: 'Stand up, look away from the screen'
});

kapsula.notify.cancel(id?)

Cancels one alarm by id, or all alarms of this project when called without arguments. Returns { cancelled }. Tip: call cancel() before re-scheduling so the 16-slot limit doesn't fill up.

kapsula.notify.list()

[{ id, at, title, body }] — alarms still pending for this project.

kapsula.storage.get(key) · set(key, value) · remove(key)

Per-project key–value storage that survives app restarts and code updates. value is any JSON-serialisable value; get resolves to it or null. Keep it small (settings, session state), not megabytes.

await kapsula.storage.set('session', { startedAt: Date.now(), step: 3 });
const s = await kapsula.storage.get('session');   // → object or null

kapsula.sound.play(preset)

Plays a short built-in sound while the page is open: 'beep' (default), 'triple', 'alarm'. For sounds while the app is closed, use an alarm instead.

kapsula.haptics.vibrate(ms?)

Vibrates for ms milliseconds (default 300).

Error handling

Rejections carry a message: time in the past, alarm limit reached, notification permission denied, unknown id. Wrap calls in try/catch and show the message in your UI — there is no developer console inside the sandbox yet (planned for 0.3).

Complete example — a tea timer

Works in a browser tab (without alarms) and in Kapsula (with a real alarm). Save as tea.html, or paste the code into Kapsula.

<!DOCTYPE html>
<html><head><meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Tea timer</title>
<style>
  body{font-family:system-ui;background:#0A111F;color:#F0EBE0;margin:0;padding:24px;text-align:center}
  button{font:inherit;font-size:18px;padding:14px 22px;border:0;border-radius:12px;background:#FFB020;margin:8px}
  #left{font-size:64px;font-variant-numeric:tabular-nums;margin:24px 0}
</style></head>
<body>
  <h1>Tea timer</h1>
  <div id="left">–</div>
  <button onclick="start(3)">3 min</button>
  <button onclick="start(5)">5 min</button>
  <button onclick="stop()">Stop</button>
<script>
const K = window.kapsula || null;   // null in a plain browser
let endAt = 0, timer = null;

async function save(){ if (K) await K.storage.set('endAt', endAt); }
async function load(){ endAt = K ? (await K.storage.get('endAt')) || 0 : 0; tick(); }

async function start(min){
  endAt = Date.now() + min*60*1000;
  await save();
  if (K) {
    try {
      await K.notify.cancel();                       // free the slot
      await K.notify.schedule({ at: endAt, title: 'Tea is ready', body: min + ' minutes are up' });
    } catch (e) { alert(e.message); }
  }
  tick();
}
async function stop(){ endAt = 0; await save(); if (K) K.notify.cancel(); tick(); }

function tick(){
  clearTimeout(timer);
  const left = endAt - Date.now();
  if (!endAt) { document.getElementById('left').textContent = '–'; return; }
  if (left <= 0) { document.getElementById('left').textContent = 'Ready!'; if (K) K.sound.play('triple'); endAt = 0; save(); return; }
  const m = Math.floor(left/60000), s = Math.floor(left/1000)%60;
  document.getElementById('left').textContent = m + ':' + String(s).padStart(2,'0');
  timer = setTimeout(tick, 250);
}
load();
</script>
</body></html>

Roadmap (not yet available)

Kapsula executes only code you add yourself. Questions: hello@kapsula.app. See also the prompt for AI assistants.