Shipping now

Build interactive e-learning. Publish to every format an LMS accepts.

Amarna Studio is an authoring tool for interactive e-learning. Describe the course and get a validated draft back, lay it out on a responsive canvas, branch it into scenarios, stage it as animated scenes, score its interactions, check it against WCAG — then publish a self-contained package that runs in any LMS.

Runs in the browser or as a desktop app. The AI layer works with no API key at all — and with your own key on any of eight providers if you have one.

11Publish targets, from one project
17Scored interaction types
13Element types on the canvas
9Scenario-graph node types
9Gates every AI draft passes
512Paths simulated per course

Why it exists

Immersive training is stuck between slideware and custom builds.

Slide-based tools are fast and cheap and produce click-next courses that don't change behavior. Bespoke simulations change behavior and cost a project plan and a development team. Generic AI content tools are fast and shallow — video and prose, not interactivity, and no assessment worth the name.

Amarna Studio is built for the people who outgrew the first option and can't justify the second: instructional designers who need branching, variables and scored interactions, and the engineers who have to make the output actually pass an LMS conformance check.

What it does

Seven things, and the seams between them are the product.

01 · Compose

Describe it, get a validated draft

Compose writes a Course Spec — objectives, screens, decisions and assessments — runs it through nine gates, repairs what fails, and only then compiles a real project. One run is one undoable change.

02 · Author

Canvas, layers, timeline

Pages → sections → layout containers, with 13 element types, rich text, per-breakpoint responsive overrides and a keyframe timeline. Undo and redo are backed by document patches, not screenshots of state.

03 · Branch

A scenario graph, not a slide order

A node-graph editor with 9 node types: choice points, dialogue, condition gates, variable setters, random gates, merges and endings. Variables drive the path; characters and dialogue drive the story.

04 · Assess

17 interaction types out of the box

Multiple choice through drag-and-drop, hotspot, matching, ordering, sorting and media annotation — plus a custom escape hatch. Each is independently scorable and weighted, and each reports to the LMS as a real interaction.

05 · Animate

A screen, or a scene that plays

Any node can render as a real-time animated scene on a GPU canvas instead of text on a page — cast members with bodies that move, a procedural backdrop, a camera that frames the beat, lip sync. Same document, same assessment graph, same LMS tracking.

06 · Check

Accessibility while you author

A built-in WCAG validator, contrast checker, tab-order manager and caption editor, so problems surface before review rather than after. A rule-driven Learning Design Score grades the project across eight instructional-design categories.

07 · Publish

One project, eleven targets

HTML5, SCORM 1.2, SCORM 2004 (3rd and 4th Edition), xAPI, cmi5, AICC, MP4/WebM/MOV renders, and a hosted review build. Every format's runtime exposes the same four tracking calls, so the course never branches on where it landed.

Also · Share

Send a course as a link

Publish to a public URL and anyone holding the link can open the course — no account, no LMS, no download. The link survives a re-publish and dies on a revoke.

Also · Review

Comments on the running course

Review builds are hosted behind an email gate with an in-place comment overlay and live threads. Stakeholders comment on the course as it runs, not on a screenshot of it.

Also · Extend

Plugins in a real sandbox

Plugins run in a Web Worker with a startup timeout and a message-type allowlist, governed by a three-level permission model that decides network access and the termination deadline.

The AI layer

The model doesn't write the course file. It writes the thing above it.

A single default text element serialises to 56 required values, 37 of them geometry and presentation. Handing a model that document means asking it to author coordinates. So Compose inserts a tier above it: the model writes a small, ID-keyed Course Spec — objectives, screens, decisions, choices, feedback and assessment data — and a deterministic compiler turns that into a real project through the same factory functions the canvas uses. Geometry stops being a generation problem.

