Kynetic Editor: Instructions

Created by Hamd Waseem • hamdivazim/Kynetic

← Back to editor

Self-hosting the editor website

The editor is a standard Next.js (App Router, client-heavy) application in editor/kynetic-editor. It stores projects in your browser and talks only to your own AWS API. There is no backend to deploy beyond the CDK stack below.

Requirements

Node.js 20 or newer and npm.

Run locally

cd editor/kynetic-editor
npm install
npm run dev        # development server on http://localhost:3000

Build for production

npm run build
npm start          # serves the production build on port 3000

Deploy anywhere Node runs

The production build is self-contained. Run npm run build && npm start behind any reverse proxy, or deploy to a Node host such as a VPS, Railway, Render, Fly.io, or Vercel (import the repo and set the root directory to editor/kynetic-editor). No environment variables are required; the AWS API URL and API key are entered in the editor's AWS setup popup and stored in the browser's localStorage only.

Projects: nodes & transitions

A project is a JSON file (matching renderer/renderer/schema.py) with three parts: a scene (width, height, background color), definitions (the nodes), and a timeline (the transitions that animate them). The exported JSON is what the Docker renderer consumes.

Coordinates

The editor works in the renderer's world coordinates: the default 1920×1080 scene maps the world rectangle (0..1778, 0..1000) onto the video frame with a small margin, so the numbers you see in the inspector are exactly the numbers written to the JSON. Text/math nodes are positioned at their top-left, rectangle/square at their top-left corner, and circle/ellipse/ngon/glow-dot at their center.

Node types

NodeKey fieldsInfo
mathtex_expression, font_size, font_nameLaTeX expression, e.g. $x^2$
texttext, font_sizePlain text
squareside_lengthposition = top-left
rectanglewidth, heightposition = top-left
rounded_square / rounded_rectangleside_length / width+height, border_radiuscorner radius as a fraction of the short side
lineend_pointposition = start point
polygon / curve / curved_arrow / arrowpoints / start_point+end_point, arrow head stylearrows support ->, <-, <-> heads
ellipsecenter, width, height
circle / glow_dot / ngoncenter, radius / +nglow_dot renders as a glowing dot
svgsrc, scale_x, scale_ysrc is s3://key.svg (uploaded) or a path relative to the JSON
groupchildren_idschildren are defined before the group; the group's transition animates them together
eraserobjects_to_erasewhitens over previously defined nodes

Styles

Every node can carry a stroke_style (color, width), an optional fill_style (hachured fill), an optional sketch_style (roughness/bowing/stroke multiplier) and a glow_dot_hint (a glowing dot that follows the pen while the node is drawn).

Transitions

TransitionWhat it doesBest use cases
sketchDraws the node on stroke-by-stroke (entrance)Shapes, text, math, SVGs
fade_inFades the node in (entrance)Labels and dots
fade_outFades the node out (exit)Removing things
zoom_outShrinks the node to nothing (exit)Animated exits
translate_toMoves the node's center to the destination point; "stay at destination" keeps it thereRearranging the scene

Timeline rules

The renderer only shows a node once it has an entrance transition ( sketch or fade_in). The editor adds a default entrance whenever you create a node and fills in any missing ones on export, so nothing disappears. Transitions are exported sorted by start time; the video length is the end of the last transition plus one second (five seconds for a scene with no transitions). Each transition has a target node, a start time and a duration.

Preview, import and export

Preview plays the timeline in the browser using the same semantics as the renderer (entrance/exit visibility, translate-to-center, eraser whitening). Export JSON downloads the renderer-ready project; Import loads any project JSON back into the editor.

AWS setup with CDK (your own S3 bucket)

The AWS stack is optional: it gives you a private S3 bucket for SVG assets plus an API-Gateway/Lambda API that hands out presigned URLs. Everything runs in your own AWS account (BYOC); the editor stores the API URL and key only in your browser.

Deploy

# prerequisites: AWS CLI configured (aws configure), Node.js, Python 3.11+
npm install -g aws-cdk

cd editor/cdk
python -m venv .venv
# Windows: .venv\Scripts\activate    macOS/Linux: source .venv/bin/activate
pip install -r requirements.txt

cdk bootstrap     # once per account/region
cdk deploy

Full step-by-step detail (credentials, console navigation) is in editor/cdk/README.md. After deploying, note the API's invoke URL (API Gateway console → Kynetic-PresignedURL-API → Stages → prod) and the API key value (API Keys → ClientApiKey → Show).

Configure the editor

Open AWS setup in the editor header, paste the API URL (with or without the /prod stage - both work) and the API key, then use Test connection. SVG nodes can then upload to your bucket; the exported JSON references them as s3://filename.svg and the renderer fetches them at render time.

API routes

RouteConsumerUse
/get-url-frontend, /put-url-frontendThis editorGet presigned URLs to upload/fetch remote SVGs from S3 from within the editor
/get-url, /put-urlThe local rendererUse by renderer to fetch SVGs from S3

All routes require the X-Api-Key header and are throttled by the usage plan; uploads and downloads go directly between the browser/renderer and S3 via short-lived presigned URLs.

Rendering with Docker

The renderer lives in renderer/ and is distributed as a Docker image (see renderer/README.md for the full guide). Export your project from the editor, then:

docker pull hamdivazim/kynetic-renderer:latest

# project without remote assets
docker run --rm \
  -v "$(pwd)/<project_dir>:/input" -v "$(pwd)/<output_dir>:/output" \
  hamdivazim/kynetic-renderer:latest /input/<project_file>.json

# project using s3:// SVGs, pass your CDK API URL and key
docker run --rm \
  -e KYNETIC_API_URL="https://your-api-id.execute-api.region.amazonaws.com" \
  -e KYNETIC_API_KEY="your-api-key" \
  -v "$(pwd)/<project_dir>:/input" -v "$(pwd)/<output_dir>:/output" \
  hamdivazim/kynetic-renderer:latest /input/<project_file>.json

KYNETIC_API_URL may be the bare API URL or the one ending in /prod; if the variables are omitted the container prompts for them. The video is written to the output directory next to the project file.

Keyboard shortcuts

ShortcutAction
Ctrl/⌘ + ZUndo
Ctrl/⌘ + Shift + Z or Ctrl/⌘ + YRedo
Ctrl/⌘ + DDuplicate the selected node(s)
Ctrl/⌘ + SExport JSON
Delete / BackspaceDelete the selected node(s)
EscapeDeselect (or leave the focused field)
Shift + clickAdd/remove a node from the selection; drag moves the whole selection
Mouse wheelZoom in/out around the cursor
Drag the canvas backgroundPan the view
0 or HomeRecenter to the original view
+ / −Zoom in/out around the view center

Troubleshooting

SVG upload or preview fails with 403 / "Failed to fetch"

That is a CORS or authentication failure against your API. Check the API URL and key in AWS setup, make sure the key is the current ClientApiKey value (redeploying creates a new one), and redeploy the stack if it predates the current cdk_stack.py — the gateway now returns readable errors instead of opaque fetch failures. The editor uses the get-url-frontend / put-url-frontend routes.

The renderer cannot fetch an s3:// SVG

Confirm the file was uploaded (its name must match the src in the JSON exactly), and pass the same API URL/key via KYNETIC_API_URL / KYNETIC_API_KEY. The renderer uses the legacy get-url route; both URL forms (with and without /prod) are supported.

A node is missing from the rendered video

The renderer only shows nodes with an entrance transition. The editor guarantees one per node on export. If you hand-edit JSON, give every node at least one sketch or fade_in event.