PinePaper

Other

Create and animate vector-based text, shapes, diagrams, and visualizations on an infinite canvas with resolution-independent export and rich animation and re...

Install

openclaw skills install pinepaper

PinePaper Studio — AI Agent Skills Reference

What is PinePaper? A professional web app for creating animated text, graphics, diagrams, and data visualizations on an infinite canvas. Powered by Paper.js vector math — everything is resolution-independent and exportable.

How AI agents use it: Via MCP tools (@pinepaper.studio/mcp-server) or the Agent Mode JS API (window.PinePaperAgent).


Table of Contents


Item Creation

Create items with app.create(type, params). All items are vector-based and infinitely scalable.

Item Types

TypeKey Parameters
textcontent, fontSize, fontFamily, fontWeight, color, x, y
circleradius, fillColor, strokeColor, x, y
rectanglewidth, height, fillColor, cornerRadius, x, y
ellipseradiusX, radiusY, fillColor, x, y
triangleradius, fillColor, x, y
starradius, points, innerRadius, fillColor, x, y
polygonradius, sides, fillColor, x, y
linefrom, to, strokeColor, strokeWidth
pathsegments, strokeColor, closed
arcfrom, through, to, strokeColor

Common Parameters (All Items)

x, y              — Position
fillColor         — Fill (hex, rgba, or gradient object)
strokeColor       — Stroke color
strokeWidth       — Stroke width
opacity           — 0-1
rotation          — Degrees
scale / scaleX/Y  — Uniform or axis scale
shadowColor       — Shadow color
shadowBlur        — Shadow blur radius
shadowOffset      — [dx, dy]
blendMode         — CSS blend mode string
label             — String or { content, position, fontSize, color }

Gradient Colors

fillColor: {
  type: 'linear',   // or 'radial'
  stops: [
    { color: '#ff0000', offset: 0 },
    { color: '#0000ff', offset: 1 }
  ],
  origin: [100, 100],
  destination: [500, 500]
}

Batch Operations

app.batchCreate([
  { type: 'text', params: { content: 'Hello', x: 200, y: 200 } },
  { type: 'circle', params: { radius: 50, x: 400, y: 300 } }
]);

Animation

Simple Animations

Apply via app.animate(item, { animationType, animationSpeed }) or inline during creation.

TypeEffectKey Params
pulseScale breathingspeed, intensity
rotateContinuous spinspeed
bounceVertical bouncespeed, intensity
fadeOpacity pulsespeed, intensity
wobbleSide-to-side rockspeed, intensity
shakeRapid jitterspeed, intensity
swingPendulum swingspeed, intensity
jellyElastic squash/stretchspeed, intensity
typewriterCharacter-by-character revealspeed

Inline Animation

app.create('text', {
  content: 'Hello World',
  x: 400, y: 300,
  animationType: 'bounce',
  animationSpeed: 1.2,
  animationIntensity: 0.15
});

Relations

Relations define persistent inter-item behaviors. Add with app.addRelation(sourceId, targetId, type, params).

Motion Relations

RelationDescriptionKey Params
orbitsCircular motion around targetradius, speed, direction, phase
followsMove toward targetoffset, smoothing, delay
attached_toMove with targetoffset, inherit_rotation
maintains_distanceStay fixed distancedistance, strength
points_atRotate to face targetoffset_angle, smoothing
mirrorsMirror positionaxis, center
parallaxDepth-based movementdepth, origin
bounds_toStay within boundspadding, bounce
spring_followPhysics spring motionstiffness, damping, mass, maxDisplacement

Animation Relations

RelationDescriptionKey Params
grows_fromScale in from zeroorigin, duration, delay, easing
staggered_withStaggered effectindex, stagger, effect
indicatesHighlight pulsescale, color, duration, repeat
circumscribesDraw shape around targetshape, color, strokeWidth, fadeOut
wave_throughWave distortionamplitude, frequency, direction
morphs_toShape morphduration, easing, morphColor, morphSize

Camera Relations

RelationDescriptionKey Params
camera_followsView tracks itemsmoothing, offset, zoom, deadzone
camera_animatesKeyframe camerakeyframes, duration, loop

Procedural Relations