L1
SchemaBlocking
Structural validity. Every field rebuilt and narrowed field-by-field, so anything the model invented is dropped rather than carried.
L2
LintBlocking
Semantics: reachability, dead ends, objective coverage, and decisions whose options fail to discriminate between them.
L3
SimulationBlocking
An exhaustive walk of every path a learner can take, up to 512. A truncated walk is reported as an issue rather than passed as a partial success.
L4
ObjectivesBlocking
Every stated learning objective is actually assessed somewhere in the course, and every assessment maps back to one.
WCAGEvidence
Accessibility findings against the draft, reported on the receipt.
AssetsEvidence
Which requested images and portraits exist and which are still outstanding.
GroundingEvidence
Citations checked against the source material you attached. A citation that resolves to nothing is reported as fabricated.
ReviewEvidence
A second model critiques the teaching across five lenses — decision quality, feedback, objectives, realism, clarity — because a course can pass every check above and still teach nothing.
MotionEvidence
For animated scenes: what share of the motion renders something — a state change, a cause, a consequence, a reaction — rather than decorating the screen. Decorative animation measurably hurts recall, so this is reported rather than assumed.
The four blocking gates block on errors, not warnings, and a draft that fails goes back through a repair loop rather than reaching your project. Findings that name a screen the document doesn't have are discarded and counted — a confabulating model shows up on the receipt instead of quietly filing bug reports against screens that don't exist.
Bring your own model — or none

Eight providers, plus anything OpenAI-compatible

  • Metered: Anthropic.
  • Free tiers: Google AI Studio, Groq, OpenRouter, Cerebras, Mistral, Ollama Cloud.
  • Local: Ollama — nothing leaves the machine.
  • Custom: any OpenAI-compatible endpoint you point it at.
  • No key at all: the built-in keyless provider produces a genuine brief-derived draft, so the whole loop is exercisable before you spend anything.
The run does not hide what it is doing

Receipts, not a spinner

  • Provider, model and endpoint are named on the run before the first call — and a fallback says, in a sentence, why it fell back.
  • Every outbound call is a row: URL, attempt, prompt size, status, latency, bytes, finish reason. Keys travel in a header and never reach that stream.
  • Raw model output streams on three channels — reasoning, prose, and the document being written.
  • Gate receipts record what passed, what failed and the evidence for each, and survive a reload: runs are journalled and replayable.
Retrieval

It writes from your source material

Attach policies, transcripts, SME documents (DOCX, PPTX, HTML, CSV, JSON, TXT, Markdown) and Compose retrieves from a per-project corpus rather than pasting a blob into the prompt. Retrieval is lexical — BM25 with rank fusion — so it needs no key, no network and no embedding bill. Every claim in the draft can be traced back to the passage it came from, and the grounding gate checks that it resolves.

PDF is not supported yet.

Five agents

Agent, Edit, Ask, Reviewer, Director

  • Agent — plans and executes multi-step work on a whole course.
  • Edit — ID-addressed patch operations against the document you have. A batch that would break it is rejected whole, never half-applied.
  • Ask — answers questions about the course without touching it.
  • Reviewer — audits the teaching and returns anchored findings, changing nothing.
  • Director — stages an existing course as animated scenes, and may emit staging operations only. Anything else it proposes is dropped and reported.

Every turn is one change, one history entry, one undo.

Animated scenes

The same course, played out instead of read.

A staged node renders as an animated scene on a GPU canvas rather than as text on a page: cast members with bodies that move, a procedural backdrop, a camera that frames the beat, effects. It is a presentation choice, not a second document — the same assessment graph, the same variables, the same LMS tracking. A course can stage one beat or all of them, and a project that stages nothing ships nothing extra.

The rule that makes Compose work applies here too: the model authors direction and a deterministic compiler owns geometry. A beat is ten fields — who, framed how, doing what, feeling what, saying what, and why the motion is there — and the compiler synthesises every bone transform, camera key, viseme cue and particle from that. The harness never emits shader or path data; effects are a catalog and the runtime owns the drawing. That is not a stylistic preference — on symbolic-graphics benchmarks a frontier model scores 84.8 and a 7B model scores 8.8, so a shader path would work on one paid provider and produce black canvases on every free tier.

