skills/bubble-io-plugins/SKILL.md
Bubble.io plugin development rules, API reference, and coding standards. Use when working on any task in this repo: writing, reviewing, refactoring, or creating initialize.js, update.js, preview.js, header.html, element actions, client-side actions, server-side actions (SSA), Plugin API v4 async/await code, JSDoc, setup files, README, CHANGELOG, marketplace descriptions, or field tooltips. Also use for security audits, code review, debugging, and publishing plugins. Covers instance/properties/context objects, BubbleThing/BubbleList interfaces, data loading suspension, DOM/canvas rules, element vs shared headers, exposed states, event handling, ESLint standards, and Bubble hard limits.
npx skillsauth add afaraha8403/bubble-io-plugin-boilerplate bubble-io-pluginsInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
This is a Bubble.io plugin development boilerplate. It provides the folder structure, coding conventions, and tooling for building plugins that run inside the Bubble.io no-code platform.
Plugins are deployed by copying code into the Bubble Plugin Editor — no build step, no npm publish.
project-root/
actions/
client/ # Client-side workflow actions
<action-name>/
action-setup.md
client.js
params.json # Optional: parameter definitions
server/ # Server-side actions (runs on Bubble's Node.js server)
<action-name>/
action-setup.md
server.js
elements/ # Visual plugin elements
<element-name>/
element-setup.md
initialize.js # Runs once on element load
update.js # Runs on every property change + data load
preview.js # Renders placeholder in Bubble Editor
header.html # <head> content: CDN links, external scripts
actions/ # Element-specific workflow actions
<action>.js
eslint.config.mjs # ESLint flat config
package.json # ESLint scripts and dependencies
README.md
Each local file maps 1:1 to a text field in the Bubble Plugin Editor:
| Local file | Bubble Editor field |
|---|---|
| initialize.js | Function: initialize |
| update.js | Function: update |
| preview.js | Function: preview |
| header.html | Element Header |
| actions/<name>.js | Element Action code |
| server/<name>/server.js | Server-Side Action code |
| styles.css | Shared/Element Header (wrap in <style> tags) |
When generating or editing any code in this project, follow these rules unconditionally.
All code must be clean, consistently formatted, and easy to scan. This means:
container not c, itemCount not ic).update.js — use comment blocks (// === SECTION ===) to delimit lifecycle phases (data loading → guard → change detection → cleanup → render).Every non-trivial block of code must include an inline comment explaining why it exists, not just what it does. Specifically:
properties.* field contains and why it is loaded first.instance.canvas instead of document.body).All functions (wrappers and helpers) must have JSDoc blocks. Follow the rules in documentation.md Section 1. Summary:
initialize, update, preview, actions) — include a top-level @description summarising the function's purpose, followed by @param tags for each argument (instance, properties, context).@param, @returns, and a one-line description.Example (initialize wrapper):
let initialize = function(instance, context) {
/**
* @description One-time setup for the PLUGIN_PREFIX element.
* Creates the root DOM container, generates a unique event namespace,
* and initialises default exposed states.
*
* @param {object} instance - Bubble element instance (canvas, data, publishState, etc.)
* @param {object} context - Bubble context (keys, currentUser, etc.)
*/
// ... implementation ...
};
verbose_logging)When scaffolding a new element or action from scratch, ask the user once:
"Should this component include a
verbose_loggingtoggle? This adds a boolean field in the Bubble Plugin Editor that gates allconsole.logoutput at runtime."
Do not ask on edits, reviews, refactors, or bug fixes — only on new scaffolds.
If the user accepts:
verbose_logging to the element or action configuration in the Bubble Plugin Editor and document it in the relevant setup file.console.log calls behind properties.verbose_logging:if (properties.verbose_logging) {
console.log('[PLUGIN_PREFIX] update called', { properties });
}
update.js, client actions, and server actionsconsole.error() in catch blocks is always unconditional — never gate error logging behind the verbose flag.initialize.js does not receive properties — verbose logging is unavailable. Use a plain console.log only for temporary init-time debugging; remove before production.preview.js and header.html run in the editor only — verbose logging does not apply.If the user declines, omit all console.log statements. console.error() in catch blocks remains unconditionally.
These are the highest-consequence rules. Violating any of these causes hard-to-debug failures:
'not ready' exception — Bubble uses it as control flow for data loading. If you must use try/catch, re-throw when err.message === 'not ready'.document.body — use instance.canvas for all visual output.context.keys.myPlugin-root) — avoid collisions with the host app.async — use await on .get(), .length(), and fetch().<script>, <meta>, <link> — anything else gets auto-moved to <body>.$(document).ready() inside plugin functions — it breaks Bubble's dependency detection.Do not preload all files. Determine the task type, then load only the relevant reference:
initialize.js, update.js, preview.js, header.html)? → Load bubble-platform.mdinstance/properties/context API details, or v4 migration? → Load bubble-api.md| File | Load when... |
|---|---|
| bubble-platform.md | Element lifecycle, DOM/canvas, data loading, headers, preview, events, debugging, hard limits. |
| bubble-api.md | instance, properties, context API reference. BubbleThing/BubbleList types. Custom data types / API Connector App Types. Plugin API v4 migration. |
| actions-guide.md | Client vs server actions. When to use which. SSA Node modules, return values, option sets. |
| code-standards.md | ESLint config, syntax rules, security, performance, error handling. |
| documentation.md | JSDoc, setup files, marketplace descriptions, field tooltips, changelog, publishing. |
When scaffolding a new element or action, copy the relevant template from assets/templates/:
| Template | Use for |
|---|---|
| initialize.js | New element — container setup, instance.data, event namespace |
| update.js | New element — data-first pattern, change detection, namespaced listeners |
| preview.js | New element — editor placeholder with responsive sizing |
| header.html | New element — idempotent <script> loading |
| client-action.js | New client-side action |
| server-action.js | New server-side action (v4 async/await) |
eslint.config.mjs (flat config format). VS Code auto-fixes on save via .vscode/settings.json (source.fixAll.eslint). Do not introduce a second formatter.tools
Use when work should span one or more detached tasks but still behave like one job with a single owner context. TaskFlow is the durable flow substrate under authoring layers like Lobster, ACPX, plugins, or plain code. Keep conditional logic in the caller; use TaskFlow for flow identity, child-task linkage, waiting state, revision-checked mutations, and user-facing emergence.
tools
# Lobster Lobster executes multi-step workflows with approval checkpoints. Use it when: - User wants a repeatable automation (triage, monitor, sync) - Actions need human approval before executing (send, post, delete) - Multiple tool calls should run as one deterministic operation ## When to use Lobster | User intent | Use Lobster? | | ------------------------------------------------------ | --------------------------
tools
# Lobster Lobster executes multi-step workflows with approval checkpoints. Use it when: - User wants a repeatable automation (triage, monitor, sync) - Actions need human approval before executing (send, post, delete) - Multiple tool calls should run as one deterministic operation ## When to use Lobster | User intent | Use Lobster? | | ------------------------------------------------------ | --------------------------
tools
A CLI tool for making authenticated requests to the X (Twitter) API. Use this skill when you need to post tweets, reply, quote, search, read posts, manage followers, send DMs, upload media, or interact with any X API v2 endpoint.