Victory City reborn — the full breakdown

It used to be weird: 1 win equals an entire skyscraper. Played 5 games — you have a five-tower district, which made no sense for a game about stacks of 11 blocks.

We rebuilt everything at the core and added a bunch of viral features. No database migration was needed — all old wins recompiled automatically. If you used to have 30 towers from 30 wins, now you will have 5–7 towers plus one under construction.

NEW BRICK MODEL

1 win now gives 1 to 5 bricks:
— base +1
— vs human opponent +1
— Hard AI +1, Extreme +2, Impossible +3
— golden victory +1

Bricks stack chronologically into towers of 11. The 11th brick closes the highrise. If that final brick was special (golden victory or Impossible AI), a golden crown spire sits on top, with a star and smoke above it.

Floor color = the skin you used in that win. Towers come out colorful — it is the history of your skins.

INTERACTION

Hover any floor — tooltip shows the specific win: opponent, AI difficulty, date. Hover the whole tower — status (closed/building), build period from first to last win, how many wins it took. The tower itself is highlighted and slightly scaled up. Click a tower — modal with the full list of wins and brick count from each (grouped per win).

Tower filters: all / crowned / contains Impossible AI / last week. Others go semi-transparent.

“Next highrise: 7/11 bricks” indicator under city stats — you see how close the next tower is to closing.

SHOTS, VIDEO AND VIEWS

4 camera presets: Iso (overview), Top, Cinematic (low cinematic angle), FPV-flythrough + auto-rotate. Smooth transition between them. 6 saved view slots — found a nice angle, save it with a name, come back in one click.

4 time of day presets: Night, Morning, Day, Sunset — sky color, fog, sun and exposure all change. At night windows in the towers light up, stars come out. Seasonal weather: snow in winter, rain in spring, leaves in autumn (off in summer).

Time-lapse “History” — plays back city construction chronologically with dates in the corner. You see your city grow.

City snapshot with filters (Vivid, B&W, Sepia) and watermark “Highrise Heist · Name · N wins”.

8-second city flythrough video recording (.webm/.mp4, codecs vp9→vp8→h264). Where Web Share is supported — straight to system share sheet (one tap to TikTok or Instagram Stories), otherwise downloads as a file. Recorder shows a REC indicator with a progress bar and countdown.

Fullscreen mode. Minimap in the corner (gold/purple/blue, click to fly to that tower).

SHARING AND COMPETITION

“Share city” button. The modal contains three links with copy buttons:
— embed widget highriseheist.com/embed/city/123 — a standalone page with the interactive 3D city
— personal profile
— iframe snippet to paste into a blog/site (supports ?theme=day|night and ?nocontrols=1 query params for clean screenshots)

When the embed link is pasted into Telegram, Discord, Reddit, BGG or any blog, a beautiful preview card appears: name, 4 stats (wins/bricks/towers/crowns), tower silhouette. The image is generated on the server on the fly and refreshed after every new win.

“Compare with…” button with three tabs:
— Friends (if any)
— Top from leaderboard
— Search by exact username

Opens a side-by-side page with both cities, score and crowned leader. Score = towers × 100 + crowns × 50 + bricks (same formula used in Hall of Fame). On the compare page itself there is a “Share comparison” button — copies a link that gives its own nice preview in messengers with both names and the score.

The public profile of another player now also has a quick compare button — one click.

TOP AND FEED

Hall of Fame (“Top” button in the panel) — top 20 players by 4 metrics: city size (score), bricks, towers, crowns. At the top — global counters (total players, bricks, towers). Medals 🥇🥈🥉 for top-3, your row is highlighted with “(you)”. Click on a row — navigate to that player’s profile. Each row has a mini-preview as an SVG city silhouette (lightweight, no WebGL).

If your city is empty — a “See top cities” button appears right on the welcome screen — you instantly see what to aim for.

New endpoint /api/buildings/feed/recent — feed of last 20 wins of all players + global counters for 24h and all-time. Coming soon to the landing page and global feed.

LITTLE THINGS

Intro camera animation on first load and tower grow from the ground. ESC closes any modal. prefers-reduced-motion is respected — pulsing, smoke and weather are disabled.

UNDER THE HOOD

2D fallback for non-WebGL devices was rewritten for the new model — SVG isometric, wheel zoom, drag-pan, tap to select. Weak phones get mobile mode: fewer windows, simplified shadows, fewer weather particles. Rendering pauses when the city is off-screen or the tab is in the background.

OG previews are rendered via @resvg/resvg-js (Rust binding) — lightweight, no headless chrome, around 50 ms per image. LRU cache 500 images / 1 hour in memory. Invalidated automatically after a new win for both the personal image and compare images where this player participates. POST /api/buildings now returns the updated city right away — the client updates UI without a second request.

Messenger bots do not run JS, so for proper previews there are SSR pages /embed/city/:id and /embed/compare/:id1/:id2 — they serve og:image and redirect users to the full SPA.

3D POLISH PASS

After shipping the release, I went through the 3D engine with a flashlight and closed a handful of small but annoying issues.

Tower windows now light up at night on first profile load. Previously you had to click any time-of-day preset for them to “turn on” — the initial night view was dark with no glow, which looked off.

Windows no longer hang in the air while towers grow from the ground. Both during the first appearance of the city (intro animation) and in “History” mode (time-lapse) — windows now show up only after all towers have grown to their final height. Previously they stayed on their final positions while towers were small — looked like floating dots.

The 8-second flythrough recording no longer “eats” your enabled auto-rotate. If you had camera auto-rotate active before recording, it will be restored after the video. Previously it was silently turned off.

Roads (~10 pieces) now share one geometry, material and texture instead of being cloned each. This removed a leak of 10 GPU textures and 10 geometries on every profile open.

And a global resource cleanup — Victory City now correctly releases all WebGL resources when the profile is closed. If you open and close the profile many times in a row (or you keep the profile in a side panel and switch tabs), GPU memory no longer keeps growing. Also fixed: a recording-progress timer leak (if you close the profile mid-recording), orphaned mouse handlers and a race condition between component unmount and the animation loop that occasionally produced a console error.

Each fix on its own is barely noticeable, but together — visibly more stable on long sessions and weak machines.