RelationDescriptionKey Params
wiggleNoise-driven motionproperty, frequency, amplitude, seed
driven_byProperty linkingsourceProperty, targetProperty, multiplier
time_expressionMath-based motionproperty, expression, baseValue

Character Relations

RelationDescriptionKey Params
part_ofSemantic childrole (e.g., eye_left, mouth)
expressesFacial expressionexpression, interval, duration

Convenience Methods

app.addRelation(sourceId, targetId, type, params);
app.removeRelation(sourceId, targetId, type);
app.replaceRelation(sourceId, targetId, type, params);
app.getRelations(itemId);
app.hasRelation(sourceId, targetId, type);
app.addParts(parentId, { eye_left: id1, eye_right: id2 });

Time-Scoped Relations

Any relation supports startTime, endTime, and autoRemove to limit when it's active during timeline playback.


Keyframe Animation

Full timeline-based animation with per-property easing, spatial paths, and morphing.

app.create('circle', {
  radius: 40, x: 100, y: 300,
  animationType: 'keyframe',
  keyframes: [
    { time: 0, properties: { x: 100, opacity: 0 }, easing: 'easeOut' },
    { time: 1, properties: { x: 500, opacity: 1 } },
    { time: 2, properties: { x: 500, y: 100, scale: 2 }, easing: 'bounce' }
  ]
});

Animatable Properties

x, y, position, scale, scaleX, scaleY, rotation, opacity, fillColor, strokeColor, fontSize, strokeWidth, shadowBlur, shadowOffsetX, shadowOffsetY, segments (path morphing), trimStart, trimEnd, trimOffset

Easing Functions

linear, easeIn, easeOut, easeInOut, easeInCubic, easeOutCubic, easeInOutCubic, bounce, elastic, or custom cubic bezier [x1, y1, x2, y2]

Per-Property Easing

{ time: 1, properties: { x: 500, y: 100 }, propertyEasings: { x: 'bounce', y: 'easeOut' } }

Spatial Motion Paths

{ time: 0, properties: { x: 100, y: 300 }, spatialHandles: { out: [50, -100] } },
{ time: 1, properties: { x: 500, y: 300 }, spatialHandles: { in: [-50, -100] } }

Trim Paths (Line Draw Effect)

app.create('path', {
  segments: [[100, 300], [700, 300]],
  strokeColor: '#3b82f6',
  animationType: 'keyframe',
  keyframes: [
    { time: 0, properties: { trimEnd: 0 } },
    { time: 2, properties: { trimEnd: 1 }, easing: 'easeOut' }
  ]
});

Timeline Playback

app.playKeyframeTimeline(duration, loop);
app.pauseKeyframeTimeline();
app.stopKeyframeTimeline();
app.seekKeyframeTimeline(time);

Animation Presets Library

Import from js/templates/_shared/animations.js:

Reveal: fadeInUp, fadeInDown, fadeInLeft, fadeInRight, fadeIn Scale: popIn, explosivePop, scalePulse, breathe Physics: gravityDrop, rubberBand, swing, elasticSnap Paths: spiralIn, sineFloat, figureEight, circularOrbit Glitch: glitchFlicker, motionBlurSnap, cyberScan Exit: zoomOut, fadeOutDown, hingeDrop, shrinkAway


Text & Typography

Letter Collage

Break text into individually styled/animated letters:

const collage = app.letterCollage.create('HELLO', {
  style: 'tile',        // tile, magazine, paperCut, fold, gradient
  palette: 'neon',       // wordle, scrabble, candy, neon, rainbow, pastel, etc.
  fontSize: 48,
  x: 200, y: 150
});

Tile Palettes: wordle, scrabble, candy, neon, rainbow, pastel, cotton, earth, ocean, forest, sunset, corporate, minimal, monochrome, christmas, halloween, valentines, magazine, ransom, newspaper

Gradient Palettes: rainbow, sunset, fire, gold, rose, ocean, ice, forest, midnight, cyberpunk, neonGlow, chrome

Staggered Letter Animation

app.letterCollage.applyStaggeredAnimation(collageId, {
  effect: 'fadeSlideUp',   // fadeSlideDown, popIn, typewriter, wave
  staggerDelay: 0.1,
  duration: 0.5,
  sequence: 'linear'       // reverse, random, center, fibonacci, wave
});

