With HTML
Animate DOM elements without a bundler. This tutorial uses ES modules and a CDN; the same APIs apply when you import @unseenco/backstage from npm.
Starter HTML
Create animation-tutorial.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Backstage tutorial</title>
<style>
body {
margin: 0;
color: white;
background: black;
font-family: sans-serif;
}
</style>
</head>
<body>
<h1 id="article-heading" style="text-align: center">Welcome</h1>
<script type="module">
// Add JavaScript here
</script>
</body>
</html>Add Studio (development)
Publish @unseenco/backstage/browser-bundles from this monorepo, or install the packages via a bundler. For a quick CDN-style setup, import core and studio from your host (version must match your published packages).
Example with npm and Vite is preferred for real projects:
import studio from '@unseenco/backstage/studio'
import {getProject, types} from '@unseenco/backstage'
studio.initialize()For a no-bundler experiment, load the browser bundle build of @unseenco/backstage/browser-bundles (see package dist/ after yarn cli build) the same way legacy docs used core-and-studio.js.
Project, sheet, object
const project = getProject('HTML Animation Tutorial')
const sheet = project.sheet('Sheet 1')
const obj = sheet.object('Heading 1', {
y: 0,
opacity: types.number(1, {range: [0, 1]}),
})Sync to the DOM
const heading = document.getElementById('article-heading')
obj.onValuesChange((values) => {
heading.style.transform = `translateY(${values.y}px)`
heading.style.opacity = String(values.opacity)
})Tweak y and opacity in the Details Panel to confirm the link works.
Sequence an animation
Right-click a prop in the Details Panel → Sequence, add keyframes on the timeline, then press Space to preview.
Production checklist
- Export state.json from the outline (project menu → export).
- Load state when creating the project:
const project = getProject('HTML Animation Tutorial', {state: projectState})- Remove Studio (
studio.initialize()and Studio imports). - Ship only
@unseenco/backstage(orcore-onlybrowser bundle). - Start playback after
project.ready:
project.ready.then(() => {
sheet.sequence.play({iterationCount: Infinity, range: [0, 6]})
})Next steps
- Projects — state,
ready, assets - Prop types