Linh Le · senior full-stack engineer. End to end means end to end, from server to screen.

It loaded fast. Here's why.

Flash-free. Zero-dependency. View-source clean.

The page is the work sample.

Five things on this site that are fast because I read what the browser already does well. On this one you can check: Ctrl+U anytime. Where the right column shows code, it's pulled live from disk; the raw ↗ link opens the file.

№ 01 · input

Two letters and you've redecorated.

The shortcut steps aside if you're typing into a search box, so it never fights you. (Seven lines of vanilla event-listening; no library involved.)

№ 02 · hover

Hover ahead. The next page is already on its way.

Move your cursor onto a nav link and the site fetches the next page in the background. By the time you actually click, it's already on disk. Open the network tab and watch the prefetch fire. (The router injects a <link rel="prefetch"> into <head>, deduped per URL.)

Tried first · prefetch every link

The easy version walked every in-page link on load and injected <link rel="prefetch"> for each. It works, but it spends the visitor's bandwidth on pages they'll never open, on a site whose whole pitch is that every byte is deliberate. An IntersectionObserver that prefetched links as they scrolled into view was better but still speculative. Hover won: once the cursor lands on a link the intent is real. One <link>, deduped per pathname, almost always on disk by the click.

№ 03 · order

Late subscribers still get the last value.

Init order stops mattering: each topic caches its last value and replays it to new subscribers in a microtask.

№ 04 · paint

Nothing flickered.

The site picks a theme before the browser draws a single pixel, so a hard-refresh never gives you that "whoops, we meant the dark version" flash. (Inside: an inline <head> script sets data-mode before any stylesheet starts loading.)

№ 05 · system

Those drifting spots are a system, not a texture.

Two chemicals on a grid: A gets fed in, B eats A and decays; the patterns are emergent. State lives in an RGBA texture, a shader runs the Gray-Scott update on every cell in parallel, ping-pong framebuffers step time forward. (The interesting call was what to put on the GPU and what to leave in JS.)

Tried first · the CPU

First version stepped Gray-Scott in plain JS over a Canvas2D buffer: two float arrays, a double loop every frame. Correct, and far too slow: a few hundred cells in, the frame budget was gone and the pattern crawled. Moved the update onto the GPU: state in an RGBA texture, the step as a fragment shader, ping-pong framebuffers to advance time. Now the CPU does nothing per frame except ask for the next draw.

Track record

~13 years, every layer.

Looking for:

Interesting things to build, with a team that'll argue about how. If that's where you're hiring, send me an email: linh@lelinh.dev.

Or keep reading the work.