SuperIslandSuperIsland
Extension SDK

Extension Examples

Three complete, production-quality extensions — Pomodoro timer, AI usage rings, and WhatsApp Web bridge.

Extension Examples

Three complete extensions ship with SuperIsland as references.

1. Pomodoro Timer

A focus timer with compact countdown and quick controls.

Capabilities: compact, expanded, fullExpanded, backgroundRefresh, settings, notifications

manifest.json

{
  "id": "com.workview.pomodoro",
  "name": "Pomodoro Timer",
  "version": "1.0.0",
  "main": "index.js",
  "permissions": ["notifications", "storage"],
  "capabilities": ["compact", "expanded", "fullExpanded", "backgroundRefresh", "settings"],
  "refreshInterval": 1.0,
  "activationTriggers": ["manual"]
}

index.js

const WORK_DURATION = () => (DynamicIsland.settings.get("workMinutes") ?? 25) * 60;
const BREAK_DURATION = () => (DynamicIsland.settings.get("breakMinutes") ?? 5) * 60;

let remaining = WORK_DURATION();
let running = false;
let isBreak = false;

function formatTime(s) {
  const m = Math.floor(s / 60).toString().padStart(2, "0");
  const sec = (s % 60).toString().padStart(2, "0");
  return `${m}:${sec}`;
}

DynamicIsland.registerModule({
  compact() {
    const color = isBreak ? "#22c55e" : "#a855f7";
    return View.hstack([
      View.icon(isBreak ? "leaf.fill" : "timer", { size: 11, color }),
      View.text(formatTime(remaining), {
        style: "caption",
        color: "#e8e8e8",
        bold: true,
      }),
      View.when(running,
        View.animate(View.icon("waveform", { size: 8, color: "#888" }), "pulse")
      ),
    ], { spacing: 4 });
  },

  expanded() {
    const label = isBreak ? "Break" : "Focus";
    const color = isBreak ? "#22c55e" : "#a855f7";
    const total = isBreak ? BREAK_DURATION() : WORK_DURATION();
    const progress = 1 - remaining / total;

    return View.vstack([
      View.hstack([
        View.text(label, { style: "caption", color }),
        View.spacer(),
        View.text(formatTime(remaining), { style: "headline", bold: true }),
      ]),
      View.progress(progress, { color }),
      View.hstack([
        View.button(
          View.text(running ? "Pause" : "Start", { style: "caption", color }),
          "toggle"
        ),
        View.spacer(),
        View.button(
          View.text("Reset", { style: "caption", color: "#888" }),
          "reset"
        ),
      ]),
    ], { spacing: 8 });
  },

  onActivate() {
    remaining = DynamicIsland.store.get("remaining") ?? WORK_DURATION();
    running = DynamicIsland.store.get("running") ?? false;
    isBreak = DynamicIsland.store.get("isBreak") ?? false;
  },

  onAction(id) {
    if (id === "toggle") {
      running = !running;
      DynamicIsland.store.set("running", running);
      DynamicIsland.playFeedback("selection");
    }
    if (id === "reset") {
      running = false;
      isBreak = false;
      remaining = WORK_DURATION();
      DynamicIsland.store.set("running", false);
      DynamicIsland.store.set("remaining", remaining);
      DynamicIsland.playFeedback("warning");
    }
  },
});

setInterval(() => {
  if (!running) return;
  remaining = Math.max(0, remaining - 1);
  DynamicIsland.store.set("remaining", remaining);

  if (remaining === 0) {
    isBreak = !isBreak;
    remaining = isBreak ? BREAK_DURATION() : WORK_DURATION();
    running = false;

    DynamicIsland.notifications.send({
      title: isBreak ? "Break time! 🌿" : "Back to work! 🎯",
      body: isBreak
        ? `Take a ${BREAK_DURATION() / 60}m break`
        : `Start a ${WORK_DURATION() / 60}m focus session`,
      sound: true,
    });

    DynamicIsland.playFeedback("success");
  }
}, 1000);

2. AI Usage Rings

Displays Codex + Claude usage/availability with circular ring indicators.

Capabilities: compact, expanded, fullExpanded, minimalCompact, backgroundRefresh

async function fetchUsage() {
  // Try local summary files first
  const codex = await DynamicIsland.http.fetch(
    "file://" + DynamicIsland.store.get("homeDir") + "/.codex/usage-summary.json"
  );
  const claude = await DynamicIsland.http.fetch(
    "file://" + DynamicIsland.store.get("homeDir") + "/.claude/usage-summary.json"
  );
  return {
    codex: codex.data,
    claude: claude.data,
  };
}

DynamicIsland.registerModule({
  async compact() {
    const usage = await fetchUsage();
    const codexPct = usage.codex?.remaining ?? 0;
    const claudePct = usage.claude?.remaining ?? 0;

    return View.hstack([
      View.circularProgress(codexPct, {
        total: 100,
        lineWidth: 2,
        color: codexPct > 30 ? "#22c55e" : codexPct > 10 ? "#f59e0b" : "#ef4444",
      }),
      View.circularProgress(claudePct, {
        total: 100,
        lineWidth: 2,
        color: claudePct > 30 ? "#a855f7" : claudePct > 10 ? "#f59e0b" : "#ef4444",
      }),
    ], { spacing: 6 });
  },
});

3. WhatsApp Web

Pairs with WhatsApp Web via QR code and routes incoming messages to the island notification feed.

Capabilities: compact, expanded, fullExpanded, notificationFeed, backgroundRefresh

DynamicIsland.registerModule({
  async compact() {
    const state = await DynamicIsland.system.getWhatsAppWeb(0);
    const status = state?.status ?? "disconnected";

    return View.hstack([
      View.icon("message.fill", {
        size: 12,
        color: status === "connected" ? "#22c55e" : "#888",
      }),
      View.text(status === "connected" ? "WhatsApp" : "Disconnected", {
        style: "caption",
        color: status === "connected" ? "#e8e8e8" : "#555",
      }),
    ], { spacing: 4 });
  },

  async expanded() {
    const messages = await DynamicIsland.system.getWhatsAppWeb(3);

    if (!messages || messages.length === 0) {
      return View.vstack([
        View.text("No recent messages", { style: "caption", color: "#555" }),
        View.button(View.text("Connect", { style: "caption", color: "#a855f7" }), "connect"),
      ]);
    }

    return View.vstack(
      messages.map((msg) =>
        View.hstack([
          View.text(msg.sender, { style: "caption", bold: true }),
          View.spacer(),
          View.text(msg.body.slice(0, 30), { style: "caption2", color: "#888" }),
        ])
      ),
      { spacing: 4 }
    );
  },

  onAction(id) {
    if (id === "connect") {
      DynamicIsland.system.startWhatsAppWeb();
    }
  },
});

On this page