You pick the house style. Ten looks — House, Vector, Paper Cutout, Prime Time, Classic TV, Heartland, Rubber Hose, Storybook, Newsprint and Noir — and each one is a whole construction, not a filter over the same drawing: how many heads tall the cast stands, how the eyes and mouth are built, whether the jaw hinges, whether limbs bend or pivot from a visible joint, how far a body squashes when it lands, and whether it is held on twos or on threes. Choose it on the brief or change it later; the whole production restages in one step you can undo.

Renders anywhere

Three backends, one frame producer

  • WebGPU → WebGL2 → Canvas2D, picked at runtime. Canvas2D is not a token gesture: a package opened straight off a disk cannot upload a texture from a file beside it, and Canvas2D draws it anyway.
  • The runtime is generated, not bundled — and it is written into a package only when that project actually stages a scene.
  • Characters are the same people as their drawn portraits: a 17-joint body under the same seeded face, so a cast member looks identical in the editor, the graph, the scene and the published course.
  • Lip sync is baked while authoring — text to phonemes to a 15-viseme set — so the package ships a lookup table instead of an audio model.
Safe and legible by construction

Nobody has to watch it frame by frame

  • Flash rate, cut rate, beat length, actor count and particle budget are clamped while compiling, below the WCAG 2.3.1 threshold — and the compiler reports what it clamped. A compiler that cannot emit an unsafe scene needs no check that can fail.
  • Reduced motion is a second compiled stream, not a media query — a query has nothing to act on when the motion is a camera transform inside a canvas — plus an in-content pause control.
  • The accessibility mirror is an output of the compiler. There is no accessibility tree inside a canvas, so a description per beat is generated from the scene graph and written as real markup inside the canvas element. It is the screen-reader narration, the canvas fallback and the answer to "what does a learner with no GPU get" — all the same text.
The claim is not that the animated version teaches better. Animation beats static pictures only when it represents something, and decorative motion measures as actively harmful to recall across the literature. So every beat has to name what its motion renders — a state change, a cause, a consequence, a reaction, an attention cue — and a beat whose justification the model could not name is classed as ambient rather than promoted. The motion gate reports that ratio on the receipt and leaves the judgement to you.

Publishing

One project. Eleven targets. Tracking that actually reports.

Codegen produces the package; the host writes it. Every format's runtime exposes the same four functions — initialise, bookmark, report an interaction, finish — so nothing in the generated course branches on which LMS it landed in, and every bridge degrades to a no-LMS local mode, which is what makes a published package previewable outside one.

Published packages are self-contained: open the launch page and it runs.
Target What it's for Reports
HTML5 A standalone web course — host it anywhere, or open it from disk. Local progress and bookmark
SCORM 1.2 The format most LMSs still ask for first. Status, score, bookmark, interactions
SCORM 2004 (3rd Ed.) Sequencing-aware SCORM for platforms that require it. Status, score, bookmark, interactions
SCORM 2004 (4th Ed.) The current SCORM revision. Status, score, bookmark, interactions
xAPI (Tin Can) Statements to any LRS; endpoint comes from the launch URL. Statements, results, bookmark
cmi5 The xAPI profile modern LMSs launch against. Statements, results, bookmark
AICC HACP for the legacy systems that still run on it. Status, score, bookmark
MP4 · WebM · MOV A rendered video cut of the course, for channels that can't run one.
Review build Hosted behind an email gate with a live comment overlay. Reviewer comments and threads
Public share link A sandboxed copy at an unguessable URL — no account needed to open it.
Tracking is tested by running the published package, not by inspecting it: the suite serves each build over HTTP, loads it inside a fake LMS frame with the API where a real LMS puts it — on an ancestor frame, not the content window — and asserts on what the course reports back. The xAPI, cmi5 and AICC builds are driven against a real endpoint that records what arrives.

Specifications

The whole surface, in numbers.

Every figure below is a count of what is in the product today, not a roadmap. Where something is missing or advisory, it says so.

Authoring

Element types
13
Document model
Pages → sections → containers
Responsive
Per-breakpoint overrides
Rich text
TipTap
Animation
Keyframe timeline
Undo history
Patch-based

Scenarios

