Appearance
Script Library
The Script Library is a standalone repo (Script-Library) containing pre-built JavaScript scripts for the Creative Engine flow system. Scripts are authored with JSDoc metadata, built into a manifest, and served from CDN. The Builder (Application-Frontend) consumes the manifest so designers can select and configure scripts without writing code.
Architecture
Script-Library repo
└─ scripts/ ← .js files with JSDoc headers
└─ build/ ← generate-manifest.js
└─ dist/ ← built output (manifest + scripts)
↓ deploy (Cloudflare Pages, auto on push to main)
CDN: script-library.pages.dev
├─ script-library.json ← manifest (all script metadata)
└─ scripts/{category}/{name}.js ← script source files
↓ fetched at runtime
Application-Frontend (src/services/scriptLibrary.ts)
├─ getManifest() → fetches + caches manifest
├─ getScriptSource() → fetches + caches individual script source
└─ assembleScript() → wraps source with PARAMS injection
↓ used by
LibraryScriptOp.vue (flow operator in the Builder)
├─ Shows script picker (SearchableDropdown)
├─ Renders param form based on manifest metadata
└─ Calls assembleScript() → saves assembled <script> to operator bodyHow Scripts Reach the Creative
- Authoring — Designer selects a script and configures params in the Builder's LibraryScriptOp
- Assembly —
assembleScript()prependsconst PARAMS = {...};to the script source and wraps it in a<script>tag - Storage — The assembled script is saved to the operator's
body.inputText.value(same field as custom scripts) - Publishing — The Creative Composer bakes the script into the published creative. Published creatives have no runtime CDN dependency — the script source is embedded at publish time
- Execution — The Creative Engine executes the script when the flow reaches the operator, same as any custom script
Deployment
Hosted on Cloudflare Pages. Pushes to main auto-deploy:
| Asset | URL |
|---|---|
| Manifest | https://script-library.pages.dev/script-library.json |
| Scripts | https://script-library.pages.dev/scripts/{category}/{name}.js |
Local development: The Frontend uses http://localhost:8090 when running in dev mode (see CDN_BASE in scriptLibrary.ts). Run a local server from the Script-Library dist/ folder on port 8090 to test changes before deploying.
Update Flow
To update a script in production:
- Edit the script in
Script-Library/scripts/{category}/{name}.js - Run
npm run buildto regenerate the manifest and dist - Push/merge to
main→ Cloudflare Pages auto-deploys - The Builder fetches the updated manifest and source on next load
- Existing published creatives are NOT affected — they have the script baked in. Only newly published (or re-published) creatives will use the updated script
Writing Scripts
Each script is a .js file in scripts/ with a JSDoc metadata header:
js
/**
* @script Image Swap with Delay
* @description Swaps an image element after a configurable delay
* @requires image
* @param {element} targetElement - Element to swap
* @param {url} imageUrl - URL of the new image
* @param {number} delayMs - Delay before swap in milliseconds (default: 0)
* @param {select} easing - Easing function
* @option easing linear - Linear
* @option easing easeOut - Ease Out
*/
const target = PARAMS.targetElement
const url = PARAMS.imageUrl
// script logic...Metadata Tags
| Tag | Purpose |
|---|---|
@script | Display name in the Builder dropdown |
@description | Shown below the dropdown when selected |
@requires | Filters visibility — script only shown if the creative has this block/operator type (e.g. answer, image). Does NOT affect execution |
@param | Defines a configurable parameter |
@option | Defines options for select type params |
Parameter Types
| Type | Builder UI | PARAMS Value |
|---|---|---|
string | Text input | Free text |
number | Number input | Numeric value |
boolean | Toggle switch | true / false |
url | Text input with URL validation | URL string |
color | Color picker | Hex string |
select | Dropdown (options via @option tags) | Selected option value |
element | TargetOpSelector (element picker) | Element abbreviation (e.g. "bg1", "t1") |
element-list | Multi-select element picker | Array of abbreviations |
element-pairs | Source → Target mapping UI | Array of { source, target } objects |
block | Block/step picker dropdown | Block key from the flow |
video | Video upload with thumbnail | Cloudflare Stream UID |
Parameter Rules
- Parameters without
(default: ...)are required — the Builder validates them before saving - Parameters with
(default: ...)are optional and use that default value selecttype requires@option paramKey value - Labeltags- Access all parameters via the global
PARAMSobject at runtime
Available Globals
Scripts execute through the Engine's Tag/Script pipeline and have access to:
PARAMS— Object containing all configured parameter valuesDATASTORE— Creative statechangeImage(abbrev, url),changeText(abbrev, text),changeUrl(abbrev, url),changeVideo(abbrev, url)showHideFunctions.hideElement(abbrev),showHideFunctions.showElement(abbrev)resetCreative(),restartFlow()ANALYTICS.sendEvent({...})
Key Source Files
| File | Repo | Purpose |
|---|---|---|
scripts/flow/choice-click-target.js | Script-Library | Maps button clicks to choice clicks for analytics tracking (see analytics/visual-element-tracking-gap.md) |
scripts/{category}/*.js | Script-Library | Script source files |
build/generate-manifest.js | Script-Library | Parses JSDoc → generates manifest |
src/services/scriptLibrary.ts | Application-Frontend | CDN fetch, caching, assembly |
src/pages/.../operators/LibraryScriptOp.vue | Application-Frontend | Builder UI for script selection and param configuration |
Script Categories
Scripts are organized into subdirectories under scripts/:
| Category | Purpose |
|---|---|
flow | Flow logic -- choice routing, conditional branching, button-to-choice mapping |
visual | Visual effects — image swaps, responsive adjustments |
high-impact | High-impact format integrations — skin placements |