This site looks like a static portfolio. It is a server-rendered Next.js application running on AWS Lambda, with a sky that no one has seen before and no one will see again. This post explains the three parts worth explaining: the hosting, the background, and the AI that built most of it.

The hosting
This is full server-side rendered Next.js without a server to own. Page requests run on AWS Lambda through the Lambda Web Adapter, which lets the normal Next.js server handle HTTP inside a serverless function. There is no Express wrapper, no custom server process to patch, and no instance sitting idle between visits.
CloudFront sits in front with two origins. Page requests and API calls go to the same Lambda, so the app keeps the useful parts of server rendering: dynamic metadata, private logic, route handlers, incremental regeneration, and API endpoints living beside the pages that use them. Static assets go to S3 with long cache headers, so the Lambda only sees requests that actually need application code.
CloudFront forwards the request to the Lambda, where Next.js renders the HTML on demand.
There are two environments with separate Lambda functions, S3 buckets, and CloudFront distributions. Pushing to main deploys production. Pushing to dev deploys a preview at a separate domain, locked behind basic auth in the Next.js middleware. Production has no auth variables set, so the same middleware passes traffic through untouched.
The practical result is "serverless side rendered" Next.js. It behaves like a real server-rendered app, but scales down to zero and fans out automatically under traffic. For a portfolio-sized site, Lambda's free tier can absorb a large amount of traffic before there is any meaningful compute bill.
The sky
The background is not an image and not a particle library. It is raw WebGL: tens of thousands of point sprites, generated fresh on every page load from a random seed.
Each nebula follows a structural profile modeled on a real object, and takes its colors from the photograph of that object. The large cloud follows Orion: a deep red surround, green gas fronts, a salmon interior, a pale core. The ring follows the Helix: an orange ring with a golden rim around a steel-blue cavity. The web keeps the Crab's filament anatomy in the Cat's Eye's teal and salmon. A cloud is built in layers with fixed opacity budgets: outer volume, shell, body gas, inner cavity, wisps, emission glow, and dust. The bright structure lives in the inner half of each cloud, the way it does in the photographs; only faint gas reaches the silhouette. Gas blends additively. Dust blends over it and occludes the stars behind.
The shaders compile in the background while a lightweight canvas starfield covers the wait. When compilation finishes, the nebula fades in over it. Behind everything sits a dust of 1,800 faint stars, generated once as point geometry. That layer draws on every page of the site; the interior pages keep it under a single small corner cloud.
Every nebula is a literal point cloud: thousands of particles, each one nothing more than a position, a size, a color, and a role (outer volume, shell, body, filament, dust). Most particles render as soft gaussian sprites that accumulate into gas. Two kinds carry their own glyphs. Young stars draw a tight core with four diffraction spikes, scattered along the shell arcs above the gas. Wisps draw as oriented streaks, emitted in chains that walk along an arc with each streak overlapping the last, so they fuse into continuous curved fibers. There is no mesh and no pre-rendered image behind any of it.
Each particle also carries a second, optional position: a point sampled from a signed distance field built out of an SVG path. Hover an element that names a shape, and every particle in the scene eases toward its target over about half a second. Shell and filament particles land on the outline. Body particles fill the interior. The spiked stars space themselves evenly along the outline, so the shape gets a beaded rim. Stop hovering and the same easing runs in reverse, back into the nebula's normal drift.
The scene respects the machine it runs on. It is fill-bound, so the canvas backing store is capped: soft gas upscales invisibly, and a 4K window would otherwise triple the per-pixel work. The gas sprites run a minimal fragment shader, and the star and wisp glyphs draw through a separate program, so the heaviest layer never pays for glyph math. Slow GPUs get a reduced render scale after a few dropped frames. Phones drop the big cloud entirely and run two small, brighter ones in the open corners, because the card stack covers everything else.
It respects the person running it too. The scene checks prefers-reduced-motion once at boot. If the flag is set, every hover morph snaps straight to its target with no easing: no drift, no half-second ease, just the shape. Every device exposes that flag at the OS level, independent of browser.
Claude's first pass didn't check for it at all: the hover morph animated the same way no matter what the operating system was told. Adding the branch was a direct call-out, not something a review of the shader math would have caught. That is the gap this project keeps surfacing: the model ships the visible feature; a person has to notice what it left out.
The AI
Claude, running Anthropic's Fable model inside Claude Code, wrote most of this codebase. The architecture came from a written plan with a reference implementation. The sky came from a specification that set the palette, the opacity range of every layer, and the motion rules before any code existed.
That order matters. The model is fast. The plan is why the output was worth keeping. I wrote about that split in the previous write-up.
The first pass was not the finished site. Fable could turn a detailed specification into pages, components, and a working visual system, but it did not know which omissions mattered most. That takes an experienced person looking beyond whether the page renders: checking semantic structure and keyboard behavior, reading a Lighthouse report, tuning cache policy, verifying metadata and social previews, and making sure search engines and analytics can see what they need without seeing what they should not.
Those details are easy to miss because none of them announce themselves in a screenshot. A site can look complete while shipping weak SEO, inaccessible interactions, uncached assets, incomplete meta tags, or no useful measurement of how people move through it. The human contribution was knowing to ask those questions, interpreting the results, and returning for the second and third passes that an AI working toward visible completion would not initiate on its own.
The source is on GitHub. The details behind any of it are a conversation away: hello@artnikitin.dev.