Nubu
  • Features
  • How it works
  • Pricing
  • Integrations
  • FAQ
  • Contact
  • Docs
  • Blog
  • Log in
  • Log inSign up
    Nubu

    Creative automation for teams that ship campaigns, not busywork.

    Try for free
    Product
    FeaturesNubu MotionHow it worksPricingIntegrationsFAQ
    Company
    AboutContactDocsBlogLog in
    Legal
    Privacy policyTerms of serviceData deletion
    © 2026 Bear Studios · Nubu
    Introduction
    Templates overviewInstalling Nubu BuilderAdding template compsAdding propertiesAdding footageSetting defaultsExporting your templateUploading a template
    Flows overviewAvailable nodesAdding a nodeConnecting nodesWorking with dataTemplates and outputsUsing AI nodesBuilding a creative
    CampaignsTemplatesAssetsGlossariesRendersSettings
    Connecting Meta AdsConnecting Google AdsConnecting OpenAIConnecting Gemini AI StudioConnecting Anthropic
    AI Assistant overviewPrompt examplesAssistant settings and controls
    Nubu Motion scripts: the reference
    OverviewQuick startDifferences from After EffectsDeterminism
    JavaScript supportReferences and idsProject scriptsState and timeBudgets and errorsFormatting values
    GlobalTime conversionInterpolationVector mathsRandom and noiseColour conversionOther maths
    LayerCompPropertyKeyframePathGeometryProjectComponentConsoleComponentControlExpressionControl
    The property vocabularyAnimators propertiesAudio propertiesContent propertiesContents propertiesEffects propertiesExpression controls propertiesFills propertiesInstance controls propertiesLayer propertiesLayout propertiesMasks propertiesStrokes propertiesText style propertiesTransform propertiesTrim path properties
    Error codesBudgets
    Changelog
    All docs
    Motion Scripting
    / Language

    JavaScript support

    Which parts of modern JavaScript scripts can use, and the short list of exclusions that keep evaluation deterministic.

    Scripts are modern JavaScript - the current ECMAScript standard library, minus a small set of exclusions that exist to keep evaluation deterministic and sandboxed. If a construct is ordinary JavaScript and not listed below, it works: classes, arrow functions, destructuring, template literals, iterators, Map/Set, typed arrays, JSON, the full Math object and friends.

    The module shape#

    A script is a module. Its top level runs ONCE when the script compiles - the place for constants, helper functions and module-level handles - and the exported frame() runs once per evaluated frame:

    export const outputs = ["layer_1:transform.position"];
    
    const RADIUS = 120;
    
    export function frame({ time, dt, frame, fps }) {
      return [320 + Math.cos(time) * RADIUS, 180 + Math.sin(time) * RADIUS];
    }
    

    The argument to frame() carries the clock: time (seconds), dt (one frame in seconds), frame (the integer frame) and fps. The same values are available as globals, with ONE caution: inside frame() the bare word frame names the function itself, so destructure { frame } from the argument whenever you need the frame number in the body.

    Excluded on purpose#

    • eval and new Function - no code from strings; both throw immediately.
    • WeakRef and FinalizationRegistry - garbage-collector timing must never influence a frame.
    • SharedArrayBuffer and Atomics - no shared memory, no timing channels.
    • Date.now() and the real clock - Date reports the comp's time; the time zone is pinned to UTC on every host.
    • Unseeded Math.random - the global is replaced by the seeded stream, the same numbers on every machine (see Determinism).
    • Host surfaces - no fetch, no DOM, no workers, no storage. typeof window is "undefined", exactly as in any plain sandbox.

    Absent libraries#

    Intl and Temporal are not present - locale tables and calendar databases would make renders differ between machines. Format numbers with the standard tools instead (toFixed, padStart, template literals - the Formatting page collects the recipes), and do date maths in frames and seconds.

    Promises settle inside the frame#

    async helpers and promises work, but everything must SETTLE within the frame being evaluated - a frame's value cannot arrive later. A frame() whose returned promise never settles reports the typed async_unsettled error. In practice: use plain synchronous code in frame(); there is nothing asynchronous worth awaiting inside a sandbox with no outside world.

    Budgets, not trust#

    The runtime does not rely on scripts being polite. Poll budgets stop runaway loops, a memory ceiling stops runaway allocation and a stack guard stops runaway recursion - each reported as a typed status while the frame renders with base values. The numbers live on the Budgets page.