:::meta description: How to give Tern's element names meaning, look and behaviour: the schema and every schema field, window.TERN.schema, add-ons, tern.define, custom transforms, styling, and labels in other languages. ::: ::site-nav # Vocabulary and behaviour {#top} ::toc Tern's core knows how a name is *written*, as in `:::theorem`, `::toc` or `:kbd[Ctrl]`, but not what it *means*. A **schema** gives names their meaning: the element, a label such as "Theorem 2", a counter, how a reference reads, a title slot, an end mark, a table of contents. The schema's `css` and `dom` fields, `tern.style` and `tern.define` give them a look and a behaviour. This page covers all of it, from a note that declares three names in its head to an add-on shared by a hundred notes. The live examples run with **no schema** unless they say `schema=demo`. The demo schema is the small vocabulary listed at the [end of this page](#demo-schema). ## Why names need a schema {#why} The core gives a name no meaning. `:::theorem` is `div.t-block.theorem` until a schema says otherwise: no label, no number, and a reference to it reads its title. ```tern {.live} :::theorem[Rank–nullity]{#rn} $\dim V = \dim \ker T + \dim \operatorname{im} T$. ::: See @rn. ``` The same note with the demo schema, which declares `theorem`: ```tern {.live schema=demo} :::theorem[Rank–nullity]{#rn} $\dim V = \dim \ker T + \dim \operatorname{im} T$. ::: See @rn. ``` The difference is one entry: ```js theorem: { tag: 'section', counter: 'theorem', label: 'Theorem', ref: '{label} {n}' } ``` **Why the core declares nothing.** Every subject needs its own names: a lecture has theorems, a lab notebook has protocols, a cookbook has steps. Labels differ from one language to the next. And a note must render from one script line, without a standard library to keep in step with it. So a note, or an add-on it loads, declares exactly the names it uses. A name without an entry still renders. It keeps its class and its `data-t`, so CSS and behaviours can find it, and it becomes an element on its own when the name is one: - an allowlisted element: `:::aside` is an `