Orbit documentation: docs, wiki and FAQ pages

This commit is contained in:
reverse 2026-06-20 06:34:12 +00:00
commit bcbe5fff22
No known key found for this signature in database
18 changed files with 714 additions and 0 deletions

100
docs/compiled-plugins.md Normal file
View file

@ -0,0 +1,100 @@
# Compiled plugins
A quick `.js` plugin (see [Plugin system](/docs/plugins/)) is great for small
things. For anything substantial — real components with state and hooks — build
the plugin like a normal project and compile it down to **one droppable file**: a
compiled, externalized-React plugin model.
## The trick: externalize React
The output bundle must **not** carry its own copy of React. Two React instances
on one page break hooks ("invalid hook call"). Instead, mark `react`, `react-dom`
and `react/jsx-runtime` **external** and map them to Orbit's globals, so your
plugin shares the host's single React instance:
| Module | Maps to |
|---|---|
| `react` | `Orbit.React` |
| `react-dom` | `Orbit.ReactDOM` |
| `react/jsx-runtime` | `Orbit.jsxRuntime` |
Because your component is created with Orbit's React and rendered through a slot
into Orbit's tree, **hooks, state, context and effects all work**.
## Vite config
```ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
export default defineConfig({
plugins: [react()],
build: {
lib: { entry: 'src/index.tsx', formats: ['iife'], name: 'MyOrbitPlugin',
fileName: () => 'my-plugin.js' },
rollupOptions: {
external: ['react', 'react-dom', 'react/jsx-runtime'],
output: { globals: {
react: 'Orbit.React',
'react-dom': 'Orbit.ReactDOM',
'react/jsx-runtime': 'Orbit.jsxRuntime',
} },
},
},
});
```
## Write normal TSX
```tsx
import { useState } from 'react';
Orbit.plugin('my-plugin', (orbit) => {
orbit.addUi('composer_button', () => <ShrugButton orbit={orbit} />);
orbit.addSettingsSection({
label: 'My plugin', icon: '🧩',
render: () => <Panel orbit={orbit} />,
});
});
function Panel({ orbit }) {
const [count, setCount] = useState(() => orbit.storage.get('count', 0));
const bump = () => { const n = count + 1; setCount(n); orbit.storage.set('count', n); };
return (
<div className="scard"><div className="scard__body">
<div className="sfield"><div className="sfield__intro">
Compiled plugin — real React with hooks. You are <b>{orbit.state.nick()}</b>.
</div></div>
<div className="modal__actions">
<button className="upbtn upbtn--primary" onClick={bump}>Clicked {count}×</button>
</div>
</div></div>
);
}
```
The compiled bundle is tiny — it contains only your code, calling Orbit's React.
## Starter template
A ready-to-copy starter (Vite config with the externals set up, `tsconfig`,
ambient types and a working example) lives in the repo at
[`plugin-template/`](https://codeberg.org/reversefr/orbit/src/branch/main/plugin-template).
```bash
git clone https://codeberg.org/reversefr/orbit.git
cd orbit/plugin-template
npm install
npm run build # → dist/orbit-plugin-template.js
```
## Deploy
1. Copy the built `.js` to where Orbit can fetch it (e.g. `/app/plugins/`).
2. List it in the deployed `config.json` — no rebuild of Orbit needed:
```json
{ "plugins": ["/app/plugins/my-plugin.js"] }
```
3. Reload. Your composer button and Settings section appear.