79 lines
1.3 KiB
Markdown
79 lines
1.3 KiB
Markdown
# Tools
|
|
|
|
A tool is an app that appears as a tab in the dashboard instead of in the sidebar.
|
|
|
|
Tools know which app is selected and render in an iframe over the content area.
|
|
|
|
## making an app a tool
|
|
|
|
Add `toes.tool` to package.json:
|
|
|
|
```json
|
|
{
|
|
"toes": {
|
|
"tool": true,
|
|
"icon": "🔧"
|
|
},
|
|
"scripts": {
|
|
"toes": "bun run --watch index.tsx"
|
|
}
|
|
}
|
|
```
|
|
|
|
## getting the selected app
|
|
|
|
Query param `?app=<name>` tells you which app the user selected:
|
|
|
|
```tsx
|
|
app.get('/', c => {
|
|
const appName = c.req.query('app')
|
|
if (!appName) {
|
|
return c.html(<p>No app selected</p>)
|
|
}
|
|
// do something with appName
|
|
})
|
|
```
|
|
|
|
## accessing app files
|
|
|
|
Always go through the `current` symlink:
|
|
|
|
```ts
|
|
const APPS_DIR = process.env.APPS_DIR ?? '.'
|
|
const appPath = join(APPS_DIR, appName, 'current')
|
|
```
|
|
|
|
Not `APPS_DIR/appName` directly.
|
|
|
|
## linking to tools
|
|
|
|
Use `/tool/:name` URLs to link directly to tools with params:
|
|
|
|
```html
|
|
<a href="/tool/code?app=my-app&version=20260130-000000">
|
|
View in Code
|
|
</a>
|
|
```
|
|
|
|
## resize iframe
|
|
|
|
```js
|
|
window.parent.postMessage({
|
|
type: 'resize-iframe',
|
|
height: 500
|
|
}, '*')
|
|
```
|
|
|
|
## iframe behavior
|
|
|
|
- iframes are cached per tool+app combination
|
|
- Never recreated once loaded
|
|
- State persists across tab switches
|
|
|
|
## cli
|
|
|
|
```bash
|
|
toes list --tools # list tools only
|
|
toes list --all # list apps and tools
|
|
```
|