# 00Widget [Health: Active]

**Category:** 💻 Developer Tools  
**Repository:** https://github.com/morais/00widget  
**GitHub Stars:** 0  
**Views:** 0  
**Installs:** 0  
**Upvotes:** 0  
**Directory Page:** https://allmcps.com/mcp/00widget

## Description
Publish status cards and Live Activities to iOS widgets, the Lock Screen, and the Dynamic Island.

## Claude Desktop Quick Installation
Install path detected from listing signals. Uses `npx` (confidence: high):

```json
"mcpServers": {
  "00widget": {
    "command": "npx",
    "args": ["-y","wrangler"]
  }
}
```

## Documentation & README

<p align="center">
  <img src="https://raw.githubusercontent.com/morais/00widget/HEAD/docs/brand/wordmark-horizontal.png" alt="00Widget — Widgets for all your agents." width="720">
</p>

# 00Widget

**Widgets for all your agents.**

A reusable Apple-platform companion app and Cloudflare Worker backend that gives Claude, ChatGPT, automations, and software you build a native output channel through widgets, Live Activities, the Dynamic Island, and Apple TV dashboards.

The server never sends UI — only structured state conforming to a small set of templates. The Apple apps render that state through predefined SwiftUI views.

## Choose how to connect

### Claude, ChatGPT, and other MCP hosts

Hosts that speak the Model Context Protocol can publish to 00Widget with no
integration code: add `<BASE_URL>/mcp` as a custom connector, sign in, and pick
a tenant. The tools wrap the same handlers as the REST routes, so the two
surfaces cannot drift.

MCP is off by default (`MCP_ENABLED` in `wrangler.toml`) because it exposes a
browser flow that mints API tokens on the public internet. Approving a connector
requires signing in, and the credential it issues is a normal tenant token
scoped to the approver's own account, revocable from `/admin`.

Details: `server/README.md` → "MCP".

### Apps, scripts, automations, and coding agents

If you're inside another repo (say, a CI pipeline or a home-automation script) and want to make Claude Code / Codex publish state to your 00Widget instance, paste this into the agent — it's self-contained:

```
Integrate this project with 00Widget so its state shows up on iOS widgets and Live Activities.

Read the integration contract: https://github.com/morais/00widget/blob/main/docs/llms.md
That single document is everything you need — don't pull in the rest of the 00Widget repo.

Operator-supplied env vars:
  00WIDGET_BASE_URL=https://api.example.com
  00WIDGET_API_KEY=<bearer token>

Verify both work with `curl $00WIDGET_BASE_URL/health` and an authenticated `GET /v1/cards` before writing any code.

Then:
1. Identify the surfaces in this project that an iOS widget should reflect (status, build state, queue depth, in-progress jobs, etc.).
2. For each, pick a template (`summary`, `progress`, `list`, `action`, or `chart`) per llms.md's decision matrix.
3. Add the smallest possible publish path — POST one card to `/v1/cards/upsert`, or one related snapshot to `/v1/cards/upsert-batch`, using stable ids. No SDK, no class hierarchy.
4. If something is time-bounded with a clear end (a build, a charge cycle, a delivery), use a Live Activity instead of a card.

Constraints:
- Use a stable `id` per logical thing — never embed timestamps or run ids.
- Never put secrets or PII in card fields. They render on the Lock Screen.
- Always end Live Activities. Never make destructive actions auto-run from widgets.
- Don't publish more than ~once a minute per card unless the value actually changed.

If this project is itself a Cloudflare Worker, see the "Notes for Cloudflare Workers callers" section in llms.md — same-account integrations should use a Service Binding instead of a public HTTPS fetch.
```

## Anatomy

```
00widget/
  ios/          # SwiftUI app + WidgetKit extension + Live Activity (iOS 26+)
  server/       # Cloudflare Worker (TypeScript) — REST API + APNs fan-out
  examples/     # curl scripts showing how any agent can publish state
  marketing/    # Screenshot and App Preview sources, docs, and entry points
  artifacts/    # Generated marketing output (ignored by Git)
```

## Quick start

### 1. Backend

```
cd server
npm install
install -m 600 .dev.vars.example .dev.vars   # fill in SESSION_SECRET; enable the local fallback only when needed
npx wrangler dev
```

Then:

```
curl -s http://localhost:8787/health
```

### 2. Examples

```
cd examples
install -m 600 env.example.sh env.sh   # edit BASE_URL and API_KEY
./upsert-solar.sh
```

