{
  "markdown": "<p align=\"center\">\n  <img src=\"./docs/brand/wordmark-horizontal.png\" alt=\"00Widget — Widgets for all your agents.\" width=\"720\">\n</p>\n\n# 00Widget\n\n**Widgets for all your agents.**\n\nA 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.\n\nThe server never sends UI — only structured state conforming to a small set of templates. The Apple apps render that state through predefined SwiftUI views.\n\n## Choose how to connect\n\n### Claude, ChatGPT, and other MCP hosts\n\nHosts that speak the Model Context Protocol can publish to 00Widget with no\nintegration code: add `<BASE_URL>/mcp` as a custom connector, sign in, and pick\na tenant. The tools wrap the same handlers as the REST routes, so the two\nsurfaces cannot drift.\n\nMCP is off by default (`MCP_ENABLED` in `wrangler.toml`) because it exposes a\nbrowser flow that mints API tokens on the public internet. Approving a connector\nrequires signing in, and the credential it issues is a normal tenant token\nscoped to the approver's own account, revocable from `/admin`.\n\nDetails: `server/README.md` → \"MCP\".\n\n### Apps, scripts, automations, and coding agents\n\nIf 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:\n\n```\nIntegrate this project with 00Widget so its state shows up on iOS widgets and Live Activities.\n\nRead the integration contract: https://github.com/morais/00widget/blob/main/docs/llms.md\nThat single document is everything you need — don't pull in the rest of the 00Widget repo.\n\nOperator-supplied env vars:\n  00WIDGET_BASE_URL=https://api.example.com\n  00WIDGET_API_KEY=<bearer token>\n\nVerify both work with `curl $00WIDGET_BASE_URL/health` and an authenticated `GET /v1/cards` before writing any code.\n\nThen:\n1. Identify the surfaces in this project that an iOS widget should reflect (status, build state, queue depth, in-progress jobs, etc.).\n2. For each, pick a template (`summary`, `progress`, `list`, `action`, or `chart`) per llms.md's decision matrix.\n3. 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.\n4. If something is time-bounded with a clear end (a build, a charge cycle, a delivery), use a Live Activity instead of a card.\n\nConstraints:\n- Use a stable `id` per logical thing — never embed timestamps or run ids.\n- Never put secrets or PII in card fields. They render on the Lock Screen.\n- Always end Live Activities. Never make destructive actions auto-run from widgets.\n- Don't publish more than ~once a minute per card unless the value actually changed.\n\nIf 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.\n```\n\n## Anatomy\n\n```\n00widget/\n  ios/          # SwiftUI app + WidgetKit extension + Live Activity (iOS 26+)\n  server/       # Cloudflare Worker (TypeScript) — REST API + APNs fan-out\n  examples/     # curl scripts showing how any agent can publish state\n  marketing/    # Screenshot and App Preview sources, docs, and entry points\n  artifacts/    # Generated marketing output (ignored by Git)\n```\n\n## Quick start\n\n### 1. Backend\n\n```\ncd server\nnpm install\ninstall -m 600 .dev.vars.example .dev.vars   # fill in SESSION_SECRET; enable the local fallback only when needed\nnpx wrangler dev\n```\n\nThen:\n\n```\ncurl -s http://localhost:8787/health\n```\n\n### 2. Examples\n\n```\ncd examples\ninstall -m 600 env.example.sh env.sh   # edit BASE_URL and API_KEY\n./upsert-solar.sh\n```\n\n### 3. iOS\n\nRequires macOS with Xcode 26+, iOS 26 simulator or device, and [XcodeGen](https://github.com/yonaskolb/XcodeGen).\n\n```\nbrew install xcodegen\ncd ios\nxcodegen\nopen ZeroZeroWidget.xcodeproj\n```\n\nIn Xcode, change the bundle id and App Group to values your Apple Developer team owns (see `ios/README.md`), then run.\n\n## Data model\n\nSee `ios/Sources/Shared/Models/` (Swift) and `server/src/types.ts` (zod) — the two are kept in lockstep.\n\n- **DashboardCard** — a single widget tile. Templates: `summary`, `progress`, `list`, `action`, `chart`.\n- **LiveActivitySession** — a Lock Screen / Dynamic Island activity.\n- **ActionDefinition** — a button that runs a backend-defined action via `POST /v1/actions/:id/run`.\n\n## Web sign-in and admin\n\n`/login` signs a person in with the same Apple ID they use in the iOS app.\nSigning in establishes identity, not authority: `ADMIN_EMAILS` names the\naddresses whose sessions additionally carry admin capabilities, and every route\nunder `/admin` asserts that capability rather than assuming it.\n\n**Signing in does not sign you up.** The callback resolves the Apple identity\nagainst the account the app created and turns away one it does not recognise, so\nfinding this endpoint is not a way to become a tenant. `WEB_SIGNUP_ENABLED`\n(off by default) opts a deployment into web account creation.\n\nThe admin dashboard at `/admin` lists cards, devices, push tokens, Live\nActivities, pending activities, and push-to-start tokens across every tenant. It\ncan also create and revoke tenant credentials and delete tenant data, so access\ngrants full administrative control rather than read-only visibility. An\n`API_KEYS` bootstrap login (`ADMIN_API_TOKEN_LOGIN=true`, off by default) covers\na deployment that has no accounts yet.\n\nCreate 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/*`.\n\nSetup walkthrough: `server/README.md` → \"Web sign-in\".\n\n## Documentation\n\n- `ios/README.md` — Xcode setup, entitlements, signing.\n- `server/README.md` — Worker deploy, D1 binding, APNs secrets, web sign-in and admin.\n- `examples/README.md` — publishing state from any shell or agent.\n- `docs/llms.md` — for agents (Claude Code / Codex) integrating *another* project with 00Widget.\n- `docs/brand/README.md` — logo, colors, tagline rules.\n- `marketing/screenshots/README.md` — raw capture, promotional composition, and App Store screenshot workflow.\n- `marketing/app-preview/README.md` — App Store Preview capture, rendering, and validation workflow.\n\n## Status\n\nWorking 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`).\n\n**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.\n\n**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.\n\n**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.\n\n## License\n\nSource code is MIT licensed. The 00Widget name and brand assets are excluded;\nsee [LICENSE](./LICENSE) and [docs/brand/LICENSE](./docs/brand/LICENSE).\n",
  "bytes": 8351,
  "sha": "879708fb82a036862f28bfcdcc7fdb3d1f07b4d4f8e7c2443f9e10532a6cf74d",
  "repo_slug": "morais/00widget",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_com_00widget_00widget_7556514b/readme"
}