Private plugins enforce a maximum 100 kilobyte blob of data from external resources. Endpoints that respond with a larger payload will be rejected.
But it's not always possible to reduce a payload with request parameters alone. Introducing the transformer sandbox runtime.
Join the Beta
This feature is currently behind a feature flag. To give it a spin,
Join TRMNL's Developer-only Discord (link on your Account tab).
Add your Discord username to your Account > Discord field.
Navigate to Discord > #plugins channel > Sandbox Beta thread.
Example use case
Create a private plugin that sometimes yields a large JSON object. As is, this plugin will soon go into a degraded state when the response is too large (> 100 kb).
Visit the Markup Editor > Transform tab and filter the payload with JavaScript (Node v22), returning a new object.
Wrap your logic with the transform() function like so:
function transform(input) {
return {
// parsed payload goes here
}
}The input variable contains the complete original payload.
Trigger a force refresh from the plugin settings screen, then find your new payload object back inside the Markup Editor.
Benefits of using this sandbox
In addition to making otherwise disallowed plugin endpoints possible, the transformer() strategy can enhance your developer experience overall.
Cleaner code
If your plugin needs just a few bits of data but you find yourself traversing deeply nested nodes to find it, surfacing those values as top level JSON objects can simplify your plugin's markup.
Deeper functionality
TRMNL is committed to making Liquid templating a formidable tool in plugin development. But let's not pretend JavaScript isn't a lot more powerful. As plugins become more advanced we hope to reduce the learning curve with data parsing inside this sandbox versus alongside your markup.
Usage notes
The Node.js runtime lives inside an isolated-vm.
Execution timeout is capped at 1 second.
Internet access is disallowed -- sorry, no Underscore.js.
Troubleshooting
How to access other variables, e.g. {{ trmnl }} form field values?
The trmnl global variable node is available as input.trmnl. To leverage a custom form field value with keyname genre, for example:
function transform(input) {
let userFilter = input.trmnl.plugin_settings.custom_fields_values.genre;
return {
// parsed payload that leverages userFilter goes here
}
}
How can I debug my JavaScript?
We suggest retrieving a (large, realistic) payload independently of the TRMNL platform, then writing a parser separately. Enable debug logs for lightweight hints at what may be causing issues, for example a missing semi-colon. In the future we hope to expose more native JavaScript exceptions.
(JavaScript) Examples
Limiting the Size of an Array of Objects
Data
Inside Your Variables you have {{ actions }} (seen below), a top-level key in the JSON you are polling; it is an array of objects. There are other top-level keys in the JSON as well, but we only want to Transform this one and leave the rest untouched.
[
{
actionId: 1000
...
},
{
actionId: 1001
...
},
...
]
Transform
datais the name of the new object that will be present after the transform, aka{{ data }}....inputmakes sure to include all other key:value pairs.input.actions.slice(0, 30)returns only the first 30 entries in the array.
function transform(input) {
return {
data: {
...input,
actions: input.actions.slice(0, 30)
}
};
}
Removing a Property
Data
We want to Transform by removing the top-level property synonyms.
{
id: 12345,
word: "payload",
definition: {...},
examples: [{...},{...},{...}],
synonyms: [{...},{...},{...}],
metadata: {...}
}Transform
datais the name of the new object that will be present after the transform, aka{{ data }}.synonymsis extracted as its own variable, which is ignored....newInputvariable contains the remaining properties.
function transform(input) {
const {synonyms, ...newInput} = input;
return {
data: newInput
};
}
What's next?
JavaScript is the lingua franca of web development. Still you may prefer Ruby, its little brother Python, or Java. TRMNL is open to extending this sandbox to more runtimes (languages) to make plugin development feel native to developers of all technical backgrounds.



