Writing the artwork

Renderers, edition inputs, lifecycle, sizing and traits.

On this page

The viewer executes a JavaScript function body for each artwork instance. Do not include HTML, an import statement, a top-level module export, or your own new p5(...) wrapper in a p5 script.

Contexts and renderers

  • p5js: the supplied p is the p5 instance. Use p.setup, p.draw, p.keyTyped and other instance methods.
  • threejs: the supplied t is your instance context; the current viewer supplies THREE. Create the scene and renderer and attach its canvas to props.container.
  • vanillajs: the supplied v is your instance context. Create your own canvas and attach it to props.container.
  • glsl: the supplied g is your instance context. Provide JavaScript that creates WebGL and compiles shaders; raw GLSL alone is not a complete posted script.

Do not assume the same runtime version will exist forever. Preserve the library versions used to validate your release and test the downloadable viewer. GPU output and font rasterization can differ between devices even when the inputs and trait choices agree.

Edition inputs

Implement context.myCustomRedrawAccordingToNewPropsHandler = props => { ... }, substituting p, t, v or g for context. The callback receives:

  • transactionHash: the full 0x-prefixed hash of the edition's mint transaction, not the code-post transaction.
  • projectId: the art project ID.
  • editionId: the edition's number within that project, starting at 1 for a real mint.
  • tokenId: the ERC-721 token number across the art platform. This differs from editionId.
  • square: the layout divisor; a single selected edition uses 1. Numeric fields may arrive as strings.
  • container: supplied to the three.js, vanilla and GLSL wrapper for your renderer's DOM output. p5's wrapper manages its own container.

The current generic callback does not supply a block hash, prevrandao, mint timestamp, VRF result, or an authenticated seed field. Do not invent those inputs. Extra project-specific data requires an explicitly supported integration.

Initialization and redraw

For p5, create a small canvas in setup and use the props callback to configure the edition. Guard against missing props. Create edition-specific state when its identity changes, and handle size changes separately. Avoid registering a new keyboard listener or starting another animation loop every time props arrive.

p.updateWithProps is bridged to the older props callback in the current viewer, but the callback above is the portable authoring convention for this client. For a non-p5 renderer, put cleanup work on context.cleanup; keep requestAnimationFrame IDs in context._animationId and dispose GPU resources.

A useful sizing pattern is Math.min(window.innerWidth, window.innerHeight) * 0.8 / Number(props.square). Use fixed logical coordinates for the composition and scale to the canvas. Changing phone orientation should not choose new traits.

Each grid cell is a separate artwork. Keep state local to the posted function body or its supplied context. Avoid assignments to window, replacing browser globals, or mounting unrelated elements into the surrounding app.

Traits and metadata

Report a flat object after the edition's traits are ready:

console.log('metadata: ', {
  transactionHash: props.transactionHash,
  Palette: 'Midnight',
  Structure: 'Orbit'
});

Keep transactionHash as the original mint transaction. Do not replace it with your derived seed. Prefer stable strings or finite numbers for traits; do not put a canvas, a cyclic object, current frame, or fluctuating performance measurements in metadata.

The current viewer groups reported traits by transaction hash. Multiple editions minted in one transaction can have distinct art when the seed includes edition ID, but that grouping can conflate their statistics. This is a viewer limitation to account for before designing a batch release.

Deterministic identity and time

Use a local seeded stream for persistent composition and traits. Math.random() and crypto.getRandomValues() are suitable for generating preview inputs, not the permanent identity of a rendered edition. Animation may evolve over frames or time if that is the artwork's design; document its clock, initial state and replay expectations.

See the working starter, controls and seed guidance.

Source basis: P5Wrapper, ThreeWrapper, Grid, WizardProvider and BlockchainProvider in clients/art/src/.

Use this guide with an assistantRead the Technical Reference brief