plz

3D Concept Explainer Page

The goal is to let a first-time learner see where things get blocked, where they flow, and when they appear and disappear. Show structure that text alone cannot convey (layers, boundaries, flows, lifetimes) with a model, and let the learner trigger the events with a button. The model is half of the explanation, not decoration.

Output

Page language

Decide the page language in this order. If an earlier item exists, ignore the later ones.

  1. The language the user named (“make it in Japanese”)
  2. The language of the request
  3. The language mainly used in the conversation

Workflow

If references/preferences.md exists, read it first. Where items overlap, follow preferences over this document’s defaults. If it does not exist, use the defaults.

1. Decide the content first

Fact-check. If the topic depends on repository code or current product information, check it first (read the code, official docs, web search). Leave the sources you checked and the date at the end of the page, and write “not checked” for anything you could not verify. Learners trust this page as fact and memorize it.

Chapter design. Split into 5-10 chapters. Go from easy to hard, and use the last one or two chapters to apply the idea to the user’s actual situation (an issue in progress, a design draft, a product comparison). Decide three things for each chapter:

A chapter with no action in mind is either well served by text alone or should be merged into another chapter. Write a short chapter list, then build. Ask the user only when the topic scope is ambiguous.

2. Visual rules

This style is an architectural model (white massing model + ink outlines) seen in axonometric view. It is chosen so that learners read “structure”, so keep it when the topic changes.

3. Build from the template

Copy assets/template.html to the output location and fill in only the HTML marked TEXT and the SCENES section. Do not edit the ENGINE sections, which hold the renderer, camera fitting, label handling, animator, chapter switching, and verification hooks. They already contain fixes for bugs we hit.

4. Writing

5. Verify (do not skip)

Read references/gotchas.md first. Overlapping labels and clipped models cannot be found by reading the code.

  1. Start a local server in the background: python3 -m http.server <port> --bind 127.0.0.1 --directory <folder>
  2. Open the page at 1440×900 with a browser automation tool (for example Playwright). Check the console for errors (ignore a favicon 404).
  3. Run every chapter in one pass for the machine check:
    async () => { const out = {}; for (const n of window.__explainer.scenes()) {
      const text = await window.__explainer.run(n);
      out[n] = { text, overlaps: window.__explainer.overlaps(), clipped: window.__explainer.clipped() };
    } return out; }
    

    overlaps and clipped must be empty arrays. run waits until the action finishes, so no intermediate state is captured.

  4. Take a screenshot right after __explainer.run(name) for each chapter and look at it. Check that the end state matches the result sentence and that the empty space is not excessive (adjust with fitW and fitH). Give the save path as an absolute path inside a folder the tool allows (see gotchas).
  5. Check auto-play. Turn it on with __explainer.autorun(true) and scroll to a chapter. In one chapter, confirm that the loop runs three or more times, that each time the result sentence reaches the last step’s sentence and is cleared by reset, and that overlaps() and clipped() are empty at each final state. With it off, scrolling must run nothing; when you move to the next chapter during a run, the previous chapter’s loop must stop and the new chapter’s loop must start.
  6. Check on phones too. At 390×844 and 360×800 (deviceScaleFactor 3, isMobile, hasTouch), confirm that overlaps() and clipped() are empty arrays for every chapter, that there is no horizontal scroll (document.documentElement.scrollWidth === innerWidth), and that the layout does not break in landscape at 844×390. While scrolling, confirm that __explainer.current() matches the chapter being read on screen. Confirm that a vertical swipe on the stage scrolls the page and a horizontal swipe rotates the model.
  7. If you built a page that is not Korean (en, ja, zh-CN, an override language), confirm that __explainer.lang() is that language and that the screen text (HUD, hint, glossary and sources headings) appears in that language. At 390×844 and 360×800, confirm that the HUD’s chapter title, switch, and reset-view button do not overlap.
  8. Confirm that no placeholder remains and that no Hangul is left in a non-Korean page. Grep the finished page for placeholders of the form __…__ (for example grep -nE '__[^_ ][^_]*__' <page>.html | grep -v -e __explainer -e "label = '__actor__'"; the two filters skip the verification hook and the engine’s own default label argument), and expect no output. If the page language is not Korean, confirm that the visible text (excluding script and style, for example document.body.innerText and document.title) contains no Hangul (/[\uAC00-\uD7A3]/).
  9. After fixing, rerun 3, 5, 6, 7, and 8.

The phone layout is built into the template.

6. Deliver