Hosted Playground first

Generate editable Scene Graph Timelines, not rendered video frames.

Start in the hosted Playground to edit Text DSL, inspect .fluxion.json, and preview with the SVG Runtime. Fluxion also generates the same editable animation IR from a Manim-like Python DSL.

scene width=1280 height=720 fps=60
camera at 0,0 scale=1
value theta = 0

path orbit d="M -170 0 C -170 -94 -94 -170 0 -170 C 94 -170 170 -94 170 0 C 170 94 94 170 0 170 C -94 170 -170 94 -170 0" at 640,390 fill="none" stroke="#38bdf8" strokeWidth=4 opacity=0.55
text title "Fluxion Motion Lab" at 640,118 size=42 fill="#e2e8f0"
math equation "x^2+y^2=r^2" at 640,200 size=38 fill="#bae6fd" renderer=katex
circle dot r=38 at 470,390 fill="#38bdf8" stroke="#0f172a" strokeWidth=5
rect target w=190 h=104 at 960,390 fill="#f97316" stroke="#fed7aa" strokeWidth=4

at 0s:
  hide target
  play AnimationGroup(Write(title), FadeIn(equation), FadeIn(orbit), FadeIn(dot), lagRatio=0.16) duration=1.4s easing=easeOut

animate theta from 0 to 6.283 duration=2.4s easing=linear
set dot.x to expr="640 + 170 * cos(theta)"
set dot.y to expr="390 + 170 * sin(theta)"
animate camera.x from 0 to -24 duration=2.4s easing=easeInOut
play Transform(dot, target) duration=1s easing=easeInOut

Text DSL commands

DSL commands you can try on GitHub Pages

Text DSL builds a Scene Graph and Timeline with one command per line. Use each card’s sample code with “Run here” to preview the command inline, or open the same sample in the Playground.

scene

Configure canvas size and fps.

scene width=960 height=540 fps=30
text label "960x540 / 30fps" at 480,270 size=42 fill="#e2e8f0"
theme

Switch default colors for following nodes and helpers.

scene width=640 height=360 fps=60
theme light accent="#2563eb"
text label "Light theme" at 320,130 size=40
circle dot r=52 at 320,230
circle

Draw a circle with radius and colors.

scene width=640 height=360 fps=60
circle dot r=58 at 320,180 fill="#38bdf8" stroke="#0f172a" strokeWidth=6
rect

Draw a rectangle with width, height, and opacity.

scene width=640 height=360 fps=60
rect card w=220 h=120 at 320,180 fill="#f97316" opacity=0.85
triangle

Draw a triangle with width and height.

scene width=640 height=360 fps=60
triangle tri w=220 h=190 at 320,180 fill="#ef4444" stroke="#7f1d1d" strokeWidth=6
line

Draw a line segment with start and end points.

scene width=640 height=360 fps=60
line axis x1=-220 y1=0 x2=220 y2=0 at 320,180 stroke="#e2e8f0" strokeWidth=8
path

Draw curves and arbitrary shapes with SVG path data.

scene width=640 height=360 fps=60
path curve d="M 80 220 C 180 60 460 60 560 220" fill="none" stroke="#38bdf8" strokeWidth=8
text

Place text with size and color.

scene width=640 height=360 fps=60
text title "Hello Text DSL" at 320,180 size=42 fill="#e2e8f0"
math

Place a LaTeX string as a math node.

scene width=640 height=360 fps=60
math formula "e^{i\pi}+1=0" at 320,180 size=44 fill="#bae6fd" renderer=katex
group

Group multiple nodes for display and animation.

scene width=640 height=360 fps=60
text label "Grouped" at 320,130 size=34 fill="#e2e8f0"
circle dot r=36 at 320,220 fill="#38bdf8"
group badge label dot
play FadeIn(badge) duration=1s
surroundingRect

Create a rectangular frame around a target node.