Cursive Handwriting

app.createCursiveText('Hello World', {
  x: 200, y: 300, scale: 2,
  strokeColor: '#f59e0b', strokeWidth: 3,
  animate: true, duration: 3
});

Font Studio

Create custom fonts from drawn glyphs:

app.fontStudio.createGlyph(char, paperPath);
app.fontStudio.downloadFont('otf');
app.fontStudio.loadIntoDocument();

Diagrams & Flowcharts

Create Diagram Shapes

app.diagramSystem.createShape('process', { position: new Point(x, y), label: 'Step 1' });
app.diagramSystem.createShape('decision', { position: new Point(x, y), label: 'Yes/No?' });

Shape Types: process, decision, terminal, data, document, database, cloud, server, uml-class, uml-usecase

Comment Shapes: speech-bubble, speech-bubble-square, thought-bubble, comment-box, speech-bubble-pointed, double-bubble, quote-bubble, callout-box

Connect & Layout

app.diagramSystem.connect(shape1, shape2);
await app.diagramSystem.applyLayout(null, 'hierarchical', { direction: 'TB' });

Layout Algorithms: hierarchical, force-directed, tree, radial, grid

Mermaid Import/Export

// Import Mermaid syntax
const result = app.importMermaid(`
  graph TD
    A[Start] --> B{Decision}
    B -->|Yes| C[Action]
    B -->|No| D[End]
`);

// Export current diagram as Mermaid
const mermaid = app.exportMermaid({ direction: 'LR' });

Arrow System

app.arrowSystem.createArrow([point1, point2], {
  lineColor: '#333', lineWidth: 2,
  headStyle: 'stealth'   // classic, stealth, sharp, open, none
});

Maps & Geospatial

Load a Map

const map = await app.mapSystem.loadMap('world', {
  projection: 'naturalEarth',
  quality: 'standard',
  interactive: true,
  showOcean: true
});

Available Maps: world, worldHighRes, usa, usaCounties, canada, india, europe

Projections: naturalEarth, mercator, robinson, orthographic, equirectangular, albers, albersUsa, conicEqualArea, winkelTripel

Choropleth & Data Visualization

app.mapSystem.applyDataColors(
  { 'USA': 90, 'CAN': 75, 'MEX': 60 },
  { colorScale: ['#f7fbff', '#08519c'], legend: true, legendTitle: 'Score' }
);

Region Control

app.mapSystem.highlightRegions(['USA', 'CAN'], { fill: '#ef4444' });
app.mapSystem.animateReveal('all', { duration: 1, stagger: 0.05, effect: 'fadeIn' });

Markers & Labels

app.mapSystem.addMarker(-122.4, 37.8, { shape: 'pin', label: 'San Francisco' });
app.mapSystem.addRegionLabel('USA', { content: 'United States', fontSize: 14 });

Region Animation

app.animateMapWave({
  duration: 10, loop: true,
  colors: ['#ef4444', '#fbbf24', '#22c55e', '#3b82f6'],
  waveDirection: 'horizontal'
});

Import/Export

app.mapSystem.exportSVG();
app.exportMapGeoJSON({ includeStyles: true });
app.exportMapRegionDataCSV();
await app.importCustomMap(geoJson);

Masking & Reveal Effects

Static Masks

app.applyMask(item, 'circle', { radius: 100 });
app.applyMask(item, 'star', { points: 5, radius: 80 });

Mask Types: rectangle, circle, ellipse, star, triangle, hexagon, heart, rounded, custom

Mask Modes: clip (show inside), subtract (show outside), intersect (overlap only)

Animated Mask Reveals

app.applyAnimatedMask(item, 'wipeLeft', { duration: 0.8 });

Preset Animations: wipeLeft, wipeRight, wipeUp, wipeDown, iris, irisOut, star, heart, curtainHorizontal, curtainVertical, cinematic, diagonalWipe, revealUp, revealDown

Mask Stacking

app.maskingSystem.addMask(item, 'circle', { mode: 'clip' });
app.maskingSystem.addMask(item, 'rectangle', { mode: 'subtract' });

Visual Effects

Apply particle/FX effects to items:

app.applyEffect(item, 'sparkle', { color: '#ffd700', speed: 2 });
app.applyEffect(item, 'confetti', { colors: ['#ff0', '#f0f', '#0ff'], count: 50 });

Effect Types:

EffectKey Params
sparklecolor, speed, size
blastcolor, radius, count, interval
firecolor, size, turbulence
smokecolor, size, drift
raincolor, count, speed, angle
snowcolor, count, speed, spread
confetticolors[], count, gravity
ripplecolor, maxRadius, ringCount
glowcolor, speed, intensity
electriccolor, boltCount, length

Image Filters

GPU-accelerated filters for raster images:

await app.applyImageFilter(raster, 'blur', { radius: 5 });

// Chain multiple filters
await app.applyImageFilterChain(raster, [
  { name: 'brightness', params: { value: 20 } },
  { name: 'contrast', params: { value: 15 } },
  { name: 'vignette', params: { intensity: 0.5 } }
]);

Filters: grayscale, sepia, brightness, contrast, saturation, invert, posterize, hsl, colorTint, vignette, edgeDetect, blur

Cutout Style Presets

await app.applyCutoutStyle(item, 'sticker');

Presets: papercut, postcard, sticker, poster, monochromeCut, edgeSketch, warmGlow, coolTone


Rigging & Skeletal Animation

Create a Skeleton

const skeletonId = app.riggingSystem.createSkeleton('character', { x: 400, y: 500 });
const spine = app.riggingSystem.addBone(skeletonId, { name: 'spine', length: 100, angle: -90 });
const head = app.riggingSystem.addBone(skeletonId, { name: 'head', length: 40, angle: -90, parentBoneId: spine });

Rig Presets

Apply a full preset skeleton in one call:

const preset = getRigPreset('humanoid');
const { boneMap, chainIds } = applyRigPreset(app.riggingSystem, skeletonId, preset);

Presets: humanoid (20 bones), quadruped (13), spider (19), bird (15), fish (14), hand (17), centaur (29), simple_arm (3), snake (10), chain (5)

IK Solvers

app.riggingSystem.createIKChain(skeletonId, {
  name: 'left_arm', boneIds: [upperArm, lowerArm],
  solverType: 'two_bone'   // 'fabrik', 'two_bone', 'ccd'
});

Poses & Shape Keys

// Save/load poses
const poseId = app.riggingSystem.savePose(skeletonId, 'wave');
app.riggingSystem.loadPose(skeletonId, poseId);
app.riggingSystem.interpolatePoses(poseA, poseB, 0.5);

// Shape keys (blend shapes)
const blinkKey = app.riggingSystem.saveShapeKey(skeletonId, 'blink');
app.riggingSystem.loadShapeKey(skeletonId, blinkKey, 0.8);  // weight 0-1

Expressions

Built-in facial expressions: blink, smile, frown, surprise, wink, talk

app.addRelation(faceId, null, 'expresses', { expression: 'blink', interval: 3 });

Path Skinning (2D LBS)

app.riggingSystem.skinPath(skeletonId, itemId, { maxInfluences: 2 });

Blending & Compositing

app.blendingSystem.applyPreset(itemId, 'neon');
app.blendingSystem.transitionBlendMode(itemId, 'screen', { duration: 0.5 });
app.blendingSystem.setGroupBlendMode(groupId, 'multiply', { cascadeOpacity: true });

Presets: ghost, neon, shadow, glow, xray, dreamy, vintage

Blend Modes: normal, multiply, screen, overlay, darken, lighten, color-dodge, color-burn, hard-light, soft-light, difference, exclusion, hue, saturation, color, luminosity

Interactive Blending

app.blendingSystem.addInteractiveBlend(itemId, {
  event: 'hover',
  modes: ['normal', 'screen'],
  opacities: [1.0, 0.8]
});

3D Projection

Render 3D primitives onto the 2D canvas:

app.createObject3D('cube', { size: 1.5, color: '#3b82f6', rotationY: 45 });
app.createObject3D('sphere', { radius: 1, color: '#ef4444' });
app.createGlossySphere({ x: 400, y: 300, radius: 60, color: '#F97316' });

app.setProjection3D('perspective', { fov: 60 });
app.setCamera3D({ position: { x: 3, y: 2, z: 5 }, target: { x: 0, y: 0, z: 0 } });