### 3. iOS

Requires macOS with Xcode 26+, iOS 26 simulator or device, and [XcodeGen](https://github.com/yonaskolb/XcodeGen).

```
brew install xcodegen
cd ios
xcodegen
open ZeroZeroWidget.xcodeproj
```

In Xcode, change the bundle id and App Group to values your Apple Developer team owns (see `ios/README.md`), then run.

## Data model

See `ios/Sources/Shared/Models/` (Swift) and `server/src/types.ts` (zod) — the two are kept in lockstep.

- **DashboardCard** — a single widget tile. Templates: `summary`, `progress`, `list`, `action`, `chart`.
- **LiveActivitySession** — a Lock Screen / Dynamic Island activity.
- **ActionDefinition** — a button that runs a backend-defined action via `POST /v1/actions/:id/run`.

## Web sign-in and admin

`/login` signs a person in with the same Apple ID they use in the iOS app.
Signing in establishes identity, not authority: `ADMIN_EMAILS` names the
addresses whose sessions additionally carry admin capabilities, and every route
under `/admin` asserts that capability rather than assuming it.

**Signing in does not sign you up.** The callback resolves the Apple identity
against the account the app created and turns away one it does not recognise, so
finding this endpoint is not a way to become a tenant. `WEB_SIGNUP_ENABLED`
(off by default) opts a deployment into web account creation.

The admin dashboard at `/admin` lists cards, devices, push tokens, Live
Activities, pending activities, and push-to-start tokens across every tenant. It
can also create and revoke tenant credentials and delete tenant data, so access
grants full administrative control rather than read-only visibility. An
`API_KEYS` bootstrap login (`ADMIN_API_TOKEN_LOGIN=true`, off by default) covers
a deployment that has no accounts yet.

Create least-privilege tenant API tokens from `/admin` using the tenant owner email and a permission preset; those generated credentials are what apps and agents use for `/v1/*`.

Setup walkthrough: `server/README.md` → "Web sign-in".

## Documentation

- `ios/README.md` — Xcode setup, entitlements, signing.
- `server/README.md` — Worker deploy, D1 binding, APNs secrets, web sign-in and admin.
- `examples/README.md` — publishing state from any shell or agent.
- `docs/llms.md` — for agents (Claude Code / Codex) integrating *another* project with 00Widget.
- `docs/brand/README.md` — logo, colors, tagline rules.
- `marketing/screenshots/README.md` — raw capture, promotional composition, and App Store screenshot workflow.
- `marketing/app-preview/README.md` — App Store Preview capture, rendering, and validation workflow.

## Status

Working end-to-end. Cards publish, Live Activities start/update/end, push-to-start is wired, and APNs payloads are verified against Apple's current docs (date-stamped in `server/src/apns.ts`).

**Push-to-start (ActivityKit, iOS 17.2+)** — fully implemented. iOS observes `Activity<ZeroZeroWidgetActivityAttributes>.pushToStartTokenUpdates` from `didFinishLaunchingWithOptions`, registers via `POST /v1/live-activities/register-start-token`. The backend's `POST /v1/live-activities/start` sends the start event to all registered devices and falls back to the pending-queue path if no token is registered (or if the APNs delivery fails). End-to-end verification needs `.p8` credentials configured on the Worker.

**tvOS activity dashboard** — the Apple TV app lists ongoing Live Activities above its widgets. The backend exposes one deduplicated tenant-scoped view across pending starts and registered device activities, while tvOS renders countdowns and progress locally.

**WidgetKit `pushHandler` (iOS 26+)** — fully implemented. Each widget configuration calls `.pushHandler(ZeroZeroWidgetPushHandler.self)`. The handler persists WidgetKit’s canonical token/configuration snapshot in the App Group, and the host app reconciles it at launch, on foreground, after app-build changes, and through a short bounded retry while WidgetKit finishes generating a token. Backend pushes carry `aps.content-changed: true`, use budget-aware per-tenant cadence, and durably coalesce suppressed changes into one delayed queue delivery when the cadence window opens. A successful foreground app fetch also requests targeted timeline reloads immediately. End-to-end verification still needs `.p8` credentials and a physical device.

## License

Source code is MIT licensed. The 00Widget name and brand assets are excluded;
see [LICENSE](https://github.com/morais/00widget/blob/HEAD/LICENSE) and [docs/brand/LICENSE](https://github.com/morais/00widget/blob/HEAD/docs/brand/LICENSE).

