Manifest

Every provider site must serve /manifest.json at the same HTTPS origin as the activity.

Required fields

{
  "schema_version": "1.0",
  "provider": {
    "id": "com.example.myprovider",
    "name": "My provider",
    "version": "0.1.0"
  },
  "runtime": {
    "entrypoint": "https://my-site.getforge.io/",
    "sdk_version": "^1.0"
  },
  "activities": [
    { "id": "my_activity", "name": "My activity", "duration_minutes": 2 }
  ],
  "permissions": ["context.current_state"],
  "capabilities": [
    "activity.start",
    "activity.complete",
    "context.getCurrent",
    "host.haptic"
  ]
}

Provider id

Use reverse-DNS: com.yourcompany.activityname. Stable forever — Nuwe keys installs on this id.

Thumbnails (optional)

Nuwe renders directory tiles from manifest metadata. Host the PNGs on the same Forge origin as your activity, then reference site-relative paths:

{
  "presentation": {
    "thumbnail": "images/thumbs/my-provider.png"
  },
  "activities": [
    {
      "id": "my_activity",
      "name": "My activity",
      "thumbnail": "images/thumbs/my-activity.png",
      "surfaces": ["directory", "today"]
    }
  ]
}

The Nuwe API resolves these to absolute thumbnail_url values for the iOS Activities tab. Marketplace plugin icons are separate from manifest thumbnails.

Permissions (declare only what you need)

Validate locally

node scripts/validate-manifest.mjs manifest.json

Schema: activity-manifest.json