Developer

Filters

Transform data through a priority-ordered chain of handlers.

Filters (Data Transformation)

Filters pass a value through a chain of handlers. Each handler can transform the value before passing it to the next.

Capability required: hooks:provide (to register filter handlers) and/or hooks:consume (to apply filters)

Registering a filter handler

// Applet A (capability: hooks:provide)
rp.hooks.addFilter("weather:format_temp", (value) => {
  // Convert Fahrenheit to Celsius
  return { ...value, tempC: Math.round((value.tempF - 32) * 5 / 9) };
}, { priority: 10 });

Applying a filter

// Applet B (capability: hooks:consume)
const result = await rp.hooks.applyFilter("weather:format_temp", { tempF: 72 });
console.log(result); // { tempF: 72, tempC: 22 }

Priority

Multiple handlers on the same filter run in priority order (lower number first). Default priority is 10.

// Runs first (priority 5)
rp.hooks.addFilter("myapp:process_data", handler1, { priority: 5 });

// Runs second (priority 10, default)
rp.hooks.addFilter("myapp:process_data", handler2);

// Runs third (priority 20)
rp.hooks.addFilter("myapp:process_data", handler3, { priority: 20 });

Each handler receives the return value of the previous handler.

API Reference

rp.hooks.addFilter(hookName, handler, opts?)

Register a filter handler.

ParameterTypeDescription
hookNamestringFilter name
handler(value: unknown) => unknownTransform function (can be async)
opts.prioritynumber (optional)Execution order (default: 10, lower runs first)

rp.hooks.applyFilter(hookName, value)

Run a value through all registered filter handlers.

ParameterTypeDescription
hookNamestringFilter name
valueunknownInitial value to transform
ReturnsPromise<unknown>Transformed value

If no handlers are registered, the original value is returned unchanged.

rp.hooks.removeFilter(hookName)

Remove your applet’s filter handler for a hook.

ParameterTypeDescription
hookNamestringFilter name to unregister from

Manifest Configuration

Declare which hooks your applet provides and consumes:

{
  "capabilities": [
    "hooks:provide",
    "hooks:consume"
  ]
}

Use hooks:provide if your applet registers filter handlers. Use hooks:consume if your applet applies filters. Most applets that use hooks will need both.

Naming Convention

Hook names use a namespace prefix followed by a colon:

{namespace}:{event_name}

Examples:

  • weather:format_temp - weather applet exposes a temperature formatting filter
  • theme:render_header - theme applet exposes a header rendering filter

Use your applet’s name or ID as the namespace to avoid collisions.

Example: Plugin System

// Theme applet provides a filter for page rendering
rp.hooks.addFilter("theme:render_header", (html) => {
  return html + '<div class="announcement-bar">Sale today!</div>';
});

// Main app applies the filter
const headerHtml = await rp.hooks.applyFilter("theme:render_header", "<header>...</header>");

Backend Limitations

From the Node.js backend, applyFilter and removeFilter work normally. However, addFilter is not yet available from backends - use the frontend SDK for registering filter handlers.