Plugins overview.
A plugin is a piece of server-side JavaScript that runs inside the request pipeline. It subscribes to hooks, reads and writes site data through a capability model, and runs in a sandbox with a strict time and memory budget. It is how you add behaviour that Liquid alone cannot express.
Where a template describes a page, a plugin runs logic: rewrite a response header, add data to the render context, transform the finished HTML, or react when a lead comes in. Plugins are per site. Each is a record with its code, the hooks it listens on, its capability grants and its limits.
The sandbox
Plugin code runs in an isolated V8 sandbox, one per plugin and version. It has no ambient access to the network, the filesystem or the host process. It cannot use eval, the Function constructor, timers, require or process; code containing those is rejected when you save it. Everything a plugin can reach, it reaches through a single provided fs object.
Every invocation is bounded. If a plugin exceeds its time budget the sandbox is discarded, and a plugin that throws or times out never breaks the request: the pipeline logs the failure and carries on with the unmodified value.
The plugin record
A plugin is defined by these fields. The three allow-lists are the capability model: all default-deny, so a new plugin can do nothing until you grant it.
| Field | Meaning |
|---|---|
name, identifier | A label and a stable id for the plugin. |
code | The plugin source. It exports a handler per hook. |
hooks | The hooks it subscribes to. See Hooks. |
allowed_hosts | The hosts fs.fetch may reach. Empty means no outbound requests. |
allowed_permissions | The data grants, as . See Permissions. |
effective_role | The role cap. The plugin acts as its creator, but never above this role. |
enabled | On or off. |
timeout_ms | Time budget per run. Default 200, from 50 to 5000. |
memory_mb | Memory cap for the sandbox. Default 32, from 8 to 256. |
version | Bumped on any change that affects execution, so every server picks it up. See Building a plugin. |
The host surface
Inside a handler, everything a plugin can do is on the fs object:
| Call | What it does |
|---|---|
fs.log(level, msg, meta) | Writes to the server log. |
fs.fetch(url, init) | Makes an outbound HTTP request, only to a host on allowed_hosts, with an SSRF guard and a five second timeout. |
fs.collection(name) | Reads and writes site data: .list, .get, .create, .update, .delete, .action. Gated by allowed_permissions. |
fs.schedule | Schedules a later callback, for plugins on the scheduled hook. |
fs.collection shares the resource names and tenant scoping of the collection tag, but it is a separate mechanism: it goes through the platform API as the plugin's capped user, and unlike the read-only template tag it can also create, update and delete. Access is checked twice: against the plugin's grants, and against the role of the user it acts as.
Continue with Hooks to see when your code runs and what it receives.