scene width=640 height=360 fps=60
math equation "f(x)g(x)" at 320,180 size=44 w=220 h=80 fill="#e2e8f0"
surroundingRect frame target=equation buff=12 stroke="#fbbf24" strokeWidth=5
axes

Generate a coordinate-axes helper group.

scene width=960 height=540 fps=60
axes ax at 480,270 width=700 height=300 xRange=-4,4 yRange=-2,2 stroke="#94a3b8" strokeWidth=3 xTicks=-4,-2,0,2,4 yTicks=-2,-1,0,1,2
numberPlane

Generate a Manim NumberPlane-style background grid.

scene width=960 height=540 fps=60
numberPlane plane at 480,270 xRange=-7,7 yRange=-4,4 unit=60
axisLabels

Generate Manim-style math labels at an axes helper endpoint.

scene width=960 height=540 fps=60
axes ax at 480,270 width=700 height=300 xRange=-4,4 yRange=-2,2 stroke="#94a3b8" strokeWidth=3
axisLabels labels axes=ax x="x" y="f(x)" size=28 fill="#e2e8f0"
plot

Sample a function expression into a plot path.

scene width=960 height=540 fps=60
plot curve fn=sin(t) range=-3.14,3.14 scaleX=90 scaleY=70 at 480,270 stroke="#38bdf8" strokeWidth=5 fill="none"
graphLabel

Place a Manim-style math label from a point on a plot helper.

scene width=960 height=540 fps=60
plot curve fn=sin(t) range=-3.14,3.14 scaleX=90 scaleY=70 at 480,270 stroke="#38bdf8" strokeWidth=5 fill="none"
graphLabel label plot=curve label="\sin(x)" xVal=1.57 direction=up fill="#38bdf8"
dataPolygon

Generate a polygon path from axes data coordinates.

scene width=960 height=540 fps=60
axes ax at 480,270 width=700 height=300 xRange=-4,4 yRange=-2,2 stroke="#94a3b8" strokeWidth=3
dataPolygon poly axes=ax points=-2,-0.5;0,1;2,0.5 fill="#22d3ee" opacity=0.25 stroke="#22d3ee" strokeWidth=4
dataRect

Generate an updatable rectangle from axes data coordinates.

scene width=960 height=540 fps=60
value t = 5
axes ax at 480,270 width=480 height=360 xRange=0,10 yRange=0,10 stroke="#94a3b8" strokeWidth=3
dataRect area axes=ax from=0,0 to=t,25/t fill="#58C4DD" fillOpacity=0.5 stroke="#F7D45A"
animate t from 5 to 8 duration=1s
dataDot

Generate an updatable dot from axes data coordinates.

scene width=960 height=540 fps=60
value t = 5
axes ax at 480,270 width=480 height=360 xRange=0,10 yRange=0,10 stroke="#94a3b8" strokeWidth=3
dataDot dot axes=ax point=t,25/t r=10 fill="#ffffff"
animate t from 5 to 8 duration=1s
dataLine

Generate a line segment from axes data coordinates.

scene width=960 height=540 fps=60
axes ax at 480,270 width=500 height=330 xRange=0,5 yRange=0,6 stroke="#94a3b8" strokeWidth=3
dataLine marker axes=ax from=2,0 to=2,4 stroke="#FFFF00" strokeWidth=5
dynamicLine

Generate line endpoints that follow expressions.

scene width=640 height=360 fps=60
value x = 0
value y = 0
dynamicLine connector x1=80+60*x y1=180 x2=360 y2=180-60*y stroke="#FC6255" strokeWidth=5
circle d1 r=10 at 80,180 fill="#58C4DD"
circle d2 r=10 at 360,180 fill="#83C167"
always d1.x = expr=80+60*x
always d2.y = expr=180-60*y
animate x from 0 to 2 duration=1s easing=smooth
animate y from 0 to 2 duration=1s easing=smooth
dataArea

Generate the area between two functions in axes coordinates.