Node types
9
Path logic
Variables + conditions
Randomisation
Random gates
Characters
Cast with expressions
Portraits
Drawn, seeded, offline
Validation
Exhaustive path walk

Assessment

Interaction types
17 + custom
Scoring
Per-interaction, weighted
Feedback
Per choice
Objectives
Mapped and gate-checked
LMS reporting
Real interaction records

AI (Compose)

Providers
8 + custom
Works with no key
Yes
Agents
5
Gates
9 (4 blocking)
Paths simulated
up to 512
Retrieval
BM25, per project
Source formats
DOCX, PPTX, HTML, CSV, JSON, TXT, MD

Publishing

Targets
11
SCORM
1.2, 2004 3rd & 4th
xAPI / cmi5 / AICC
Yes
Video
MP4, WebM, MOV
Packages
Self-contained
Public share link
Sandboxed, revocable

Animated scenes

Render backends
WebGPU, WebGL2, Canvas2D
Authored per beat
10 fields, no shader code
Motion classes
8, declared per beat
Character rig
17 joints, seeded
Lip sync
15 visemes, baked
Flash / cut safety
Clamped at compile
Reduced motion
Second compiled stream
Screen readers
Per-beat text mirror

Accessibility

WCAG validator
Built in
Contrast checker
Built in
Tab order
Managed
Captions
Editor included
Design scoring
8 categories

Data & storage

Project format
Plain JSON
Desktop location
Your own disk
Document in the DB
Never — metadata only
Assets
Beside the project
Export
Project + corpus together

Security posture

API keys in the browser
Never
Key storage
Encrypted, host-side
Previews
Sandboxed, opaque origin
Shared courses
Sandboxed, no same-origin
Plugins
Worker + allowlist
Accounts
Sessions, roles, admin

Accounts & plans

Desktop sign-in
Not required
Web sign-in
Email, OAuth, passkeys
Roles
Admin and user
Plans
Free, Pro, Team
Metered
Compose runs only
Self-hosted
Nothing metered

Interface

Themes
27 (light, dark, system)
Appearance controls
13
Layouts
Phone, tablet, desktop
Command palette
⌘K
Browser Back
Works on every surface
Reduced motion
Follows the system
Two things this page will not overstate. Asset approval is advisory — it decides what the document points at, and nothing blocks a publish on it. And retrieval is lexical only: there is no semantic/embedding tier today, by choice, so nothing in the product needs an embeddings bill to work.

Where it runs

One backend, one interface, four ways to deploy it.

The desktop app, the browser, a container on your own infrastructure and a serverless deployment are the same backend and the same interface — not a cut-down web version of a desktop product. Where a host genuinely can't do something, the app hides the control rather than failing the call.

Host Best for Notes
Desktop Full capability — video export, native file handling, local model support. Windows, macOS, Linux. Projects on your own disk. No account required, and the browser build hands the installer over rather than pretending the gap isn't there.
Browser Nothing to install; open a link and author. Signed in, with roles and an admin surface. No video export — that needs the desktop build, and the app says so instead of offering a button that fails.
Container Self-hosting on your own infrastructure. One long-lived process and one volume. Full progress streaming, no execution ceiling. Refuses to start on a public address without a signing key.
Serverless Managed hosting with a database instead of a disk. Same app on Postgres. Function time limits apply and video export is unavailable; long runs stay visible because every run is journalled and replayable.
Your key never reaches the browser. The model harness runs host-side on every deployment, the key is encrypted at rest, and the page's own security policy forbids the browser from talking to a model provider at all — the same guarantee the desktop build makes, enforced the same way.
Only the hosted deployment charges, and only for Compose runs. The web build signs you in — email and password, optional single sign-on, optional passkeys — with an administrator role and an operator dashboard behind it, and offers Free, Pro and Team. The desktop app and a self-hosted install meter nothing and require no account at all; billing stays off entirely until an operator configures it, and the app reports plainly that nothing is metered rather than implying a limit it does not enforce.

Open it and compose something.

The keyless provider means you can run the whole loop — brief, generation, gates, receipts, a compiled course, a published package — before you decide anything.