Primitives: cube, sphere, cylinder, torus, cone

Projections: perspective, orthographic, isometric, cabinet, cavalier


Background Generators

Procedural animated backgrounds:

app.executeGenerator('drawBokeh', { circleCount: 30, animated: true });
app.executeGenerator('drawConstellation', { animated: true });
app.executeGenerator('drawWaves', { waveCount: 8, fill: true, animated: true });

Generators:

NameDescription
drawBokehDepth-of-field circles
drawGradientMeshMulti-color gradient blobs
drawOrganicFlowAurora/silk flowing layers
drawWavesFlowing wave lines
drawStarfieldAnimated starfield
drawNeonGridGlowing neon grid
drawCircuitCircuit board with pulses
drawConstellationConnected star points
drawGridCustomizable animated grid
drawSunburstRadiating rays
drawFlowFieldDirectional flow particles
drawNoiseTexturePerlin noise texture
drawKaleidoscopeKaleidoscope pattern
drawTessellationGeometric tiling
drawSunsetSceneAnimated sunset
drawCosmosSpaceSpace scene
drawFirefliesFloating fireflies
drawFallingPetalsFalling petals
drawGeometricAbstractOverlapping shapes
drawMetaballsOrganic blobs
drawGoldenSpiralGolden ratio spiral
drawPerspectiveGrid3D perspective grid

Camera Control

app.camera.zoomIn(2, 0.5);           // Zoom 2x over 0.5s
app.camera.panTo(200, 200, 0.5);     // Pan to point
app.camera.moveTo(200, 200, 2, 0.5); // Pan + zoom
app.camera.reset(0.5);               // Reset view

// Keyframe camera animation
app.addRelation('camera', null, 'camera_animates', {
  duration: 6, loop: true,
  keyframes: [
    { time: 0, zoom: 1, center: [400, 300] },
    { time: 3, zoom: 2, center: [600, 300], easing: 'easeInOut' },
    { time: 6, zoom: 1, center: [400, 300] }
  ]
});

Export Formats

FormatMethodNotes
WebMExport UIVP9, best for animations
MP4Export UIH.264 via WebCodecs (Chrome 94+)
GIFExport UIVia gif.js Web Workers
Animated SVGapp.exportAnimatedSVG()SMIL or CSS animations
PNGExport UIUp to 600 DPI
PDFapp.exportPDF({ dpi })300/600 DPI, bleed, trim marks
Lottieapp.exportLottie({ fps, duration })JSON for any Lottie player
GeoJSONapp.exportMapGeoJSON()Map data export
Mermaidapp.exportMermaid()Diagram text export

Canvas & View Management

Canvas Presets

app.setCanvasSize('instagram-post');    // 1080x1080
app.setCanvasSize('youtube-thumbnail'); // 1280x720
app.setCanvasSize('tiktok');            // 1080x1920
app.setCanvasSize({ width: 1920, height: 1080 }); // Custom

Presets: youtube-thumbnail, instagram-post, instagram-story, tiktok, a4-portrait, letter-portrait, and more.

View Control

app.getCanvasSize();  // { width, height, preset }
app.expandCanvasToIncludeContent(20);  // Fit to content + padding

Selection & Queries

app.select(item);
app.deselect();
app.selectAll();
app.deselectAll();
app.getSelection();

// Registry
app.itemRegistry.getAll();
app.itemRegistry.getByType('text');
app.itemRegistry.getItem(itemId);

// Relation queries
app.hasRelation(sourceId, targetId, type);
app.queryNotRelation(type);        // Items without relation
app.queryIsolatedItems();          // Items with no relations
app.queryCompound([...conditions]);
app.queryRelationChain([...types]);

History

app.undo();
app.redo();
app.getHistoryState();  // { canUndo, canRedo, undoCount, redoCount }
app.clearCanvas();

Agent Mode Quick Start

Activate via URL ?agent=1 or ?mode=agent:

const agent = window.PinePaperAgent;
await agent.configure({ mode: 'agent' });
await agent.waitForReady();

// Create content
const text = app.create('text', { content: 'Hello', x: 400, y: 300, fontSize: 48 });
app.animate(text, { animationType: 'pulse' });

