inkmark Hand-drawn marks for any screen

Circle, underline and point at things on a page, an image or a chart. Play them step by step.

npm i @oblik/inkmark
GitHub

Install

Install the package.

npm i @oblik/inkmark

Or use a script tag. The global name is Inkmark.

<script src="inkmark.iife.js"></script>
<script>
  Inkmark.annotate('#total', 'circle').show()
</script>

Labels use the font Permanent Marker. Load it on your page, or set font.src in a style.

Quick start

inkmark draws in two ways. Pick the one that fits.

On your page

Marks on the real elements of your running page. They follow scroll and resize. You need no file.

annotate()

In a scene

Marks on a picture: a screenshot, a chart or an HTML file. Play them step by step, show them all at once, or export PNG and MP4.

createPlayer()

On your page

Give a selector and a mark type. Call show().

import { annotate, annotateGroup } from '@oblik/inkmark'

const tour = annotateGroup([
  annotate('#checkout-discount', 'highlight'),
  annotate('#checkout-code', { type: 'box', color: 'accent' }),
  annotate('#checkout-total', 'circle'),
  annotate('#checkout-pay', { type: 'arrow', from: 'bottom' }),
  annotate('#checkout', { type: 'label', text: 'Best value', side: 'top' }),
])

tour.show()

In a scene

A scene is one JSON file: a background and a list of steps. Each step has up to three marks. See the examples.

import { createPlayer } from '@oblik/inkmark'

const scene = await (await fetch('scene.json')).json()
createPlayer(document.querySelector('#box'), scene)

Examples

Each example is one scene file. Click the dots to go step by step. The scene JSON is under each one.

Mark types

A mark is one drawing: a circle, a line, an arrow or a note. Each box below is drawn live with the style panel.

There are nine types. Every mark also has id, with, duration, delay, color and seed. Marks on your page can use eight of them: all but scribble.

MarkUse it toKey options
circleLoop around a thingtarget pad loops
boxDraw a rectangletarget pad
underlineDraw a line below texttarget offset double
highlightAdd a marker bandtarget opacity
strikeCross out texttarget crossed
bracketFrame one or more sidestarget sides pad
arrowPoint at a thingfrom to bend head
labelWrite a short texttext at side maxWidth size
scribbleDraw a free linepoints thickness

A target says where a mark goes. Use one key: selector, anchor, box, point or mark. A selector or an anchor is exact. A box or a point is a guess. Details: Scene reference.

Styles

A style is a set of tokens: pen, colors, font, stroke and timing. Ten styles are built in. Each box uses your panel colors. Click a box to use that style on this page, or copy it.

Marks name color tokens such as ink, accent and highlight. They never use hex values. Make your own style from a built-in one:

createPlayer(el, scene, {
  styles: { brand: { extends: 'marker', colors: { ink: '#D6336C' } } },
})

Set "overlay": true on a scene or a step to dim the background and leave holes around the targets. Pass scheme: 'light' | 'dark' | 'auto' to follow light and dark. Details: Styles.

Export

Turn a scene into one PNG per step, an MP4 or one HTML file. The command line tool does it: node cli/index.ts <command>.

node cli/index.ts preview scene.json --out png
node cli/index.ts play scene.json --out player.html
node cli/index.ts render scene.json --out scene.mp4 --fps 30

The same tool also checks a scene and finds targets for you.

CommandOutput
previewOne PNG per step
renderAn MP4 (needs ffmpeg)
playOne self-contained HTML player
validateErrors and warnings for a scene
targetsSelectors or anchors you can point at
gridAn image copy with a labeled grid

Node 22.18 or newer is needed. A Chromium browser is needed for preview and render.

For AI agents

Copy a prompt. Paste it into any AI chat or coding agent.

Highlight things on my page

Use it to mark elements on a live page.

Make a step-by-step scene or video

Use it to get a scene JSON for a player, PNGs or an MP4.

Coding agents: add skill/SKILL.md to your project. Or read the Agent page. It has this whole doc as one Markdown file.

API

FunctionWhat it does
annotate(target, mark, options?)Makes one live mark. Returns an Annotation with show(), hide() and remove().
annotateGroup(list, options?)Shows many live marks one after the other. Options: overlay, gap.
createPlayer(el, scene, options?)Mounts a scene with step dots and a Play button.
mountScene(el, scene, options?)Mounts a paused scene with no controls.
validate(scene)Checks a scene.
resolveStyle(style)Resolves a style name or a partial style.

Player options: controls, autoplay, loop, keyboard, baseUrl, style, styles, scheme, overlay. A player has next(), back(), play(), pause(), current and onStep().

Docs: Live mode, Scenes, Styles, README.