Contrast comes to your phone
This week Contrast came to your phone. There is now a chat-first mobile app that opens straight into a live conversation with your build agent and previews your running app on-device, a touch-optimized layout when you open Contrast in a mobile browser, and an automated pipeline that ships the app to TestFlight testers. On the desktop the whole workspace gained light mode, the homepage’s animated demo now boots a real IDE in about a third of a second, and SootSim took a big step closer to real iOS with faithful splash screens, retuned liquid glass, and enough native fidelity to run MetaMask end to end.
Platform
Contrast comes to your phone
The Contrast mobile app was rebuilt from a cramped mini-IDE into a chat-first companion for your projects. Open a project and you land straight in a live conversation with your build agent as the home screen: streaming markdown replies, activity cards that summarize what the agent is doing instead of raw tool-call noise, a gentle breathing animation on the agent’s avatar while it thinks, and smooth infinite scroll pinned to the newest message. Because your phone cannot run the build agent itself, anything you send kicks off a real reply from the same hosted agent that builds on the web. A native bottom tab bar with iOS-26 liquid-glass tabs plus a floating project switcher lets you jump between projects in place, the app ships with its own icon and branded launch screen, and GitHub sign-in is now the primary way in.
Opening Contrast in a phone browser gives you the same purpose-built layout rather than a squeezed desktop one: chat front and center, floating bottom tabs to move between Chat and Preview, a preview sheet with Web and Native views, and a floating top bar with a project switcher and a two-step settings flow.
Watch your project live from your phone
A new Preview tab shows your project’s actual running app on your phone: the deployed website in a web view, or your app full-screen through SootSim’s real iOS simulation, dismissed with a three-finger swipe so it never collides with gestures inside the app you are previewing. Both surfaces follow whatever your build agent most recently shipped and stream your current files and data straight from your dev session, updating live as you or an agent edits, with no build or deploy step.
Switching between the Web and Native panes used to reboot whichever one you left, which on Native meant a multi-second cold start you saw as blackness. Now both panes stay warm and the one you are not looking at simply parks off-screen, so flipping between them is instant. The status dot by the settings gear tracks your build for real (grey to orange to green), and tapping it opens a sheet that breaks the wait into Dependencies, Build, and Runtime steps instead of a bare spinner.
Mobile chat that reads like the web
Mobile chat now renders agent replies as faithfully as the web: GFM tables, task-list checkboxes, soft line breaks, and code fences (even ones with no language tag) all render properly, and it no longer breaks on nested or loosely-spaced lists. Long streaming replies parse incrementally as they arrive instead of re-parsing the whole growing message on every token, so they stop stuttering while they type out, and scrolling up mid-reply surfaces a jump-to-latest pill instead of yanking you back down.
Several silent failures that could stop a sent message from ever reaching your agent are fixed too: a project’s very first message now creates its conversation, a wedged or idled-out assistant recovers on the next send, and sending with an expired session shows a clear inline error. Build progress and tool activity render as proper activity cards on mobile instead of vanishing, and an unexpected error now shows a branded fallback with a retry instead of a raw red crash stack.
The Icon Designer becomes a full live AI icon tool, now free
The Icon Designer graduated from a dev-tools overlay into its own workspace column and became a real design tool. Its chat can compose icons directly onto the live canvas (gradient or solid backgrounds with shape or custom-monogram glyphs), you can drop in your own image, and it can generate images too: a clean SVG on any chat model, or a raster PNG via Nano Banana on Pro, composited as a transparent foreground over your chosen background. The pane is now a chat-left, preview-right layout with a segmented background-fill picker, and Install favicon writes a full favicon plus apple-touch-icon straight into your project with nothing to edit by hand. The whole tool is now free; only PNG generation stays a Pro feature.
Light mode across the workspace
The workspace now has a proper light appearance. The Factory view, where you watch the AI agents build your app, got a real light-mode floor scene plus several rounds of spacing and layout polish on the Beans panel, factory hero, and surrounding chrome. The code editor gained a light counterpart to its dark theme and swaps between them live as you toggle the app’s appearance, including on cached and reopened tabs.
The homepage boots a real IDE instantly
The homepage centers on an animated demo that morphs into a working Contrast IDE, and it had gotten rough. Visitors were being served a months-old cached page, and even when it rendered it flashed a full-screen placeholder card over the demo for a couple of seconds while the intro played flat. All of that is fixed: the placeholder is gone, the intro animates correctly from the first frame, and the full IDE chrome (top bar, code panes, phone preview) now arrives already rendered instead of downloading a separate chunk after load. The page paints in the right typeface immediately and shows the real demo in roughly a third of a second instead of several. The homepage also swapped its hand-drawn mockups for an actual screenshot of the real cross-platform preview fanout and picked up a new baked dithered background and a coordinated soft-fade polish pass across the header, hero, showcase, and production diagram.
SootSim paints your app’s real splash and launches faster
On boot, SootSim now shows your app’s actual configured launch splash (the real image and background read straight from your evaluated Expo config) instead of a placeholder, with faithful implementations of all three major splash libraries so whichever one your app uses behaves like the real thing. A new Splash tab in the Dev media manager lets you upload and preview it in a device frame, and the image is routed through the share proxy so splash screens show correctly in shared previews too.
Trying SootSim for the first time no longer means staring at a near-black frame. The boot shows a subtle progress strip and a quiet stage label, the mascot animates into the phone frame while it loads and hops back out the moment the home screen paints, and the splash no longer holds you on an artificial minimum wait. The home screen warms up every built-in app’s code during the first idle moment and starts loading an app the instant your finger touches its icon, so first launches land on work already in flight. The live clock on the home grid also sweeps smoothly and shows the correct time from the very first frame.
SootSim’s liquid glass matches real iOS
A broad fidelity pass on how SootSim renders frosted glass. The floating tab bar’s selected pill now settles into the same flat, denser-frosted look real iOS shows at rest (live glass only while pressed or dragging) and crossfades cleanly into place instead of flashing grey; its icons were measured against a real device and found too heavy, so the default stroke weight dropped to match, a missing newspaper glyph is supported, and the bar reports its real height so docked content sits correctly on home-indicator phones. Elsewhere, circular glass buttons no longer collapse to the wrong corner radius, low-opacity glass samples a properly blurred backdrop, adaptive materials render correctly dark in dark mode, and tab-bar glass gained a configurable vibrancy so pale tab-bar glass and vibrant menu glass differ correctly. Press and drag on the tab bar now settle with a slow, non-bouncy motion instead of overshooting, and screen-push plus edge swipe-back transitions stay smooth again.
App Store screenshots without spinning up a build
Opening Screenshots from a team’s dashboard now takes you straight to already-captured App Store screenshots you can view, edit, and download with no live device or build; only starting a brand-new shot spins one up. Review shows the real composed deliverable edge-to-edge instead of re-wrapping a stored image in another fake phone frame. The composer no longer reboots the simulator to tweak a shot: a Scene / Position / Screen toggle lets you edit a slide’s headline and see it re-composited instantly (even for 3D or composed slides), drag the captured screen onto the 3D phone to re-pose it, or re-shoot in place. A new capture command drives a real GPU-backed headless shell to capture and auto-upload editable slides straight to your org’s deck.
New example apps to explore
A new flagship example landed: Embergrove, a real-time multiplayer PS1-style 3D JRPG built on Contrast’s game template, where you see other players moving in the world live and each player keeps their own save. Over the week its world grew from a tech demo toward an app-store first impression with day/night lighting, visible NPCs and populated villages, animated retro water, wind-swayed foliage, dusk fireflies, procedural props, a branded splash, and a cinematic title-over-3D intro. Alongside it, the finance app Pennywise got a dark-luxe makeover with real features (custom logo, a floating gold pill tab bar on web, a budget summary, a calendar date picker, an animated per-category chart, and success toasts), and Pennywise, Travelo, and Sprout became the community gallery’s first fully deployed, live example apps.
Drive your projects from anywhere with the Contrast CLI
The new contrast attach <project> command links a local checkout to a live, signed-in Contrast tab so your CLI, or a coding agent running on your machine, can drive it directly with nothing to install beyond your existing login. From there the whole CLI behaves the same whether your app runs locally, in a cloud tab you have open, or is being built headless by the cloud factory: list, focus, logs, network, dev, and deploy all reach the right place, and deploy can even start a build with no tab open, handy from CI. For GitHub-connected projects, contrast push and contrast pull now do a real two-way sync. You can attach by a short per-user slug, a dropped tab reconnects on its own, and a new contrast shot takes a headless screenshot of your running dev app with an optional phone frame.
Templates and community apps get their own spaces
Templates and apps the community has built are different products, so they now live in different places: a clean, product-focused templates marketplace with no community rail, and a screenshot-forward gallery of community-built apps, split into dedicated sub-pages with a faded-edge tag scroll and a responsive card grid that lays out cleanly at every width. The curated template listings now show real icons rendered through the Icon Designer engine and real iOS screenshots of each template’s actual content instead of placeholders, and clicking Use template reliably creates a project again after a navigation bug had been silently dropping it.
Deploy and confirmation dialogs no longer silently hang
A whole class of confirmations across the app could quietly do nothing when clicked (signing out, deploying, restoring a snapshot, committing, forking or merging a project, deleting a file) because the shared dialog they rely on was not always present on the page. It is now mounted for the entire app, including the marketing splash and the mobile layout. Deploy in particular got an overhaul: your first deploy opens a dialog to pick a unique name, later deploys are a single click with a loading state, and failures show an error instead of appearing to hang.
Tech
Every server-rendered page was shipping blank in production
Cloudflare’s workerd runtime leaves import.meta.url undefined inside an attached ESModule worker, so the CJS-interop banner rolldown injects atop any bundled chunk with a CommonJS dependency (react.production.js in the SSR render graph) threw ERR_INVALID_ARG_VALUE at module eval. This only hit server-rendered routes; static routes serve prebuilt HTML and never touch the render graph. The framework’s page handler silently swallowed the throw and returned an empty 200, so every server-rendered preview and explore page had been shipping blank in production while deploy validation, which only exercises prebuilt routes, stayed green. Fixed with the same import.meta shim already used for __filename/__dirname, and prod-smoke now asserts a server-rendered route’s body so this class of silent failure cannot ship again.
SootSim now runs real crypto wallets end to end
Driving real crypto wallets through SootSim surfaced and fixed a chain of native-module gaps. react-native-blob-util was missing its .ios object, taking down redux-persist and MetaMask’s Engine hydration; get-random-values had a fail-open path that silently returned Math.random() bytes for seed entropy and now fails closed like upstream; a rive-react-native stub that never fired onPlay left onboarding CTAs stuck at opacity 0; and @segment/analytics-react-native was swapped for the real package after a hand-written stub silently killed MetaMask’s analytics-gated init. The headline fix is a faithful @metamask/native-utils nitro seam backing all eight accelerated hash/crypto methods with @noble primitives validated against canonical test vectors; without it HD-key derivation silently returned a zero-length HMAC and an empty BIP32 master key, so wallet creation always failed. A broader RN 0.83 / Fabric parity sweep rode along (13 missing root exports, the bridgeless UIManager surface, a corrected Platform.constants.reactNativeVersion that had been stuck seven minors behind, and inset-aware scrolling). MetaMask now completes onboarding, wallet creation, unlock, and home with a real account, and BlueWallet reaches its Wallets home screen.
The flights demo’s Durable Object, hardened under load
The flights demo runs an embedded zero-cache inside a single 128MB Cloudflare Durable Object isolate, and it was OOMing under concurrent traffic. Fixing it took the stack to Zero 1.7 plus four distinct fixes: the DO bundle was still pulling in the entire resident SPA client graph as memory it could never execute, and stripping that freed roughly 3.5MiB; with that headroom, connection pools left at orez’s conservative 2-per-db default were starving the view-syncer, so they were raised to cvr 10 / upstream 6 / change 4; the demo’s seed was moved server-side so a cold-boot reset mid-seed can no longer wedge a client’s next write; and better-auth’s rate limiter now reads Cloudflare’s per-visitor IP header instead of bucketing every login behind the shared edge IP. Deploy is now gated on the embed actually being ready to serve, backed by an N-client stress harness that drives many browsers logging in at once and asserts realtime fan-out to all of them.
Zero resyncs in place instead of reloading the page
When the backend resets its CVR or connection cookie under a long-lived tab (from co-tenant rebuilds, OOM health-timeouts, or a full dev-stack reset, hit roughly 10x/day by the heaviest user) the client used to hard-reload the whole page. The pure-state-loss cases now bump a generation value in React state instead, swapping in a fresh Zero client group in place while navigation, scroll position, and open preview iframes stay mounted as a stable sibling. A genuine code or schema change still triggers a real reload, and a dedup/backoff guard collapses duplicate reports from one reset.
Killing forced-layout stalls in the tiling workspace
Reading an element’s on-screen position with getBoundingClientRect() forces the browser to synchronously flush layout, and on the constantly-scrolling tiling workspace canvas those reads were interleaving with paint and causing jank during scroll, drag, and resize. We introduced observeLayout, a shared cache backed by a single IntersectionObserver that hands back the rect the browser already computed on its last layout pass instead of forcing a fresh one, and migrated the canvas’s section, resizer, reveal, and portal code onto it. A new oxlint rule bans raw getBoundingClientRect() in app code, a dev-only tripwire warns on slow calls, and three Playwright perf tests guard it.
A per-frame performance sweep through the SootSim engine
A broad pass through the CanvasKit render loop. The offscreen capture canvas repainted every frame even with no subscribers; gating it on having a consumer dropped composite paints in a 5-second sample from 29 to 2. The big structural win: useAnimatedStyle and the per-tick animation step were forcing a full Yoga relayout even for transform/opacity-only updates (the home-screen intro spring alone animates 32 icon placements at 60Hz), so layout invalidation is now scoped per owning node and the paint-only branch is taken explicitly. Paired wins include cached gradient shaders and reused scratch buffers instead of per-frame allocations, a 54-ellipse background decoration cached to one picture, per-property style diffing, subtree-bounds culling that made hit-testing roughly 82% faster on long lists, and bounding a leaf’s offscreen render target to its own rect (about 5.8ms/frame saved on an animated particle-burst stress scene).
Three stacked races behind intermittent project creation
An intermittent project-never-created failure (surfacing as a flaky deploy-gate but a real production race) turned out to be three bugs stacked. The durable active-project pointer write could reach postgres before the freshly created project row committed, violating its foreign key; it is now gated on the project’s server commit. A cold create-project page load booted the per-project runtime from a query that stays empty until the new row syncs back, a chicken-and-egg that could defer boot roughly 120s; it now reads the pending template id from pre-navigation state. And that same cold path could fire the create mutation before the sync client finished connecting, so the optimistic insert silently never landed; it is now gated on sync coming online. The whole thing was only findable after discovering the CI test itself was CPU-starved by SwiftShader software rendering; canvas-rendering harnesses now always run on GPU-backed Chrome.
A deploy-killing timeout in Cloudflare asset retention
Carrying forward previously-shipped static assets during a release re-downloaded the entire carryover set (44k+ files after a busy week) with no per-request timeout, so a handful of hung fetches could wedge all 16 download workers and blow the deploy step’s 10-minute cap, killing the release outright. The fix adds a per-request abort timeout, raises concurrency, downloads newest-first, imposes an overall deadline under the cap, and makes the asset manifest list only files actually written this run. A full production run now completes well inside the budget.
Contrast Mobile ships to TestFlight automatically
New mobile:build, mobile:publish, and mobile:invite scripts take the native companion app from source to TestFlight testers end to end (prebuild, pod install, archive, export, upload) with automatic App Store Connect app-record creation, provisioning and distribution-cert handling, and internal-tester invites. Everything authenticates through a single App Store Connect API key over REST rather than fastlane’s cookie-based flow, so there is no interactive 2FA re-auth. CI now cuts a build on demand or whenever a push changes the mobile template’s shippable code (docs and tests excluded), running on the self-hosted M1 Max lane so it serializes behind deploys, and the publish side polls each fresh build to a valid state and links it to the Internal Testers group automatically. Internal builds 4 and 5 went out this week.
Sign-in works again inside preview proxies
Public preview pages proxy their outbound fetches through an SSRF guard, and every external auth host was being rejected. Cloudflare Workers’ nodejs_compat does not implement dns.lookup, so every hostname resolution inside the guard threw and the catch treated the host as unresolvable, breaking Clerk sign-in inside the preview iframe. The fix moves to resolve4/resolve6, and a follow-up switched to DNS-over-HTTPS so the guard chases the multi-hop CNAME chains that Clerk custom domains use and behaves identically on Node and Workers. A separate bracketed-IPv6 bypass in the same guard was closed by stripping the brackets before the private-IP check.
PR-preview recordings were silently producing nothing
PR-preview recordings had been producing nothing, in prod and locally, ever since an ESM/CJS crash. The preview agent ships as ESM, but a CJS dependency pulled in transitively through the AI SDK called the bare require() that esbuild lowers to a throwing shim under ESM, crashing the agent on startup. It is fixed by injecting a top-level createRequire. The outage went unnoticed because the smoke test only HEAD-checked that the bundle was served; it now downloads and actually executes the served bundle in the post-deploy workflow.
Hosted agent runtimes self-heal from wedged connections
Two failure modes could leave a hosted agent project quietly unresponsive. If the realtime sync service bounced under a long session, the client could wedge into a silent reconnect loop without crashing the page, so the supervisor never noticed; it now watches for that error-storm signature and relaunches the runtime with a fresh sync client. Separately, a fully wedged page could hang the monitor’s own health check indefinitely (observed live as a runtime stuck for 19 minutes still reporting running); heartbeat reads are now bounded with a timeout and the runtime relaunches if none returns within the stale threshold.
Mobile
- Branded error and retry screens replace raw crash stacks, and preview panes show an on-brand “unavailable, retry” instead of a browser error or an endless spinner, handle rotation, and no longer slam shut on a stale animation.
- Sign-in no longer crash-loops on TestFlight builds, sign-out now actually invalidates your session on the server, and native sign-in no longer bounces back to the login screen mid-authentication.
- Stop reliably cancels a run even while your message is queued or the agent is still doing pre-response setup.
- Tapping into a project opens instantly from already-synced local data instead of blanking on a network round trip.
- Accessibility and layout polish: VoiceOver announces the settings and project-switcher controls, the app is locked to portrait, switching projects replaces the screen instead of stacking five deep, and a downward swipe over the message list dismisses the keyboard.
- Chat and the project grid stay smooth while replies stream, after stabilizing the identities that were re-rendering the composer, chat rows, tiles, and header on every token.
- Over-the-air update support was built and wired for the app but deferred for v1, sitting inert behind a build-time check so dev and simulated builds never load the native module.
SootSim
- The appearance toggle now reliably switches light and dark by reading the engine’s own settings instead of guessing from a DOM color.
- Custom app fonts route through the image proxy so they load in previews on the public site, and simulated Photos thumbnails paint a gray placeholder immediately.
- Lists that scrolled to the end snap back when their content shrinks, matching UIScrollView’s contentSize clamp.
- iOS context menus anchor from the trigger’s visible position, dismiss cleanly, and stay stable through submenus and surrounding re-renders.
- WebView overlays clip to the host app’s real visible geometry, and the WebView seam now matches real iOS load/error event behavior.
- Apps that manage their own splash keep that ownership across worker boundaries, the text-input caret blinks after focus, and a thrown screen surfaces the native-style red error overlay instead of freezing.
- Lists render at their true content size instead of being forced to item-layout estimates, and the home-screen dock stays capped at four icons.
- iOS 26 liquid-glass views gained per-corner radius, an interactive prop, and tuned dark-mode sampling; SF Symbols fall back to a drawn glyph, light glass tint renders white, and crowded flex rows no longer inflate.
- Voice input and offline speech-to-text libraries now work end to end in the simulator via a real browser-speech bridge running the upstream code unchanged.
- The desktop simulator shows the session id in its titlebar, signed-in dashboards get their own light/dark toggle, custom wallpaper can be dropped behind the device frame, and photo-gallery drag-to-dismiss completes reliably.
- The Connect screen surfaces Contrast Mobile dev-server targets in its scan.
Website and marketing
- A mobile-web layout pass: no sideways scroll, a readable footer and diagrams on iOS Safari, proper 44px tap targets, and a header that collapses into a hamburger menu.
- Faster first paint: a fallback font shows immediately instead of blocking for up to 3 seconds, 43 per-component CSS files consolidated into 1, and layout CSS inlined.
- The homepage’s live workspace preview no longer flickers (placeholder mismatch went from 17% to 0.000%), and the live demo is wrapped in an error boundary.
- The sootsim.com site got a developer deep-dive page, toned-down visuals, and a stabilized embedded live simulator, and the SootSim changelog page renders reliably again as per-version markdown.
- Fixes for a pricing-page 404, a homepage overlay that jumped into place after load, high-priority font loading, narrow-screen and Safari button polish, and a blank community-apps directory page.
- Windows visitors now get the correct .exe download, the org page phone grid scales fluidly, legal pages redirect to their consolidated home, and pricing plan cards were softened.
- Marketing copy pass: consistent TestFlight/GitHub/Cloudflare names, real Apple App Store and Google Play wording, refreshed hero and overview copy, and refined blog/changelog styling.
- The public homepage now shows a coming-soon page in production with the product behind a beta entrance (regular signup unchanged), plus a read-only admin dashboard of users, projects, usage, and signups.
CLI
- New
contrast edit <path>opens a file in your editor,contrast openlaunches the desktop IDE against your running dev stack, andcontrast doctor reapclears leaked Chrome processes;contrast shot,contrast web, andcontrast iosfollow the portscontrast devowns. - The sootsim CLI setup surface collapsed into
sootsim setupplusopen/runtime,serverwas renamed toserve, andsootsim skillinstalls agent skills into Codex or Claude. sootsim initis now a real command, and setup in a folder with no RN app prints copyable starter commands instead of a dead-end error.- Clean global uninstall tears down the background daemon and cache, the simulator auto-falls-back to headless on a display-less Linux box, and the Playwright driver reports host crashes instead of exiting clean.
- Interactive opens now default to Metro hot reload on, and a new
storage-clearcommand resets a running app’s storage.
Examples
- Travelo got a warm redesign with a display typeface and photo treatment, a redesigned profile screen, and live relative trip-status pills, plus fixes for a login crash, broken map tiles, and a native region-picker loop.
- Both bundled example apps now show real cross-platform success toasts (native on iOS, themed on web).
- The editor’s autocomplete and type-checking now understand the packages used by the canonical example apps, so building off an example gives correct suggestions and types.
Teams, auth, and access
- Magic-link sign-in works on the SootSim site end to end (correct origin, cookie, deployed email key, and a magic-link form on the invite page).
- Team owners can reliably remove a member after a database visibility quirk had made the delete match zero rows, and org owners can generate per-email prefilled invite links.
- New magic-link accounts get an email-verification prompt with a one-click resend instead of a pricing wall, and GitHub sign-in requests exactly the intended scopes once.
- Agents building in Contrast can push their finished branch and open or update its GitHub pull request themselves.
- The org dashboard now shows preview recordings for every repo, whether or not it was formally linked as a project.
Previews and sharing
- Demo app shares no longer render blank or crash (a re-resolved share URL and re-captured Bluesky/Uniswap bundles), and shared previews are fixed from a compressed-body decode bug and a dead service worker.
- No more white flash behind dark-forced previews for light-mode visitors, in the editor, on shared pages, and in the try-it demo.
- Live preview no longer gets permanently stuck after an interrupted catch-up, the native preview keeps its branded splash across reloads and recovers a black first paint, and iOS simulator preview links load reliably instead of timing out.
- Example-app previews no longer hang in the IDE on a silently crashed runtime, and apps using a native full-screen gallery or the imperative toast API preview correctly.
- Org project cards and dashboard thumbnails no longer come back blank, black, or stuck on a loading spinner, and the device-free screenshot review page works on any branch and stopped 404ing.
- The shared preview header no longer overlaps on medium screens, the build/screenshot iframe can no longer be squashed, and PR previews now demonstrate a component’s expanded state instead of repeating the same tap.
Editor and IDE
- The default project layout opens native-first with a wider, translucent device pane and a narrower web preview.
- File and Run merged into a single Action menu, the project picker scrolls instead of overflowing, and project settings consolidated so one place governs how the factory builds and another where it runs.
Design system
- New SegmentedPicker control (a data-driven sliding-pill toggle) replaces hand-rolled active-state chip UIs.
- Switch drops its dim thumb for a brighter default at a more compact size, and Button gained light-theme hover and press bevels with higher-contrast labels.
Reliability
- Connection-recovery reloads now show one clear 5-second countdown toast instead of a flood of near-duplicate ones.
- Spinning up a fresh project no longer throws a visible burst of failed network requests (down from around 10 to 2) thanks to gentler retry backoff and a held-until-ready background request.
- Fixed a crash opening the icon designer or a chat thread right after creating a project, from a data-layer column-type misclassification that double-decoded a value.
Tech (smaller wins)
- Realtime chat and sync now work on TestFlight builds after collapsing three URL-resolution bugs into one shared resolver that mirrors the website’s logic.
- SootSim previews run at full speed on Safari and iOS WebKit by scoping a require-corp COEP policy so SharedArrayBuffer engages instead of falling back to a slower per-frame copy.
- A deploy-time frozen-neutralizer rewrite was removed and gated after a drifted comment anchor could crash freshly deployed apps with “zeroAuth is not defined.”
- A Zero cold-boot thread-creation race is fixed with a converging check-then-insert; per-project sync now waits on a membership check before opening its socket, and anonymous identities are randomly generated rather than derived from a URL project id.
- The AI agent no longer drops a message sent mid-reply, and reply tracking survives process restarts via a durable
inReplyToId; partial replies also now stream live to remote viewers. - Security hardening: an exact-match CORS allowlist, session-derived userId on event insert, a DeepSeek/qwen 400 fix, and a closed SSRF bracketed-IPv6 bypass.
- The apex worker was kept under a re-measured 8.6 MiB budget, and the marketing entry bundle trimmed roughly 19KB by lazy-loading the IDE pane catalog.
contrast attach’s remote tunnel was hardened after an adversarial pass (per-user scoping, eval removed, an entitlement gate, and a 25-command cap).- A stable Zero provider shell ended homepage-demo crashes and a chronic CI flake, on-zero live-query results now match their array type on first render, and reconnects stop 500-ing.
- SootSim engine internals: Reanimated frame callbacks run on the shell UI runtime, idle MapLibre maps stop capturing every frame, the browser sync replica checkpoints its WAL log, and the render loop caches shaders and scopes layout invalidation (validated at sub-0.02% pixel diff).
- Native seams added or corrected for expo-modules-core UUID, expo-swiftterm terminals, gesture-handler’s Swipeable (back on upstream JS), expo native-view-manager resolution, and the Team Machine terminal PiP, plus import.meta.env support in the native preview bundler.
- Relocated native animations throttle idle ticks to 250ms and gate repaints to visible targets, with a compositor-worker proposal written up; scroll and animated-prop mirroring were hardened against timing and pointer races, and keyboard animation now streams per-frame.
- The automated PR-preview recording pipeline was hardened against target and lock races (coordinates resolved before recording, unfindable steps pruned, timed-out runs auto-stopped), and every invocation pinned to the verified global binary after a stale devDependency silently skipped previews.
- The homepage and SootSim shells are edge-cached to cut a cold-visit origin round trip, share links canonicalize onto the SootSim domain, a hydration mismatch in a lazily-hydrated store is fixed, and the shared event-helper package is now packaged into mobile Docker deploys.
- SootSim renders code-split One/vxrn apps on device, gives a bare Screen real native-stack push/pop, exposes a measurable onLayout target, and smooths the image-picker sheet and nested-scroll gesture arbitration.
Fixes & polish
Beyond the headline work, 466 fixes and 36 performance improvements landed this week. A few worth calling out: clicking Use template creates a project again after client-side navigation had been silently dropping its parameter; team owners can now reliably remove a member after a database quirk had made the delete match zero rows; and visitors stopped getting served a months-old cached homepage now that the live IDE demo build regenerates correctly.