After shipping Resleeve 1.0, I had a working product with one layout template, a Bootstrap frontend, and no customisation. The rendering engine was solid. Everything around it wasn't. I decided to rebuild the whole thing from scratch - not to fix bugs, but to match the quality of the output with the quality of the experience around it.
No frameworks
V1 used Bootstrap. V2 uses nothing - no UI framework, no component library, no build step. Just hand-written CSS and a vanilla JS file with zero dependencies. The decision wasn't ideology; it was control. I wanted every pixel to be intentional, and the overhead of working around a framework's opinions on spacing, colour, and interaction would have been greater than owning the styles outright. The result is a leaner, faster stylesheet with no unused rules and no specificity battles.
Architecture: a six-step wizard with live preview
The biggest structural change was replacing a single form with a multi-step wizard. Six steps - search, select a release, pick a theme, style the background, tweak effects, download - with a live preview that updates server-side from step three onwards. The entire UI state lives in a single plain JS object; no framework, no store, no reactivity layer. Functions read from it and write to it. It's explicit, debuggable, and serialises cleanly into a shareable URL that encodes every configuration choice - template, background type, gradient stops, effect values - so users can share their exact setup with a link.
The rendering engine: three templates, six layouts
V2 has three layout templates - Nova, Atmosphere, and Horizon - each with a desktop and a mobile variant. That's six independent render functions in render_engine.py, each composing the full image with Pillow: drawing the background, placing artwork, laying out the tracklist, rendering the footer stats bar.
The hardest engineering in this project was making all six handle every type of release correctly and consistently. The case that exposed the most complexity was singles. A single-track release fed into a layout built for a twenty-song album produces a broken composition - one track rattling around in a column grid designed for forty. Every template needed single-track detection: identify the case, skip the tracklist entirely, and rebalance the remaining elements - artwork, artist name, title - so they're vertically centred in the available canvas space. Six functions, six different spatial calculations, each needing its own centring logic while staying visually consistent with the others. Implementing it once was easy. Implementing it six times without diverging required writing the logic carefully and testing against a wide range of real releases.
Background modes
V2 supports three background types, each with its own controls and render path:
- Solid - a flat colour, selectable from the extracted palette or via a colour picker.
- Gradient - a multi-stop gradient with an interactive visual editor. Stops are draggable on a rendered bar, colours are assignable from the palette or a native colour picker, and direction is controlled separately. The full gradient definition serialises into the share URL as encoded stop positions and hex values, so a shared link reproduces the exact gradient.
- Marble - a procedurally generated marble texture produced with layered Perlin noise in Pillow. It's seeded, so a saved seed value reproduces the same texture exactly. Dominant colour, scale, and detail are all adjustable.
The preview pipeline
Every setting change fires a POST to /preview with the full current state serialised as JSON. Flask deserialises it, selects the right render function, runs it, and returns a JPEG. The preview image swaps in place with a loading state while the request is in flight. The final download hits /generate with the same payload at full resolution - 1080p, 1440p, or 4K. Because the preview and download share the same render path, what you see is exactly what you get.
The details that make it a product
A lot of what separates a tool from a product is in the details that nobody notices when they're working and everybody notices when they're not. The autocomplete on artist and release search that queries MusicBrainz as you type. The start-over flow that resets state without breaking browser history. The vinyl-card carousel on the landing page - a custom JS component with 3D CSS transforms, a smooth drop animation, and a preloaded set of real wallpapers from the slideshow folder. The way the palette extracted from the cover art populates the accent colour picker, the solid colour options, and the gradient palette suggestions, so every choice in the UI is grounded in the actual artwork you're working with.
V1 produced good output. V2 is a product I'm proud to put in front of people.
Try it at resleeve.marsphobos.com.
For the full overview, read the Resleeve case study.