TUI library built from scratch with TypeScript and a Rust core, featuring a component-based API, signal-based state management, CSS-like styling API, a Rust-powered layout and rendering engine, and cell-based diffing.
measured on
full-screen animation, 176×52 terminal, m4 pro
typical frame
1.9 ms (median)
slow frames
4.3 ms at p95, 5.6 ms at p99, 8.7 ms max
frame rate
453 fps average, 115 fps worst
avg frame
typescript 0.6 ms → rust 1.2 ms → sync 0.1 ms → flush 0.3 ms
In-browser MKV video streamer and player built from scratch, featuring real-time 4K anime upscaling powered by WGSL (WebGPU) shaders ported from Anime4K.
measured on
1080p → 4k upscaling, m4 pro
per 4k frame
32.3 ms
frame rate
31 fps max (film is 24)
gpu work
38 passes from 3 shaders, run in sequence
frame budget
41.7 ms at 24 fps: cpu 0.5 ms → upload 4.5 ms → shader passes 27.3 ms, 9.4 ms spare
Paid music collaborations and song-cover campaigns for artists worldwide. Led frontend and backend development across both products, built the Next.js frontend from scratch, and owned payments, payouts, and mobile audio features. Cut data processing for 1M+ artists from nine days to seven hours and roughly halved Soundcharts costs.
AI mapping platform for satellite and aerial imagery. Built high-performance React interfaces for large imagery datasets, simplified component state and data flow, and helped move users to centralized sign-in with zero downtime.
Social content and analytics platform with shoppable feeds for brands. Led React adoption within an Angular application and improved embedded app performance for e-commerce sites across Europe. Built a custom state manager that cut the JavaScript bundle by 20% and automated package publishing.
hitide
dec 2020 - feb 2021
Online clothing brand. Fully automated stock updates with a tested pipeline that transformed Airtable inventory data and stored it in the website's database.
Online sports insurance company for individuals, tournaments, etc. Built payment and subscription workflows and internal support tools, redesigned the PostgreSQL schema, and consolidated two backends into one codebase.
Watch anime in real time, upscaled to 4K, in your browser.
Senmei is an MKV player built from scratch: a hand-written Matroska parser, WebCodecs decoding, and Anime4K's CNN upscaling shaders ported to WGSL and run on WebGPU every frame.
Quality
The same frame, as decoded (1080p) and after Senmei's Anime4K pipeline (4K). Open each image at full size to compare line work.
Original, 1080p
Senmei + Anime4K, 4K
Features
MKV playback: play/pause, seek, and streaming from a URL over HTTP Range requests
video: H.264/AVC (8-bit) and HEVC/H.265 (8/10-bit)
audio: AAC stereo
Real-time upscaling with WebGPU, using a multi-stage, multi-pass render pipeline
Subtitles with positioning and plain text rendering
Performance
Measured on 2026-10-11 on an Apple M4 Pro (Helium, WebGPU on Metal), streaming a 1.44 GB MKV over HTTP Range, 1080p → 4K, 819 frames:
32.3 ms per 4K frame, so 31 fps max (anime runs at 23.976 fps, a 41.7 ms budget)
27.3 ms in the Anime4K passes, about 4.5 ms uploading the frame, 0.46 ms on the CPU
How it works
Matroska parser (mkv.ts): written by hand, with an API tuned for a video player.
Decoding: WebCodecs VideoDecoder and AudioDecoder.
Upscaling: the WebGPU setup and the Anime4K pipeline are maintained by hand. These Anime4K shaders are ported to WGSL (High-End HQ Mode A preset), in pass order:
Anime4K_Clamp_Highlights
Anime4K_Restore_CNN_VL
Anime4K_Upscale_CNN_x2_VL
Anime4K_AutoDownscalePre_x2
Anime4K_AutoDownscalePre_x4
Anime4K_Upscale_CNN_x2_M
Which passes run depends on the source and output size, following the GLSL !WHEN conditions.
Precision: FP32 shader arithmetic to match GLSL; rgba16float intermediates throughout.
Color: the existing sRGB preview canvas is uploaded, so the original and upscaled views share the same video color conversion. Direct hardware VideoFrame uploads can take a different browser color path. More on handling color space conversion explicitly: https://x.com/wrennly_dev/status/2039326806260748757
Canvas sizing: the real source frame dimensions and the display box are kept separate. A ResizeObserver watches the canvas container, CSS pixels are multiplied by devicePixelRatio for the canvas backing size, CSS aspect-ratio comes from the current video frame or image dimensions, and sizing reruns on resize, fullscreen and DPR changes.
bun install
bun run dev # http://localhost:3000
bun run build
bun run preview
TODO
Map //!COMPONENTS 1/2 passes to narrower texture formats instead of rgba16float everywhere.
Play audio through an AudioWorklet instead of scheduling one AudioBufferSourceNode per decoded chunk: the worklet pulls PCM from a reusable buffer on the audio thread, so there are no per-chunk allocations or seams between chunks, pause/seek don't need to tear down a queue, and the played sample position gives a precise clock to sync video to.
Lock-free streaming: one SharedArrayBuffer ring buffer between the network and decoder workers (and the audio worklet), synchronized with Atomics, so nothing is allocated after startup and the GC never runs.
Seek bar previews generated client-side: a second, hidden VideoDecoder fetches (via HTTP Range) and decodes only the keyframe for the hovered timestamp, then scales it down with createImageBitmap.
Adaptive chunk size: measure every fetch, track bandwidth with an exponentially weighted moving average, fetch small chunks just in time on fast connections and buffer more aggressively on slow ones.
Judder-free 23.976 fps on 60/144 Hz displays: schedule each frame for a specific vsync using the audio worklet's sample clock and VideoFrame.timestamp, instead of drawing whenever a frame is ready.