@schnaq/assets
v0.6.0
Published
schnaq logos and the pixel schnaqqi logo for the web
Readme
assets
schnaq brand assets: logos, schnaqqi, its animations and the pixel logo for the web.
Everything here is © schnaq GmbH; the logos and schnaqqi artwork are all rights reserved, the source
code is MIT (see LICENSE).
| Folder | What it is |
| --- | --- |
| logos/ | Current logo with wordmark, schnaqqifant variants, legacy logo (see logos/README.md) |
| illustrations/ | schnaqqi illustrations (rocket, lamp, climbing, …) |
| animations/ | schnaqqi pixel sprite and the claymation loop, with their render tools |
| web/ | The npm package's code: the logo that turns into the pixel schnaqqi on click |
Logos: logos/schnaqqifant.svg is the source; node tools/logos.mjs (after npm install)
derives the white variant, the wordmark lockups, the square and the PNGs, and web/logo.js.
Catalog: every asset on one page, generated from the files on disk by tools/catalog.mjs
(no dependencies). Locally: node tools/catalog.mjs && python3 -m http.server 8000, open
http://localhost:8000/. GitHub Actions deploys it on our own runner to https://assets.schnaq.dev on every
push to main (other branches get a preview), behind Vercel Authentication, so only schnaq team
members can open it. npm releases are manual (see CLAUDE.md).
Animation: schnaqqi (pixel)

The schnaq.com elephant as a 48×36 pixel sprite, looping for 5 seconds (50 frames at 10 fps): idle, toot with sparkles, hop, stomp.
| File | What it is |
| --- | --- |
| animations/schnaqqi/schnaqqi.js | Sprite parts, timeline and frame renderer (runs in browser and node) |
| animations/schnaqqi/index.html | Preview player with scrubber, background toggle and pixel grid |
| animations/schnaqqi/tools/export.mjs | Renders the GIF and a contact sheet, no dependencies |
| animations/schnaqqi/dist/schnaqqi.gif | 384×288 transparent GIF, loops forever |
| animations/schnaqqi/dist/schnaqqi-sheet.png | All 50 frames on one sheet |
Re-export after changing the sprite or timeline (scale defaults to 8):
node animations/schnaqqi/tools/export.mjs 8Preview in the browser (ES modules need a local server):
cd animations/schnaqqi && python3 -m http.server 8000
# open http://localhost:8000Animation: schnaqqi codes (claymation)

A plasticine schnaqqi types with its trunk, sips coffee, sprints through the last lines and trumpets when the tests pass. 5 seconds, 60 frames at 12 fps ("on twos"), with stop-motion boil: handled pieces shift a hair each frame and their fingerprints crawl. Everything is modelled in three.js from primitives; the clay texture is generated in code.
| File | What it is |
| --- | --- |
| animations/schnaqqi-coding/scene/timeline.js | Phases, keyframes and what moves on each frame |
| animations/schnaqqi-coding/scene/elephant.js | The clay schnaqqi rig and its tapered trunk |
| animations/schnaqqi-coding/scene/set.js | Desk, laptop, mug, rubber duck, stars, backdrop |
| animations/schnaqqi-coding/scene/screen.js | The code editor on the laptop screen |
| animations/schnaqqi-coding/scene/clay.js | Fingerprint bump texture, lumpy geometry, boil |
| animations/schnaqqi-coding/index.html | Player with scrubber and phase timeline |
| animations/schnaqqi-coding/tools/capture.mjs | Renders in headless Chrome and encodes with ffmpeg |
| animations/schnaqqi-coding/dist/schnaqqi-coding.gif | 600×450 GIF, loops forever |
| animations/schnaqqi-coding/dist/schnaqqi-coding.mp4 | 1200×900 H.264 |
| animations/schnaqqi-coding/dist/schnaqqi-coding-sheet.png | All 60 frames on one sheet |
Re-render after changing the scene (needs Chrome, ffmpeg and network access for three.js):
node animations/schnaqqi-coding/tools/capture.mjs # GIF, MP4 and contact sheet
node animations/schnaqqi-coding/tools/capture.mjs --frames 0,26,46 # single PNGs in dist/preview/Preview in the browser:
cd animations/schnaqqi-coding && python3 -m http.server 8000
# open http://localhost:8000Pixel logo for the web (web/)
The normal schnaq logo (SVG) that turns into the pixel schnaqqi on click. Every sprite pixel is a
spring-loaded particle: they appear over the logo in a left-to-right sweep, schnaqqi toots with
sparkles and hops (the Toot and Hop phases of animations/schnaqqi/schnaqqi.js), and the pixels sweep away
again, handing back to the SVG. About 4 seconds. Canvas only, no dependencies; with
prefers-reduced-motion the click does nothing.
| File | What it is |
| --- | --- |
| web/pixel-logo.js | mountPixelLogo(el) → { play(), destroy() }; spring and sweep tuning at the top |
| web/logo.js | The colour and white logo SVGs as strings (generated by tools/logos.mjs) |
| web/react.js | <SchnaqqiLogo height={23} /> for React / Next.js |
| web/index.html | Header, footer and stage preview |
Install it from npm (see CLAUDE.md for releasing):
npm i @schnaq/assetsReact / Next.js:
import { SchnaqqiLogo } from '@schnaq/assets/react';
<SchnaqqiLogo height={23} />
<SchnaqqiLogo variant="white" height={46} /> // white logo + white pixels, for blue/dark backgroundsAnything else: put the logo in a <button> (keyboard works for free) and mount it:
import { LOGO_SVG } from '@schnaq/assets/logo';
import { mountPixelLogo } from '@schnaq/assets/pixel-logo';
button.innerHTML = LOGO_SVG; // or LOGO_SVG_WHITE with { variant: 'white' }
const logo = mountPixelLogo(button); // { play(), destroy() }Give the button a height that is a multiple of 23px (the sprite height), e.g. 23px in a footer and
46px in a header; other heights snap to the nearest whole pixel size. The canvas covers the whole
48×36 scene and overflows the button, so the trunk, sparkles and hop can leave the logo's box.
Preview from the repo root (it imports ../animations/schnaqqi/schnaqqi.js):
python3 -m http.server 8000
# open http://localhost:8000/web/