kluuu mascot

90 moods, one spec.

The mascot is a pure function of numbers. An app sets a mood; the transition, the breathing and the blinks happen in the runtime.

How the spec reaches an app

  1. 1

    Ship it embedded

    The runtime and the spec sit in the app bundle. The first launch renders without a network.

  2. 2

    Check occasionally

    Once a day, jittered per install, never on every launch and never on a metered connection. A check that finds nothing costs one 304 with no body.

  3. 3

    Swap atomically

    Verify the signature and hash, then replace. If the new spec fails on the next launch, the client falls back to the embedded copy.

Endpoints

Base URLhttps://kluuuapi.glade.studio

Every path below is relative to this. Set with NUXT_PUBLIC_SPEC_BASE_URL; unset means origin-relative.

Spec

What an app fetches to stay current. Content-hash ETags throughout, so a poll that finds nothing new costs a 304.

  • GET/spec/v1/index.jsonPointer to the current version, with its sha256 and channels.max-age=300 · swr 24h
  • GET/spec/v1/releases/1.9.0/bundle.jsonAn immutable release: geometry, rig, motion and every mood.immutable · 1 year
  • GET/spec/v1/schema.jsonJSON Schema, generated from the same rig descriptors.immutable · 1 year

Rendering

A mood as a self-animating SVG, with its idle loop baked into CSS keyframes. No script, no runtime — it works in an <img> tag, a README or a CMS.

  • GET/api/mascot/{mood}One mood, animated. CORS open. Unknown mood ids 404 rather than falling back.max-age=1h · swr 7d
    • size=512 (16–2048)
    • bg=ffffff (hex, no #)
    • colour=mood|brand
    • idle=off|subtle|lively
    • frames=24 (6–60)
    • duration=4000 (500–20000)
    • seed=1 (1–9999)
  • GET/api/cloudsA drifting cloud band. Every scenery parameter is a query key of the same name; out-of-range values are clamped. Also served at /api/clouds.svg.max-age=1h · swr 7d
    • preset=soft|banner|outlined|launchpad|dusk|night|fill
    • frameW=402 · frameH=872 · cover=0.32 · zoom=0.57
    • depth=3 · layerGap=0.08 · scale=1.35 · softness=0.75
    • haze=1.17 · seed=0 · rocket=0 · launch=0
    • items=0 · drift=49 · cloudL=0.985 · cloudC=0.014
    • cloudHue=236 · outlineDL=-0.09 · outlineW=0 · innerDL=-0.038
    • innerSize=7 · accentDL=0.02 · accentW=0 · skyL=0.93
    • skyC=0.06 · skyHue=236 · skyOpacity=0
    • t=4200 (a still frame)

Sources and docs

Served from the repo files themselves, so what you download is what is running here.

  • GET/api/download/{target}package → the npm tarball (302 to the versioned file) · swiftui → zipped Swift package · react-native → all four adapters (SVG and Skia) and everything they import · parity → PARITY.mdno-store
  • GET/api/docs/{doc}integration | research — rendered HTML plus the extracted heading tree.must-revalidate

Embeddable bundle

Static files, not endpoints. Two of them go into an app: the runtime is code, the spec is data — which is what lets a new mood ship without a store release.

  • GET/embed/kluuu-mascot-1.9.0.jsThe runtime: rig, scene builder, spring integrator, idle layer. ESM, no dependencies.immutable · 1 year
  • GET/embed/kluuu-spec-1.9.0.jsonThe offline baseline the runtime reads before any update lands.immutable · 1 year
  • GET/embed/kluuu-mascot-1.9.0.tgzThe npm package, pinned to a version. This is the URL to put in a package.json — npm keys its integrity hash by URL, so an unversioned one breaks `npm ci` the day the bytes change.immutable · 1 year
  • GET/embed/manifest.jsonVersions, integrity hashes and sizes for the files above.immutable · 1 year

Integrate

A framework-free tag for plain HTML, a CMS template or a page you do not control the build of.

html
<script type="module">
  // The embed bundle is one self-contained ESM file with no imports at all, so
  // it works from a plain HTML page with no build step. It exports the element
  // classes rather than registering them, which is what lets you pick the tag.
  import { KluuuMascotElement, KluuuCloudsElement }
    from 'https://kluuuapi.glade.studio/embed/kluuu-mascot-1.9.0.js'

  customElements.define('kluuu-mascot', KluuuMascotElement)
  customElements.define('kluuu-clouds', KluuuCloudsElement)

  // With the package installed, one side-effect import does the same thing:
  //   import '@kluuu/mascot/define'
</script>

<kluuu-mascot mood="happy" size="160"></kluuu-mascot>

<script type="module">
  const el = document.querySelector('kluuu-mascot')
  el.mood = 'celebrating'        // springs across, never cuts
  el.setAttribute('idle', 'lively')
  el.setAttribute('colour-mode', 'brand')  // any mood in the original green
</script>

Full guide, including versioning, signing and the native targets: integration guide.