scene width=960 height=540 fps=60
axes ax at 480,270 width=500 height=330 xRange=0,5 yRange=0,6 stroke="#94a3b8" strokeWidth=3
dataArea area axes=ax lower=t upper=2*t range=1,2 samples=32 fill="#888888" fillOpacity=0.5
dataRiemannRects

Generate Riemann rectangles for a function in axes coordinates.

scene width=960 height=540 fps=60
axes ax at 480,270 width=500 height=330 xRange=0,5 yRange=0,6 stroke="#94a3b8" strokeWidth=3
dataRiemannRects bars axes=ax fn=4*t-t*t range=0.3,0.6 dx=0.03 fill="#0000FF" fillOpacity=0.5
gaussianSurface

Generate a projected checkerboard Gaussian surface mesh.

scene width=960 height=540 fps=60
gaussianSurface surface at 480,270 range=-2,2 resolution=12 scale=2 sigma=0.4 fillA="#FF862F" fillB="#58C4DD" stroke="#83C167" fillOpacity=0.5
sphereSurface

Generate a projected checkerboard sphere surface mesh.

scene width=640 height=360 fps=60
sphereSurface sphere at 320,180 radius=104 resolution=15,32 fillA="#E65A4C" fillB="#CF5044" light=0,-0.35,1
circle rim r=104 at 320,180 fill="none" stroke="#4D0E0F" strokeWidth=2
threeDAxes

Generate projected ThreeDAxes lines, ticks, and tips.

scene width=640 height=360 fps=60
threeDAxes axes at 320,190 xRange=-6,6,1 yRange=-5,5,1 zRange=-4,4,1 includeTips=true stroke="#ffffff"
projectedCircle

Generate an XY-plane circle as a projected cubic path.

scene width=640 height=360 fps=60
projectedCircle circle at 320,180 radius=1 xBasis=-56.75,25.5 yBasis=87.75,13.25 fill="none" stroke="#ffffff" strokeWidth=4
arrow

Generate an arrow with a shaft and tip.

scene width=640 height=360 fps=60
arrow vec x1=120 y1=220 x2=500 y2=120 stroke="#22d3ee" fill="#22d3ee" strokeWidth=8 tipLength=32 tipWidth=30
rotatingLine

Generate a line by rotating a reference segment around a point.

scene width=640 height=360 fps=60
value theta = 0
line base x1=200 y1=180 x2=440 y2=180 stroke="#64748b" strokeWidth=4
rotatingLine arm x1=200 y1=180 x2=440 y2=180 about=200,180 angle=-theta stroke="#f59e0b" strokeWidth=6
animate theta from 0 to 2.4 duration=1.5s easing=easeInOut
rotateUpdater

Expand a dt-based rotation updater into cumulative rotation animation.

scene width=640 height=360 fps=60
line arm x1=320 y1=180 x2=140 y2=180 stroke="#FFFF00" strokeWidth=8
rotateUpdater arm rate=1 duration=2s
rotateUpdater arm rate=-1 duration=2s
angle

Generate an angle arc that follows a value tracker.

scene width=640 height=360 fps=60
value theta = 0
angle arc radius=72 from=0 to=theta samples=72 at 320,180 stroke="#f59e0b" strokeWidth=6
animate theta from 0 to 2.4 duration=1.5s easing=easeInOut
tracedPath

Generate a parametric motion trace as a path.

scene width=640 height=360 fps=60
value theta = 0
tracedPath trace x=96*cos(t) y=96*sin(t) from=0 to=theta samples=96 at 320,180 stroke="#22d3ee" strokeWidth=5
circle dot r=16 at 416,180 fill="#38bdf8"
set dot.x to expr="320 + 96 * cos(theta)"
set dot.y to expr="180 + 96 * sin(theta)"
animate theta from 0 to 6.283 duration=2s easing=linear
arrange

Auto-layout group children with equal spacing.

