This template demonstrates the minimum files required to run a third-party JS widget in TimeLens.
manifest.json: widget metadata and registry declaration (Widget SDK v2)index.js: ESM widget entry implementingcreateWidget().mount/unmountindex.ts: TypeScript source for the same widget (optional)types.d.ts: TypeScript declarations describing the widget context APIpackage.json: build scripts; runnpm install && npm run buildto compileindex.tstodist/index.jstsconfig.json: TypeScript compiler options
{
"manifest_version": "v2",
"widget_type": "sample_hello",
"name": "Sample Hello Widget",
"entry": "index.js",
"capabilities": [
{ "capability": "read_metrics", "permission": "screen-time:read" },
{ "capability": "automation_trigger", "permission": "active-window:subscribe" },
{ "capability": "local_api_call", "permission": "local-api:call" }
]
}| Capability | Default runtime permissions granted |
|---|---|
read_metrics |
screen-time:read, todo:read |
write_data |
todo:write, settings:write |
automation_trigger |
active-window:subscribe |
local_api_call |
local-api:call |
You can also declare capabilities as plain strings; in that case TimeLens expands each capability to its default permissions. Use the object form when you want to request only a specific permission from a capability group.
- Copy this folder to your local TimeLens app data widgets directory:
widgets/sample_hello/
- Start TimeLens.
- Open Widget Center → Add Widgets.
- Add
Sample Hello Widgetand open it.
For faster iteration, use the Widget Dev Harness (dev mode only):
- Open Widget Center → "Dev Harness".
- Select this template folder.
- Toggle capabilities and reload instantly.
- Keep
widget_typeunique across all installed widgets. - The entry file must be valid ESM and export
createWidget()ormount(). - Use
context.channel.localApiCall({ method, path, scopes })to call the TimeLens local HTTP API. - See
docs/WIDGET_SDK_v2_MIGRATION.mdfor migration from v1 manifests.