Make a small tool with blocks or HTML, CSS and JavaScript. A plugin is one .allfp file containing its name, code, blocks and requested permissions. It is stored locally in this browser. There is no online marketplace or publishing step.
1. Build, test and keep a backup
- Choose Blocks or Code in the builder toolbar.
- Open Save local plugin to set a name, author, description and tags.
- Use Requested plugin permissions to keep only the access you need.
- Choose Test plugin. The mock editor on the right is separate from your real project.
- Choose Install locally in Studio. In Studio, open Local Plugins → Review & run, review its permissions and allow the ones you trust.
- Use Download .allfp Bundle to keep a backup. Import that file to edit it later or use it in another browser.
Drafts autosave in the builder. Browser storage can be cleared by browser settings or private mode, so export packages you want to keep.
2. Your first block plugin
- In Events, double-click on mount to add it to the canvas. You can also drag blocks or focus a palette block and press Enter.
- Add a toolbar button UI block inside the event's inner slot. Set its label to “Insert greeting”.
- Add an insert text editor block inside the toolbar button's slot. Enter “Hello from ALLF!”.
- Test. A new button appears in the mock toolbar; clicking it inserts text.
Place actions inside the event/button they belong to. Top-level blocks run in canvas order from top to bottom. Blocks → code generates JavaScript; changing JavaScript does not reverse-engineer the blocks.
Events: mount runs when the plugin starts; save runs when Studio saves; focus runs when an editor receives focus. Repeating blocks pause between actions. Stop a looping plugin using its panel's Stop button.
This example needs studio.controls and editor.write.
3. How HTML, CSS and JavaScript fit together
HTML builds the plugin panel. CSS styles that panel. JavaScript handles its buttons and calls the ALLF API to interact with Studio. The panel is isolated: document refers to the plugin panel, not the Studio page.
HTML pane
<h2>My note tool</h2>
<textarea id="note">Hello!</textarea>
<button id="insert">Insert note</button>
CSS pane
h2 { color: #50aaff; }
textarea { width: 100%; min-height: 100px; }
JavaScript pane
document.getElementById('insert').onclick = async () => {
const text = document.getElementById('note').value;
await ALLF.insertText(text);
};
ALLF.on('mount', async () => {
await ALLF.addToolbarButton('My note tool', () => ALLF.showPanel());
});
Use await with editor and Studio methods: the panel communicates asynchronously with Studio. This example needs editor.write and studio.controls. Use Example plugin in the toolbar to load a working panel.
4. A useful selection tool
Choose Code, leave HTML/CSS blank, and paste this into JavaScript. Enable read, write and controls permissions.
ALLF.on('mount', async () => {
await ALLF.addToolbarButton('Uppercase selection', async () => {
const selected = await ALLF.getSelection();
if (!selected) return ALLF.toast('Select some text first.');
await ALLF.insertText(selected.toUpperCase());
});
});
insertText replaces the active editor selection when a selection exists. setText replaces the whole active file, so use it carefully.
Create a new file
ALLF.on('mount', async () => {
await ALLF.addFile('notes/plugin-note.txt', 'Created by a plugin.');
});
This needs files.create. Choose a unique relative path: an existing file will not be overwritten.
6. Permissions and safe mode
Only request capabilities you use. Users review them on each run and may uncheck any capability. A denied call rejects its promise with “Permission denied”; catch the error or enable the required permission before restarting.
Plugins cannot access Studio's DOM, browser storage or Firebase directly, and cannot load remote scripts, fetch web APIs or request external images. The host grants access through the API only. Safe mode stops running plugins and blocks new starts; builder tests still run in their isolated mock environment.
Stop removes a plugin's panel and added controls. Uninstall deletes its local saved package. Export first if you need a backup.
7. Troubleshooting
- No button appears: put the UI action inside the mount event, check controls permission, then Test or restart the plugin.
- Open a code file first: editor APIs work on code tabs, not images, audio or documents.
- Permission denied: enable the requested capability in the builder, save/install, then review permissions when you run it.
- Unknown menu: use File, Edit or View with the exact capitalisation.
- Import failed: select a valid JSON .allfp package under 600 KB, rather than a standalone .html/.js file.
- A save loop or too many operations: do not call save repeatedly inside a save event. Add waits to loops and use Stop to end a runaway plugin.
- Plugin missing in another browser: local storage is browser-specific. Export from the original browser and import the .allfp file.