scene width=640 height=360 fps=60
circle d1 r=22 at 0,0 fill="#38bdf8"
circle d2 r=22 at 0,0 fill="#f97316"
circle d3 r=22 at 0,0 fill="#22c55e"
group dots d1 d2 d3
arrange dots direction=horizontal gap=40
set dots.x to 320
set dots.y to 180
nextTo

Position a node relative to another node.

scene width=640 height=360 fps=60
circle dot r=28 at 280,180 fill="#38bdf8"
text label "nextTo" at 0,0 size=30 fill="#e2e8f0"
nextTo label dot direction=right buff=24
cameraFrame

Set the initial camera frame position and zoom.

scene width=640 height=360 fps=60
cameraFrame at 0,0 scale=1
circle dot r=42 at 0,0 fill="#38bdf8"
at

Start an indented block at a fixed time.

scene width=640 height=360 fps=60
circle early r=36 at 240,180 fill="#38bdf8"
circle late r=36 at 400,180 fill="#f97316" opacity=0
at 1s:
  set late.opacity to 1
show / hide

Create or delete a node on the timeline.

scene width=640 height=360 fps=60
circle blink r=54 at 320,180 fill="#22c55e"
at 0s:
  show blink
at 1s:
  hide blink
value

Declare a scalar tracker for expressions and animation.

scene width=640 height=360 fps=60
value theta = 0
circle dot r=36 at 320,180 fill="#38bdf8"
animate theta from 0 to 6.28 duration=2s easing=linear
set dot.x to expr="320 + 100 * cos(theta)"
set

Apply an immediate value to a property.

scene width=640 height=360 fps=60
circle dot r=54 at 320,180 fill="#38bdf8"
at 1s:
  set dot.fill to "#22c55e"
animate

Interpolate a property with from / to / duration.

scene width=640 height=360 fps=60
circle dot r=42 at 160,180 fill="#38bdf8"
animate dot.x from 160 to 480 duration=1.5s easing=easeInOut
animateFrame

Move and zoom the camera frame.

scene width=640 height=360 fps=60
cameraFrame at 0,0 scale=1
circle dot r=42 at 120,40 fill="#38bdf8"
animateFrame to 120,40 scale=1.4 duration=1s easing=easeInOut
followCamera

Keep the camera target attached to a moving node.

scene width=640 height=360 fps=60
camera mode=target target=0,0 scale=1
circle dot r=30 at -180,0 fill="#ff862f"
line path x1=-180 y1=0 x2=180 y2=0 stroke="#94a3b8"
animate dot.x from -180 to 180 start=1s duration=2s easing=linear
followCamera dot start=1s duration=2s
animate camera.scale from 1 to 1.5 start=1s duration=0.8s easing=easeInOut
play

Run primitives such as FadeIn and Transform.

scene width=640 height=360 fps=60
circle dot r=42 at 180,180 fill="#38bdf8"
rect target w=110 h=90 at 460,180 fill="#f97316"
at 0s:
  hide target
play FadeIn(dot) duration=0.7s
play Transform(dot, target) duration=1s easing=easeOut
wait

Advance the current time cursor before the next animation.

scene width=640 height=360 fps=60
circle dot r=42 at 160,180 fill="#38bdf8"
play FadeIn(dot) duration=0.7s
wait 0.8s
animate dot.x from 160 to 480 duration=1s easing=easeInOut
Inline preview Choose a command sample to run.
scene width=1280 height=720 fps=60
camera at 0,0 scale=1

value theta = 0
value pulse = 0

