Blocks
The 15 blocks a course page is made of, and the keys each one takes.
A page's blocks hold what the page shows, from top to bottom. Each block has a "type", which sets its other keys. Every text a block shows is a text ID from the words file.
| Block | What it shows |
|---|---|
heading | A heading. |
text | A paragraph. |
list | A list. |
steps | Numbered steps, such as how to use a tool. |
callout | A note that stands out from the page. |
table | A table. |
quote | A quotation. |
image | A picture. |
audio | A sound. |
video | A video. |
film | A film Kapi draws and plays from its scenes, with captions, a transcript and questions that pause it. A package with a film says "sdk": "2.1". |
question | A practice question, with feedback after each answer. |
contact | A company contact. Where the company hasn't filled it in, the page shows common.contact-missing.<key>. |
sources | The titles of the documents the package was made from. |
divider | A line between parts of a page. |
heading
A heading.
type:"heading", required. The block's type.text: text ID, required. The text ID of the heading.
text
A paragraph.
type:"text", required. The block's type.text: text ID, required. The text ID of the paragraph.style:"body","lead","small". lead for an opening paragraph, small for a note, or body. Left out: body.
list
A list.
type:"list", required. The block's type.items: list of text IDs, required. The items, in order.ordered: true or false. true to number the items.
steps
Numbered steps, such as how to use a tool.
type:"steps", required. The block's type.items: list of text IDs, required. The steps, in order.
callout
A note that stands out from the page.
type:"callout", required. The block's type.tone:"note","important","warning", required. How strongly it stands out: note, important or warning.text: text ID, required. The text ID of the note.
table
A table.
type:"table", required. The block's type.header: list of text IDs. The column headings.rows: list of lists of text IDs, required. The rows.
quote
A quotation.
type:"quote", required. The block's type.text: text ID, required. The text ID of the quoted words.cite: text ID. The text ID of who or what it quotes.
image
A picture.
type:"image", required. The block's type.media: ID, required. The media ID of a picture in kapi-works.json.
audio
A sound.
type:"audio", required. The block's type.media: ID, required. The media ID of a sound in kapi-works.json.
video
A video.
type:"video", required. The block's type.media: ID, required. The media ID of a video in kapi-works.json.
film
A film Kapi draws and plays from its scenes, with captions, a transcript and questions that pause it. A package with a film says "sdk": "2.1".
type:"film", required. The block's type.scenes: list of film-scenes, required. The scenes, in order: 2 to 30, up to 10 minutes in all. Scene IDs are all different.emails: list of film-emails. The emails the film's email scenes show, with IDs all different: up to 4.emails[].id: ID, required. The email's ID, which email scenes name.emails[].from: text ID, required. The text ID of the sender's name.emails[].address: text ID, required. The text ID of the sender's address. Use an address that ends in .example.emails[].subject: text ID, required. The text ID of the subject.emails[].lines: list of text IDs, required. The email's lines.emails[].button: text ID. The text ID of a button in the email.emails[].link: text ID. The text ID of the address the button really goes to, shown when the pointer rests on it.emails[].attachment: text ID. The text ID of an attached file's name.style: text. CSS for the film's drawing scenes, up to 32000 bytes. It may use @keyframes, @media and @supports rules, and no addresses: url() names only a part of the same drawing. Kapi's clock plays every animation it starts, and every part sizes with box-sizing: border-box. The canvas is .kw-canvas; while a scene waits for a tap it also has .kw-targeting, and a tapped target has .kw-right or .kw-wrong. A part chosen for a question with several right parts has .kw-chosen, and every chosen part has .kw-right once the answer is right.
Scenes
A scene of a film. Its layout sets the keys it takes.
scenes[].id: ID, required. The scene's ID.scenes[].title: text ID, required. The text ID of the scene's name, shown in the transcript and on the seek bar.scenes[].seconds: number, required. How long the scene runs, from 4 to 60 seconds, in tenths at most, such as 6.5.scenes[].layout:"title","number","email","chat","person","icons","checklist","drawing", required. The drawn layout.scenes[].caption: text ID, required. The text ID of what the narrator says, shown as captions. Short sentences, and never a placeholder.scenes[].picture: text ID, required. The text ID of what the scene shows, for the transcript and screen readers.scenes[].headline: text ID. The text ID of a few words on the picture.scenes[].pause: ID. The ID of a choice or multi practice question the film stops for after this scene. No page or test pool may hold it too.
title scenes
A title card.
scenes[].heading: text ID, required. The text ID of the title.scenes[].kicker: text ID. The text ID of a small line above it.
number scenes
A number that counts up, with its label.
scenes[].number: text ID, required. The text ID of the number, such as 38%.scenes[].label: text ID, required. The text ID of what the number counts.scenes[].note: text ID. The text ID of a small line under it, such as where the number comes from.
email scenes
An email from this film's emails. Each beat moves the camera to the part it marks, in order.
scenes[].email: ID, required. The ID of an email in this film's emails.scenes[].beats: list of"arrive","mark-from","reveal-address","mark-subject","mark-lines","point-link","mark-attachment","report". What happens, in order. Left out: the email shows still.
chat scenes
Chat messages that arrive one by one.
scenes[].messages: list of objects, required. The messages, in order.scenes[].messages[].who: text ID, required. The text ID of who sends it.scenes[].messages[].text: text ID, required. The text ID of the message.scenes[].mark: whole number. The number of the message to mark as the one to notice, counting from 1.
person scenes
A drawn person at work, on a call with someone else or saying something.
scenes[].label: text ID, required. The text ID of who it is, such as You.scenes[].prop:"phone","laptop","none", required. What they hold: a phone, a laptop, or none.scenes[].with: text ID. The text ID of who they're talking to, which draws a call.scenes[].says: text ID. The text ID of what they say, in a speech bubble.
icons scenes
Icons with their words, each in turn.
scenes[].items: list of objects, required. The icons, in order.scenes[].items[].icon:"search","phone","flag","mail","link","file","lock","key","shield","alert","check","clock","card","person", required. The icon.scenes[].items[].text: text ID, required. The text ID of its words.
checklist scenes
A checklist that ticks each item in turn.
scenes[].items: list of text IDs, required. The items, in order.
drawing scenes
A scene the author draws on a 960 by 540 canvas, with the film's style.
scenes[].drawing: text, required. The scene's markup, up to 16000 bytes: div, span, p, b, strong, i, em, u, s, small, sup, sub, br, ul, ol, li, and inside an svg svg, g, path, rect, circle, ellipse, line, polyline, polygon, defs, linearGradient, radialGradient, stop, clipPath, with only class, style, id, aria-hidden, data-text, data-count, data-from, data-d, data-du, data-target, viewBox, width, height, x, y, x1, y1, x2, y2, cx, cy, r, rx, ry, fx, fy, d, points, fill, fill-opacity, fill-rule, clip-rule, clip-path, stroke, stroke-width, stroke-linejoin, stroke-linecap, stroke-dasharray, stroke-opacity, opacity, offset, stop-color, stop-opacity, transform, gradientUnits, gradientTransform, preserveAspectRatio. Every word is a text ID on an empty element, such as <span data-text="intro.name"></span>. data-count counts a number up from data-from, after data-d seconds over data-du seconds. data-target makes a part a choice of the question the scene stops for, tapped on the picture: a choice question takes one tap, and a multi question takes every right part, then Check answer.
question
A practice question, with feedback after each answer.
type:"question", required. The block's type.question: ID, required. The ID of a question in questions.json that isn't in a test's pool.
contact
A company contact. Where the company hasn't filled it in, the page shows common.contact-missing.<key>.
type:"contact", required. The block's type.contact: ID, required. The contact's key, such as it-help, declared in context as contacts.it-help.
sources
The titles of the documents the package was made from.
type:"sources", required. The block's type.
divider
A line between parts of a page.
type:"divider", required. The block's type.
What Kapi checks
| Check | Severity | What Kapi says |
|---|---|---|
reference_unknown | Error | This names …, which the package doesn't declare. |
word_missing | Error | The words file has no text for …. |
word_owner | Error | …'s first part names nothing in the package. Start a text ID with its lesson, page or question ID, or course, common, role or assessment. |
word_unused | Warning | … isn't used anywhere. Remove it, or use it. |
markup_not_allowed | Error | These words use …. Words take only **strong**, _emphasis_, [label](https://host/path) links and line breaks. |
link_not_https | Error | The link to … must start with https://. |
link_host_undeclared | Error | These words link to …, which kapi-works.json doesn't list in links. Add the host if people may open it. |
alt_missing | Error | This picture needs alt text, or mark it decorative. |
captions_missing | Error | Sound or video with speech needs captions. |
media_file_missing | Error | The package has no file …. |
media_not_listed | Error | This media file isn't listed in kapi-works.json. |