# Kapi Works
> Kapi Works runs a company's training for employees, partners and customers, and keeps the record. A company can upload a course it made elsewhere as one HTML file.
- [Upload a course](https://www.kapiworks.com/guides/upload-course): the guide for people
- [Example course](https://www.kapiworks.com/guides/upload-course/data-protection-at-work.html): Data protection at work, connected to Kapi Works
## Make a course Kapi Works can run
Help me make a training course for Kapi Works, the learning platform my company uses.
Build the whole course as ONE HTML file. Kapi runs the file in a sealed frame and records where each learner is. The design, the words, the buttons (Next, Back, Exit), the quizzes and the layout are yours to make. Kapi only needs the rules below.
THE FILE
1. One HTML file that starts with , saved as UTF-8, 5 MB at most.
2. Put everything inside the file: scripts, styles, pictures and fonts (as data: URLs), or use system fonts. The frame has no internet, so do not use
Rules: 1 to 200 pages. Each id has lower-case letters, digits and hyphens, 48 characters at most, and is unique. Each title has 120 characters at most. A page is required unless it says "required": false, and at least one page is required. The course is finished when the learner has opened every required page and the course calls KapiWorks.finish().
THE KAPI CONNECTION
Kapi adds window.KapiWorks to the file. Do not add a script for it. Every call returns a promise.
6. When the course loads: const start = await KapiWorks.start(). It returns { mode, resumePageId, finished, pageSeconds, passMark, pages: [{ id, opened, met }] }. mode is "learner" or "preview". Open the learner where they stopped: resumePageId (a page id, or null for the first visit) and KapiWorks.load().
7. Each time a screen shows: await KapiWorks.page("raising-the-alarm"). Use ids from the page list only. It returns { pageId, requiredSeconds, secondsLeft, allowed }.
8. Before moving on: const { allowed, secondsLeft } = await KapiWorks.canAdvance(). The company may set a minimum time on each page. While allowed is false, keep your Next button disabled and show the time left. KapiWorks.onTime(({ pageId, secondsLeft, allowed }) => { ... }) tells you each second while a page waits, and when it opens. Back always works.
9. Progress: await KapiWorks.save(state), where state is JSON of 64 KB at most (the page, the answers, anything needed to continue). const { state } = await KapiWorks.load() gives it back on any device. Do not use localStorage, sessionStorage, IndexedDB or cookies; they last for one visit only.
10. Quiz score, if the course has a quiz: await KapiWorks.score(percent), a number from 0 to 100. The company decides whether the score counts. When it does, start.passMark is the pass mark for this learner: use it instead of your own, and offer another try while the learner is below it.
11. At the end: await KapiWorks.finish(). It returns { complete }, which is true when every required page was opened. The company may ask for more, such as a test or a review, so tell the learner that Kapi Works recorded the finish, not that every requirement is met.
12. Exit: when the learner presses your Exit button, save, then call KapiWorks.exit(). When Kapi closes the course itself, it first runs the function you give KapiWorks.onExit(async () => { await KapiWorks.save(state); }) and waits up to 4 seconds.
13. Links to other websites: use normal links. Kapi shows the learner the link to open. You may also call KapiWorks.openLink(url).
14. A call that fails rejects with { code, message, retryable }. Keep the course usable, and save again later when retryable is true.
15. In preview (start.mode === "preview") nothing is kept, and page times do not apply.
ACCESS AND QUALITY
16. Use real headings, buttons and labels. Everything works with a keyboard and shows where the focus is. Text contrast is at least 4.5:1. The course works on phones from 320 pixels wide to large screens, and respects prefers-reduced-motion.
17. Write in plain English. Name the official source for any law, rule or figure.
Ask me what the course is about, who it is for and which material to use. Then agree a short plan with me, with the page list. Before you give me the file, check it against every rule above. Give me the complete HTML file.