This is the specification of TCE version 3. It is normative: it says how a package must be written, built, published and embedded. Where code and this specification disagree, one of them is wrong and gets fixed — the specification never describes a "current state", only the rule.
A Tobidot Custom Element is a self-contained Web Component (TypeScript, built with Vite into an ES module and an IIFE) that is published to a registry as a versioned package and can then be
<script src> tag and one HTML tag, with no build step and
no JavaScript on the embedding side (Integration),Packages never share source at runtime. They talk through three narrow channels — slots, bubbling request events, and library functions guarded by per-function contracts (Interfacing) — and every input that crosses a package boundary is validated (Coding Style).
| Kind | Has a DOM? | Loaded at runtime? | Examples |
|---|---|---|---|
element |
yes | yes | tce-notepad, tce-desktop, tce-window |
library |
no | yes | dll-tce-file-system, dll-tce-settings |
sdk |
no | no — bundled at build time | common (@tce-v3/common), desktop-protocol (@tce-v3/desktop-protocol) |
Elements and libraries are the same thing at the package level (Package Model):
both bind themselves into the page's loader, both have a version and init(), and a library
additionally exposes functions. An SDK package is the TypeScript every package compiles against;
it is published to the registry only so the generator can vendor it into new
projects, and it never appears in the public registry response.
{ namespace, name }, tag names, class names, prefixes.$-prefixed DOM handles, explicit
accessibility, the five-way class split, validating external input, the lint rules.attach_styles.init- and data-
attributes, the parent/child contract.public/ assets and resolve_asset_url, cheap init(),
code splitting, the dual ES/IIFE build.tobidot-project.json Manifest — the project metadata file.npm run pack builds dist/index.js + dist/index.global.js and zips dist/
(Assets & Build)./tce-elements/{namespace}/{name}; the desktop's package manager
installs it the same way at runtime (Integration).namespace is data
(Naming).