// Export
const result = await agent.quickExport();

// Reset for new canvas
agent.reset({ canvas: 'tiktok' });

Smart Export

const rec = agent.getExportRecommendation();
// { format: 'webm', reason: 'Has animations, WebM gives best quality' }

MCP Tool Reference

The MCP server (@pinepaper.studio/mcp-server) exposes these tools:

Item Tools

  • pinepaper_create_item — Create any item type
  • pinepaper_modify_item — Modify item properties
  • pinepaper_batch_create — Create multiple items

Animation Tools

  • pinepaper_animate — Apply simple animation
  • pinepaper_keyframe_animate — Apply keyframe animation

Relation Tools

  • pinepaper_add_relation — Add relation between items
  • pinepaper_remove_relation — Remove relation

Diagram Tools

  • pinepaper_create_diagram_shape — Create flowchart shape
  • pinepaper_connect — Connect shapes
  • pinepaper_auto_layout — Apply layout algorithm

Map Tools

  • pinepaper_load_map — Load geographic map
  • pinepaper_highlight_regions — Highlight regions
  • pinepaper_apply_data_colors — Choropleth coloring
  • pinepaper_add_marker — Add map marker

Rigging Tools

  • pinepaper_create_skeleton — Create skeleton
  • pinepaper_add_bone — Add bone
  • pinepaper_attach_item_to_bone — Attach item
  • pinepaper_apply_rig_preset — Apply preset
  • pinepaper_save_pose / pinepaper_load_pose — Pose management
  • pinepaper_interpolate_poses — Blend poses

Blending Tools

  • pinepaper_apply_blend_preset — Apply blend preset
  • pinepaper_transition_blend_mode — Animated blend transition
  • pinepaper_add_interactive_blend — Interactive blending
  • pinepaper_set_group_blend_mode — Group blending

Filter Tools

  • pinepaper_apply_image_filter — Single GPU filter
  • pinepaper_apply_filter_chain — Multi-filter chain

Masking Tools

  • pinepaper_apply_cutout_style — Apply cutout preset
  • pinepaper_get_cutout_styles — List presets

Lasso Tools

  • pinepaper_lasso_activate — Activate lasso on image
  • pinepaper_lasso_apply — Extract region

View Tools

  • pinepaper_zoom — Set zoom level
  • pinepaper_pan — Pan view
  • pinepaper_fit_view — Fit content in view
  • pinepaper_get_view_state — Get current view

Selection Tools

  • pinepaper_select — Select item
  • pinepaper_select_all — Select all
  • pinepaper_deselect_all — Deselect all
  • pinepaper_get_selection — Get selection
  • pinepaper_delete_selected — Delete selected

Transform Tools

  • pinepaper_nudge — Move items
  • pinepaper_flip — Flip items
  • pinepaper_reorder — Change z-order

Background Tools

  • pinepaper_set_background — Set background
  • pinepaper_clear_background — Clear background
  • pinepaper_get_background — Get background

History Tools

  • pinepaper_undo / pinepaper_redo — Undo/redo
  • pinepaper_get_history_state — Get history state
  • pinepaper_clear_canvas — Clear canvas

Query Tools

  • pinepaper_query_items — Query items by criteria
  • pinepaper_get_item_by_id — Get specific item
  • pinepaper_hit_test — Hit test at point
  • pinepaper_is_empty — Check if canvas empty

Precomp Tools

  • pinepaper_create_precomp — Create composition
  • pinepaper_add_to_precomp — Add to composition
  • pinepaper_remove_from_precomp — Remove from composition

Playback Tools

  • pinepaper_play_timeline — Play keyframe timeline
  • pinepaper_stop_timeline — Stop playback
  • pinepaper_pause_timeline — Pause playback
  • pinepaper_seek_timeline — Seek to time

Export Tools

  • pinepaper_export_svg — Export as SVG
  • pinepaper_export_training_data — Export training data

Generator Tools

  • pinepaper_execute_generator — Run background generator
  • pinepaper_list_generators — List available generators

Font Tools

  • pinepaper_font_create_glyph — Create font glyph
  • pinepaper_font_export — Export font file
  • pinepaper_font_status — Get font creation status