Create or modify AwaitJS iOS widgets in TSX using the custom SwiftUI-style DSL, native bridge APIs, modifiers, timelines, intents, and @panel controls.
Resources
5Install
npx skillscat add maundytime/await-widget-skill Install via the SkillsCat registry.
SKILL.md
Await Widget Skill
This package is both an installable agent skill and a cloneable widget template. Treat the .d.ts files as the public contract.
assets/ is the template project root.
Workflow
- Locate the target widget.
- If the user gives a file, edit that file.
- If the user is working in a fresh clone of this repo, edit
assets/widget/index.tsx. - If the user asks for a new widget project, copy
assets/package.json,assets/package-lock.json,assets/tsconfig.json,assets/runtime/,assets/types/, andassets/widget/into the target project before editing.
- Read only the declarations needed for the task:
assets/runtime/await.d.ts: importable components and JSX entry.assets/runtime/pre-script.d.ts: global native bridge APIs andAwait.definetypes.assets/types/prop.d.ts: component props and modifier types.assets/types/global.d.ts: global types.assets/types/jsx.d.ts: JSX constraints.
- Implement the widget.
- Run
npm testin the widget project directory orassets/for a fresh clone. If dependencies are missing, runnpm installfirst.
Basic Rules
- Import components only from
await. - Do not write native HTML tags.
JSX.IntrinsicElementsisnever, so<div>and<span>are invalid. - Register widgets with
Await.define({...}). - Express view styling through props and modifiers. Do not use CSS,
styleobjects, React hooks, or React state. - If a component, prop, modifier, or native bridge API is not in the
.d.tsfiles, treat it as unavailable. - Widgets run inside a widget environment, not a full app page. Keep the view tree and timeline small by default.
- Design permission-related behavior as "already authorized by the host" or "currently unavailable". Do not put first-run authorization flows inside the widget.
- When generating a widget, also generate a small
@panelsurface by default for the main tunable values unless the user explicitly says not to.
Panel Comments
@panelis a source comment convention. Put it immediately above the declaration it controls.- Value panels only work on top-level
constdeclarations, including exported top-levelconstdeclarations. - Function panels work on function declarations and top-level function-valued declarations.
- For value panels, the initializer must be a literal the panel can rewrite directly: string, number, boolean, or a color literal used with
type:'color'. - Do not put
@panelonlet,var, local variables inside functions, computed initializers, or private implementation details you do not want edited from the panel. - If you provide a payload, it must be a JS object literal after
@panel.
Supported panel types:
// @panel// @panel {type:'slider',min:number,max:number,step?:number}// @panel {type:'menu',items:[...]}// @panel {type:'editor'}// @panel {type:'toggle'}// @panel {type:'color'}// @panel {type:'xml'}
Minimal Template
import {
Text,
ZStack,
} from 'await';
function widget() {
return (
<ZStack>
<Text value='Hello, World!' />
</ZStack>
);
}
Await.define({
widget,
});Timeline
widgetTimeline(context)is optional.- It returns
{entries, update?}. entriesis an array containingdate.- If the widget does not need time-driven updates, omit
widgetTimeline. - If the goal is to refresh as fast as the system allows, use
update: new Date(). Do not hardcode minute intervals below the practical system limit.
Intents And Interaction
- Register interaction functions under
widgetIntents. - Generate
intentvalues from the result ofAwait.define(...). - Parameters must be encodable values.
- If you need continuous movement or interaction transitions, give visual entities stable
idvalues.
import {Button, Text} from 'await';
function tap(step: number) {
const count = AwaitStore.num('count', 0);
AwaitStore.set('count', count + step);
}
function widget() {
return (
<Button intent={app.tap(1)}>
<Text value='Add' />
</Button>
);
}
const app = Await.define({
widget,
widgetIntents: {tap},
});Data And Capabilities
- Use
AwaitStorefor persistent state. - Use
AwaitNetwork.request(...)for networking. Do not usefetch. - Use
AwaitFilewhen file access is needed. - Use
AwaitEnvwhen the widgetidortagis needed.
Decision Order
- Check
assets/runtime/await.d.tsto see whether the component exists. - Check
assets/types/prop.d.tsto see whether the prop or modifier is valid. - Check
assets/runtime/pre-script.d.tsto see whether the native bridge API exists. - If it is not in the
.d.tsfiles, treat it as unavailable.