Same renderer. Your framework.
Working integrations.
These are real framework mounts, not visual mockups. Each example uses the packaged adapter and the same compiled Amiri asset. Font license.
Core playback needs no animation library. Use a recipe when you already have a timeline to coordinate.
Frameworks
Play, scrub, replace the asset, or unmount and mount the component.
Animation recipes
One normalized playhead.
GSAP, Motion and Anime.js animate progress from 0 to 1. Each recipe is a separate, optional entry point.
// Native playback needs no extra engine:
controller.seek(0);
controller.play({ duration: 3000 }); // milliseconds
// Or import a recipe only when its engine is installed:
import { gsapInk } from 'arabic-ink/recipes/gsap';
const { animation, dispose } = gsapInk(controller, { duration: 3 });
// Recipe durations use seconds. Dispose before unmounting.Compile first
The smallest setup.
The source is local and publish-ready; the npm name is not published or reserved yet. In a local checkout:
bun install
bun run build
bun dist/compiler/cli.js --font ./font.ttf \
--text "نكتب بالعربية" --out ./public/hello
// In the browser:
import { loadInk, mountInk } from 'arabic-ink';
const asset = await loadInk('/hello.json');
const view = mountInk(document.querySelector('#hello'), asset);
// On teardown:
view.destroy();For large numbers of concurrent instances, share one createInkScene() instead of mounting hundreds of separate canvas components. Always retain readable fallback text.