Koder Web Kit — `engines/sdk/koder_web_kit`

Vanilla-JS counterpart of engines/sdk/koder_kit. One JS file + one CSS file, zero dependencies, ≈ 3 KB gzipped. Covers the cross-cutting UI specs (theme, back-behavior, error messages, safe-area) for every Koder web surface.

Role in the stack

Area Sector Consumers
Developer Platform SDKs all 158 Koder landing pages · admin web apps · TVWebOSTizenOS apps that share the web stack

Build-time / runtime boundary mirrors its Flutter sibling:

  • engines/sdk/koder_kit — Flutter runtime → Android · iOS · Linux · macOS · Windows
  • engines/sdk/koder_web_kit — browser runtime → web pages (landings + web apps + TV)

Primary couplings

Module Nature
meta/docs/stack/specs/themes/light-dark.kmd normative spec for the theme toggle (two-state, anti-flash, localStorage)
meta/docs/stack/specs/navigation/back-behavior.kmd normative spec for ESC / popstate interception
meta/docs/stack/specs/errors/user-facing-messages.kmd normative spec for <koder-error-banner>
meta/docs/stack/specs/app-layout/safe-area.kmd env(safe-area-inset-*) consumption (CSS tokens)
meta/docs/stack/specs/landing-pages/download-button.kmd normative spec for <koder-download-button>
dev/store / hub.koder.dev Store API that <koder-download-button> HEAD-checks at runtime
engines/sdk/koder_kit Flutter sibling — same API shape, different runtime
engines/sdk/koder_kit/docs/rfcs/RFC-001-spec-encapsulation-across-platforms.md parent RFC

Public surface

Custom elements

Element Purpose
<koder-theme-toggle> 40×40 px sun/moon button; ARIA-labelled; keyboard-accessible (Enter / Space)
<koder-back-scope> captures ESC and popstate; emits cancellable koder:back CustomEvent
<koder-error-banner id="…" message="…" technical="…" retryable> inline error per the spec; collapsible Show details; optional retry button emits koder:retry
<koder-download-button slug="…" [label] [ticket]> canonical Download button; HEAD-checks Store; renders link when available, "Coming soon" + ticket link when 404; emits koder:download-ready / koder:download-blocked; locale-aware (ptesen from <html lang>)
<koder-safe-layout> block-level wrapper; applies env(safe-area-inset-*) via --pad-top/right/bottom/left CSS vars; no consumer CSS required. Per meta/docs/stack/specs/app-layout/safe-area.kmd

Design-system parity wave v0.27.0 (WEBKIT-031…037 — GitHub Primer #092, GOV.UK #096, gov.br #098):

Element Purpose
<koder-code-block language filename line-numbers highlight copy> general code-hosting block (chrome only, not a highlighter); copy button, gutter, highlight ranges, dedent; binds --code-* tokens
<koder-error-summary> consolidated top-of-form error list with field anchors; auto-focus on show; focuses the field on link click (koder:error-jump)
<koder-summary-list> / <koder-summary-card> GOV.UK "check your answers" key-value rows with per-row + card-level actions (koder:summary-action)
<koder-cookie-banner> + window.KoderConsent unified GDPR+LGPD two-tier consent; opt-in default-deny gating; versioned consent-record (specs/privacy/consent-record.kmd); koder:consent-change
<koder-char-count maxlength threshold> GOV.UK limit-not-restrict live counter (no hard maxlength; over-limit alert)
<koder-cep-input target-*> gov.br CEP→address autocomplete (ViaCEP/HTTPS, overridable endpoint); koder:cep-resolved / koder:cep-error

JS API

Symbol Purpose
window.KoderTheme.current "light" or "dark" — the currently applied value
window.KoderTheme.saved "light" / "dark" / null — the persisted user choice
window.KoderTheme.apply() re-resolve and apply (consumer rarely needs)
window.KoderTheme.toggle() flip and persist
window.KoderTheme.setMode(mode | null) explicitly set; null clears → follow OS
window.KoderTheme.subscribe(fn) register listener; returns unsubscribe

CSS tokens

Token Light Dark
--bg #ffffff #0b1120
--text #0f172a #f1f5f9
--muted #64748b #94a3b8
--accent #5b4fe8 #7b70ff
--surface #f8fafc #1a1a2e
--border #e2e8f0 #2d2d44
--error #e84f4f #ff6b6b
--pad-top/right/bottom/left env(safe-area-inset-*, 0) idem

Anti-flash behaviour

An inline block at the top of koder-web-kit.js runs synchronously during parse, reads localStorage['theme'], and sets data-theme="dark" on the <html> element before any CSS applies — so a dark-mode first paint is not followed by a light-mode flash. Per meta/docs/stack/specs/themes/light-dark.kmd §Anti-Flash Script.

Status

v0.26.0 (2026-05-22) — released.

Feature Status
<koder-theme-toggle>
<koder-back-scope>
<koder-error-banner>
<koder-download-button> ✅ v0.2
window.KoderTheme API
Anti-flash inline
CSS tokens + safe-area vars
test.html smoke-test page
Gzipped bundle ≤ 5 KB ✅ (3.0 KB total — JS 2.1 KB + CSS 0.9 KB)
Minified build pipeline (build.sh) ✅ v0.2
Adoption sweep of 237 landings ⏳ ticket WEBKIT-001
<koder-safe-layout> wrapper ✅ v0.3

Dependencies

  • Custom Elements V1 (Safari 14+, Chrome 72+, Firefox 69+)
  • matchMedia().addEventListener('change', …) — graceful no-op on

    Safari ≤ 14 (manual toggle still works)

  • No JS / CSS framework. No build step today.

Design references