Jabbertoon for developers
The question Jabbertoon answers for developers is: how do I turn a script into an animated, talking cartoon in code? This page is the part of that answer that works today. From code, or from an AI assistant, you can:
- list Jabbertoon's moves, characters and looks;
- get any move's program, and the same program as readable text;
- check a move, a character or a cartoon, with errors that say where the problem is and what is wrong;
- write a link that opens a move in the block editor, where it plays, or a character in the studio or the character creator.
It takes about five minutes, and none of it needs a key, an account or a payment. The two steps that finish the answer are in section 4.
1. Write a link that opens a move
The simplest way to use Jabbertoon from code, or from an AI assistant, is to write a link. The move travels inside the link after the # sign, so you need no server and no API call:
Write a program. This one is a whole move: one script that bobs the body 8 pixels and swings the head 6 degrees.
{ "v": 1, "kind": "behaviour", "name": "nod and bob", "scripts": [ { "body": [ { "op": "bob", "amp": 8, "every": 1 }, { "op": "swingPart", "part": "head", "deg": 6, "every": 1.5 } ] } ] }Turn it into canonical JSON: keys sorted at every level, no spaces. This is the exact text the code is made from.
{"kind":"behaviour","name":"nod and bob","scripts":[{"body":[{"amp":8,"every":1,"op":"bob"},{"deg":6,"every":1.5,"op":"swingPart","part":"head"}]}],"v":1}Encode that text as UTF-8, then base64url without padding (the + and / of base64 become - and _, and the = at the end is dropped). That is the share code.
eyJraW5kIjoiYmVoYXZpb3VyIiwibmFtZSI6Im5vZCBhbmQgYm9iIiwic2NyaXB0cyI6W3siYm9keSI6W3siYW1wIjo4LCJldmVyeSI6MSwib3AiOiJib2IifSx7ImRlZyI6NiwiZXZlcnkiOjEuNSwib3AiOiJzd2luZ1BhcnQiLCJwYXJ0IjoiaGVhZCJ9XX1dLCJ2IjoxfQPut the code after #c= in a link to the block editor. Opening the link shows the move as blocks and plays it on a character; nothing is sent to a server, because the browser never sends the part after the #.
The same code opens in the studio too (https://jabbertoon.com/studio/#c= and the code), where the move goes into the person's own moves and plays in their cartoon. A character travels the same way, as the code of {"type": "character", "name": ..., "content": ...}: it opens in the studio or the character creator (/create/#c=). A ready-made character needs no code at all: https://jabbertoon.com/studio/#ch=dog puts the dog in the studio. The link formats are listed in the link reference, and the program format in the block language reference.
2. Call the free tools
The same tools that AI assistants use are plain HTTP endpoints at https://jabbertoon.com/api/<tool>, described by an OpenAPI document: list_moves, list_characters and list_looks list what Jabbertoon ships; get_move gives a move's program and its readable text; validate checks a move, a character or a cartoon; and share_link turns a move or a character into a link. They are free and keyless, and all of them but report_problem only read. Each example below checks a move and gets the link that opens it, against the live site, https://jabbertoon.com, and needs no key, no account and nothing to install beyond curl, Python or Node. (The variable at the top of each file can send it to another address; we use it to test our own server before a release, and you can leave it unset.)
curl
#!/bin/sh
# Jabbertoon quickstart (curl): check a move, then get the jabbertoon.com link that opens it.
# No key, no account. For a local server: JABBERTOON_BASE=http://127.0.0.1:8790 sh quickstart.sh
BASE="${JABBERTOON_BASE:-https://jabbertoon.com}"
# A move: bob up and down and swing both arms (the language: https://jabbertoon.com/docs/language/)
PROGRAM='{"v": 1, "kind": "behaviour", "name": "Happy bob",
"scripts": [{"body": [{"op": "bob", "amp": 12}, {"op": "swingPart", "part": "arms", "deg": 30}]}]}'
# 1. validate: "ok": true, or each error and warning as {code, where, says, fix}
curl -sS -X POST "$BASE/api/validate" -H 'Content-Type: application/json' -d "{\"program\": $PROGRAM}"
echo
# 2. share_link: "link" opens the move in the block editor, where it plays. The move travels in the
# link after the #, so nothing is uploaded or stored.
curl -sS -X POST "$BASE/api/share_link" -H 'Content-Type: application/json' -d "{\"program\": $PROGRAM}"
echoSave it as quickstart.sh, then run it: sh quickstart.sh.
Python
"""Jabbertoon quickstart (Python 3, standard library only): check a move, then get the link that opens it.
No key, no account. For a local server: JABBERTOON_BASE=http://127.0.0.1:8790 python quickstart.py"""
import json, os, sys, urllib.error, urllib.request # noqa: E401
BASE = os.environ.get('JABBERTOON_BASE', 'https://jabbertoon.com')
PROGRAM = {'v': 1, 'kind': 'behaviour', 'name': 'Happy bob', # a move: bob and swing both arms (/docs/language/)
'scripts': [{'body': [{'op': 'bob', 'amp': 12}, {'op': 'swingPart', 'part': 'arms', 'deg': 30}]}]}
def call(tool, args):
req = urllib.request.Request(f'{BASE}/api/{tool}', data=json.dumps(args).encode('utf-8'),
headers={'Content-Type': 'application/json'})
try:
text = urllib.request.urlopen(req, timeout=20).read()
except urllib.error.HTTPError as e: # a refusal is JSON too (busy, timeout, too_large ...)
text = e.read()
if not text.lstrip().startswith(b'{'): # not the Jabbertoon API at all (a web page, a proxy's error page)
sys.exit(f'{tool}: the answer from {BASE} is not JSON: is that the Jabbertoon API?')
answer = json.loads(text)
if 'error' in answer:
sys.exit(f"{tool}: {answer['error']['code']}: {answer['error']['says']} (fix: {answer['error']['fix']})")
return answer
check = call('validate', {'program': PROGRAM}) # 1. ok, or {code, where, says, fix} for each problem
for p in check['errors'] + check['warnings']:
print(f"{p['code']} at {p['where']}: {p['says']} (fix: {p['fix']})")
if check['ok']:
print('Open it:', call('share_link', {'program': PROGRAM})['link']) # 2. the link carries the move after the #Save it as quickstart.py, then run it: python3 quickstart.py.
JavaScript (Node 18 or later)
// Jabbertoon quickstart (JavaScript: Node 18+ or a browser): check a move, then get the link that opens it.
// No key, no account. For a local server: JABBERTOON_BASE=http://127.0.0.1:8790 node quickstart.mjs
const BASE = (globalThis.process && process.env.JABBERTOON_BASE) || 'https://jabbertoon.com';
// A move: bob up and down and swing both arms (the language: https://jabbertoon.com/docs/language/)
const program = {
v: 1, kind: 'behaviour', name: 'Happy bob',
scripts: [{ body: [{ op: 'bob', amp: 12 }, { op: 'swingPart', part: 'arms', deg: 30 }] }],
};
async function call(tool, args) {
const r = await fetch(`${BASE}/api/${tool}`, {
method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(args),
});
let answer; // every answer is JSON, a refusal too (busy, timeout, too_large ...)
try { answer = JSON.parse(await r.text()); } catch (e) { throw new Error(`${tool}: the answer from ${BASE} is not JSON (HTTP ${r.status}): is that the Jabbertoon API?`); }
if (answer.error) throw new Error(`${tool}: ${answer.error.code}: ${answer.error.says} (fix: ${answer.error.fix})`);
return answer;
}
const check = await call('validate', { program }); // 1. ok, or {code, where, says, fix} for each problem
for (const p of [...check.errors, ...check.warnings]) console.log(`${p.code} at ${p.where}: ${p.says} (fix: ${p.fix})`);
if (check.ok) {
const made = await call('share_link', { program }); // 2. the link travels with the move after the #
console.log('Open it:', made.link);
}Save it as quickstart.mjs, then run it: node quickstart.mjs.
The tools, their arguments and an example of each are listed on the page for AI assistants.
3. Check your files against the schemas
Programs, packs and cartoons have JSON Schemas at their public URLs, so your editor or your tests can check a file before Jabbertoon sees it. The pack format explains what each file holds.
4. What comes next
Two things finish the answer to the question above, and both are coming in the next release: links that play a whole cartoon, with its scenes, lines and voices, and turning a script into a video in code, with a command-line renderer and library that run on your own machine, free and with no key. Neither is published yet, so there is nothing to install or run for them today; this page will say when there is. Until then, validate already checks a whole cartoon, share_link answers a scene or a cartoon with the code not_yet instead of a link, and a cartoon is made, played and saved as a video in the studio.
The source
Jabbertoon's code is licensed under the Apache License 2.0, and the part of it that runs in your browser is served as it was written, not minified, so you can read it, save it and reuse it under that licence. The engine starts at /engine/index.js, which imports the rest of it; the code that draws the characters and runs the block editor is under /ui/. Every file:
engine/curves.jsengine/desugar.jsengine/director.jsengine/expr.jsengine/index.jsengine/packs.jsengine/parts.jsengine/runtime.jsengine/text.jsengine/validate.jsui/blocks/catalog.jsui/blocks/convert.jsui/blocks/define.jsui/blocks/reaches.jsui/blocks/review.jsui/blocks/words.jsui/character_pack.jsui/creator/model.jsui/creator/parts.jsui/creator/view.jsui/shapes.jsui/store.js
The code of the tools for AI assistants runs on our server and is not served; the OpenAPI document and the page for AI assistants describe exactly what each tool takes and gives back.
Data rights
- Jabbertoon's code is licensed under the Apache License 2.0; the browser part is listed under The source.
- Every pack Jabbertoon ships, every move, character and scene, is CC0: use it for anything, no credit needed.
- The few third-party pieces the studio loads, and their licences, are listed on the licences page.
- We keep nothing a user makes: the studio sends nothing anywhere, and the tools read what they are sent and forget it. The one exception is report_problem, which keeps the report it is sent for us to read (the privacy notice says what a report holds).