The gallery is in the HTML now
The Vibes home page has one job: show you living apps and dare you to type. As part of the July latency arc, we kept shaving the path from prompt to app on screen. This week the gallery itself got the treatment — because the showcase of everyone else's apps was arriving embarrassingly late to its own party.
The old sequence for a fresh visitor: download the HTML, hydrate React, open the shared WebSocket, request two feeds over it, then paint a row of icon tiles. Four dependent hops before the first community app appeared — on a page whose whole argument is "this platform is alive."
Now the worker computes the composed gallery feed during the server render, and the gallery is real pixels in the first HTML byte stream. No hydration gate, no socket handshake, no feed round-trip. View-source on vibes.diy and the apps are just there.
Nobody pays a new aggregate
The tempting mistake would have been to give the SSR pass its own feed query. Instead it rides the exact same cached-report keys the WebSocket feed endpoints and the vibe switch's Recommended strip already share. One aggregate, three consumers. That's what made this a latency win instead of a load trade: the server render reads a cache that live traffic was already keeping warm, so the first paint got faster and the database saw nothing new.
Get posts like this in your inbox
One email field. Real updates. No algorithm required.
MTV credits for apps
Server-rendering the gallery also forced the card redesign we'd been circling. Icon tiles made sense when the tiles arrived late and small; real pixels in the first byte deserve real art. Each card now leads with the app's live screenshot capture, and carries its credits like a music-video lower third: icon badge, title, @handle, and a detail line — "Fresh pick," "34 members." Apps are made by people, and the cards now say so before you've scrolled.
Two landmines, defused
Moving a client-only surface into the server render tripped exactly two classes of bug, both worth naming for anyone doing the same move:
The document path isn't the only path. React Router 8's single-fetch means a client-side navigation to / doesn't request / — it requests /_.data. A worker that special-cases only the document URL happily server-renders first visits while silently starving every client-side navigation of loader data. The gallery looks perfect until someone navigates back to the home page.
window.location.origin is a hydration landmine. URL helpers that reach for the browser's origin work flawlessly right up until the component server-renders, where they degenerate into file:///assets/.... The screenshot URLs came out of the server render pointing at the worker's own filesystem-that-isn't. Every helper on the SSR path now derives its origin from the request, not the window.
Both bugs share a shape: a component that has only ever run in a browser accumulates browser assumptions invisibly, and the server render is the first honest audit it's ever had.
The bigger pattern is the one the whole latency arc keeps proving: the fastest request is the one you don't make, and the fastest paint is the one already sitting in the response. First paint is the app — and now the gallery of everyone else's apps keeps up.
See it in the first byte
Open the front page, watch it paint, then describe your own app in a sentence.
Start building →