Code & Custom UI
back to documentation

Code & Custom UI

Use Function Effects, JavaScript, and custom interfaces when no-code tools are not enough.

JavaScript Function

JavaScript Function lets a task run a short JavaScript program in the Portals runtime. It is useful when a rule has several steps, needs ordinary JavaScript control flow, or needs to call a small set of Portals helpers.

Start with a no-code effect or Function Effect whenever one is enough. JavaScript Function is for the cases where a clear script is easier to maintain than a deeply nested expression.

Good uses

  • Complete a conditional quest after checking several task states.
  • Update a score, then activate the next task.
  • Assign player parameters or update a shared numeric score.
  • Call a safe no-code effect on a known item through UseEffector.
  • Render a small static message with displayHtml.

Not a general web page runtime

JavaScript Function runs inside the Portals game runtime. Do not treat it as a browser tab:

  • Do not depend on fetch(), browser-window APIs, timers such as requestAnimationFrame(), or browser audio APIs.
  • Do not put a real key, secret, or private endpoint in a script.
  • Use an iframe for an interactive website, form, canvas experience, or a page that needs its own browser behavior.

Add and test a script

  1. Create the task that represents the action.
  2. Add a JavaScript Function effect to the task.
  3. Begin with one visible outcome, such as setting a task or variable.
  4. Use Test Action, then test the actual task in a fresh play session.
  5. Give every task and variable a stable, exact name before reusing it in other scripts.

A script runs when its owning task or trigger runs. Activate On Start runs it once while that task is prepared. Trigger On Tasks Change re-runs it when a state referenced by the script changes.

Do not use a script as hidden long-lived state. Save state in a named task or variable so it can be inspected in Interactive Studio.

Read task state numerically

Use $TN{Task name} for a task state:

State Value
Not Active 0
Active 1
Completed 2
if ($TN{FindKey} === 2) {
  SetTask('OpenDoor', 'Active', 0);
}

The $TN reference is resolved by Portals when the script runs. Use numeric task state checks in all examples; they are safer and clearer than state-label comparisons.

Read a value and save a result

Use $N{Value name} to read a named value:

const nextStars = Number($N{Stars}) + 1;
SetVariable('Stars', nextStars, 0);

The third SetVariable argument is a delay in seconds. It is not an operation code.

A small complete recipe

This script opens a path only after both prerequisites are complete:

const mapFound = $TN{FindMap} === 2;
const beaconLit = $TN{LightBeacon} === 2;

if (mapFound && beaconLit) {
  SetTask('OpenMountainPath', 'Active', 0);
}

Put the door, animation, notification, or other visible work on the OpenMountainPath task. The script should make the decision; the task should own its behavior.

Scope and persistence

The script does not make a task private or shared. Its target’s configuration does.

  • A single-player task or variable belongs to the current visitor.
  • A multiplayer task or numeric variable is shared in the space.
  • Do not use the same name for unrelated local and shared data.

Continue with Portals Functions for the supported helpers, then Multiplayer Functions for player lists and shared scores.