mirror of
https://github.com/saphid/frame-control.git
synced 2026-10-26 11:01:47 +01:00
* Provide Decky automatic JSX runtime in Framey panel * Add Decky settings sample for Framey authors * Use official Decky settings path in sample backend --------- Co-authored-by: SAPHID <saphid@users.noreply.github.com>
67 lines
4.4 KiB
Markdown
67 lines
4.4 KiB
Markdown
# Write a plugin for Frame
|
|
|
|
There are two paths. Choose the one that matches your feature.
|
|
|
|
## Frame Control extension
|
|
|
|
Use a Frame Control extension for a panel, status view, or guide that does not
|
|
need to change the headset. Put `extension.json` and `index.html` in one folder
|
|
under `~/.local/share/frame-control/extensions`. The opt-in headset panel lists
|
|
the folder and opens it in a sandboxed iframe. The version 1 bridge has only
|
|
`capabilities` and read-only `status`. It cannot call Steam, change settings,
|
|
or run privileged code. See [the extension API](extensions.md) and its example.
|
|
|
|
## Decky plugin
|
|
|
|
Use a Decky plugin only if you need Decky's backend or Gamepad UI integration.
|
|
Build an official-format ZIP with one top-level folder, `plugin.json`, and a
|
|
frontend bundle in `dist/index.js`. A Python `main.py` backend is optional.
|
|
Test on ARM64. If you ship an ELF helper, build it for AArch64 (ELF machine
|
|
183). Avoid root, `sudo`, Steam Deck TDP controls, fixed x86 binaries, and
|
|
paths under `/etc`. Frame Control's managed loader is a normal user service;
|
|
it blocks root plugins and x86 archives. Keep data under your plugin folder or
|
|
the user's home directory, and provide a removal path.
|
|
|
|
The current Frame SteamVR shell does not expose Decky's Steam Deck Quick Access
|
|
Menu. A backend `Loaded` log only proves backend startup. Test any frontend
|
|
page, setting, notification, route, and controller input while wearing a Frame
|
|
before describing it as working in VR. Until a QAM bridge is verified, a Frame
|
|
Control extension is the simplest route for a self-contained read-only VR panel.
|
|
|
|
Frame Control now has an experimental [Framey panel host](framey-loader.md)
|
|
for API v2 Decky frontend bundles. It renders common settings controls in the
|
|
separate SteamVR dashboard panel, but Steam library and store page patches
|
|
remain unavailable. Wearer-visible use is not yet verified.
|
|
The [settings sample](../examples/framey-settings/README.md) shows an official
|
|
Decky JSX build, backend persistence, a toggle and a local toast. Framey offers
|
|
only official-store-owned plugins in its VR panel.
|
|
|
|
To test safely, use a separate Frame Control managed Decky install, verify the
|
|
ZIP digest from the official store, install one plugin at a time, and inspect
|
|
`journalctl --user -u frame-control-decky.service`. Remove only your own
|
|
plugin folder when you finish. See the current [compatibility table](decky-frame.md).
|
|
|
|
## Framey API v2 compatibility
|
|
|
|
Framey hosts a plugin's frontend in an isolated iframe in the Frame Control
|
|
SteamVR panel. The table describes the current implementation and its tests;
|
|
none of these frontend controls has passed a worn-headset check yet.
|
|
|
|
| Decky API or UI feature | Framey behavior | Verified in |
|
|
| --- | --- | --- |
|
|
| `definePlugin` with `content`, `titleView` | Renders a React panel and optional title | Local browser with ProtonDB Badges; host unit test |
|
|
| Official `@decky/rollup` JSX (`SP_JSX.jsx`, `jsxs`, `Fragment`) | Creates React elements in the isolated panel | Sample bundle smoke test; host unit test |
|
|
| `PanelSection`, rows, buttons, toggles, dropdowns | Local touch-sized controls | Local browser and host unit test |
|
|
| Optional `settings`, `frameyQuickActions` | Separate settings tab; up to eight actions with result text | Host unit test; these fields are Framey additions |
|
|
| `serverAPI.call` / `callable` | Calls only that plugin's Decky Python backend via the headset service | Fake Frame e2e for setting read/write across CEF calls, update, and reinstall; host unit test. Real Decky persistence remains unverified. |
|
|
| `toaster.toast` | Visible toast inside the plugin panel; `dismiss` and optional `onClick` | Host unit test; no Steam system notification |
|
|
| `routerHook.addRoute` / `removeRoute`, `Navigation.Navigate` / `NavigateBack` | Local routes inside this plugin panel only | Host unit test |
|
|
| `routerHook.addPatch`, global components | No-op; cannot patch Steam routes | Not applicable |
|
|
| Steam library/store patches, CEF tab injection | Unavailable; no matching target in the isolated panel | Frame CEF inspection |
|
|
| `fetchNoCors`, Decky event listeners, file picker, root calls | Unavailable | Not supported by Framey |
|
|
|
|
Keep routes local to the panel and give every operation a visible result. A
|
|
plugin that calls `Navigation.Navigate('/decky/store')` will not open the
|
|
Frame Control store; only paths registered by that same plugin can navigate.
|
|
Toasts stay inside the panel, so keep essential errors in the plugin UI too.
|