rect backdrop w=1280 h=720 at 640,360 fill="#020617"
path orbit d="M -170 0 C -170 -94 -94 -170 0 -170 C 94 -170 170 -94 170 0 C 170 94 94 170 0 170 C -94 170 -170 94 -170 0" at 640,390 fill="none" stroke="#1e3a8a" strokeWidth=5 opacity=0.5
line axis x1=-460 y1=0 x2=460 y2=0 at 640,390 stroke="#475569" strokeWidth=2 opacity=0.65
text title "Fluxion command demo" at 640,92 size=42 fill="#e2e8f0"
text subtitle "Text DSL → scene graph → timeline playback" at 640,146 size=23 fill="#94a3b8"
math equation "x^2+y^2=r^2" at 640,222 size=38 fill="#bae6fd" renderer=katex expandTokens=true
math equation2 "x^2+y^2=R^2" at 640,222 size=38 fill="#fef3c7" renderer=katex expandTokens=true
circle dot r=34 at 470,390 fill="#38bdf8" stroke="#0f172a" strokeWidth=5
circle halo r=56 at 470,390 fill="#38bdf8" stroke="#7dd3fc" strokeWidth=2 opacity=0.18
rect card w=230 h=112 at 1000,390 fill="#f97316" stroke="#fed7aa" strokeWidth=4 opacity=0.9
text cardLabel "morph target" at 1000,390 size=26 fill="#111827"
path spark d="M 0 -52 L 14 -14 L 52 0 L 14 14 L 0 52 L -14 14 L -52 0 L -14 -14 Z" at 640,510 fill="#facc15" stroke="#fef08a" strokeWidth=3
text caption "Values, expressions, camera moves, groups, and math-token transforms in one scene." at 640,646 size=22 fill="#cbd5e1"

group cardGroup card cardLabel
group hero title subtitle equation
group heroNext title subtitle equation2

at 0s:
  show backdrop
  show axis
  play AnimationGroup(FadeIn(orbit), Write(hero), FadeIn(dot), FadeIn(halo), lagRatio=0.18) duration=1.6s easing=easeOut

wait 0.2s
animate theta from 0 to 6.283 duration=2.8s easing=linear
animate pulse from 0 to 6.283 duration=2.8s easing=linear
set dot.x to expr="640 + 170 * cos(theta)"
set dot.y to expr="390 + 170 * sin(theta)"
set halo.x to expr="640 + 170 * cos(theta)"
set halo.y to expr="390 + 170 * sin(theta)"
set halo.scale to expr="1.0 + 0.22 * sin(pulse)"
animate camera.x from 0 to -28 duration=2.8s easing=easeInOut
animate camera.y from 0 to 18 duration=2.8s easing=easeInOut

wait 0.2s
play TransformMatchingTex(equation, equation2) duration=1.2s easing=easeInOut
play FadeIn(cardGroup) duration=0.6s easing=easeOut
play Transform(dot, card) duration=1.25s easing=easeInOut
animate halo.opacity from 0.18 to 0 start=5.8s duration=0.8s easing=easeOut

at 6.2s:
  play FadeIn(spark) duration=0.4s easing=easeOut
  animate spark.rotation from 0 to 180 duration=1s easing=linear
  animate spark.scale from 0.8 to 1.45 duration=1s easing=easeOut
  animate spark.opacity from 1 to 0.35 start=6.6s duration=0.6s easing=easeOut
  play FadeIn(caption) duration=0.8s easing=easeOut

What the demo shows

  1. scene and node declarations define the viewport, labels, equation, and shapes.
  2. The at block pins the starting time, then runs show and play in sequence.
  3. set and animate change the circle color and x position before Transform morphs it toward the rectangle.

Try the demo in Playground / Read the full Text DSL reference

Pipeline: Python DSL / Text DSL Scene Graph IR Timeline IR Browser SVG Runtime

Python and Text DSL

Generate the same Fluxion IR from a Manim-like API and a compact Mermaid/PlantUML-like declarative syntax.

Safe browser compiler

The Text DSL compiles to `.fluxion.json` in the browser without running arbitrary Python code.

SVG Runtime

Preview animations in a runtime that applies timeline operations deterministically and supports play, seek, scrub, and reset.

Next step

Try Text DSL in your browser first.

Edit DSL without installing anything, then inspect the generated Scene Graph / Timeline IR and SVG preview.