mess · changelog
The working log, newest first. Back to the site.
Running log of updates, newest first. Each "## vX.Y" milestone is a build
that shipped (the site download / friends); "Unreleased" is what only
Eryk's installed app has. share-build.sh syncs the app version from the
newest vX.Y here.
Unreleased (in Eryk's installed app, not in the shared zip)
2026-08-28
- Buy Me a Coffee in the Help menu. One item, opens buymeacoffee.com/eryksienicki in the browser. The site's download section links the same page.
- Frame labels no longer haunt the next table. Switching tables could leave the previous table's frame labels (post-1 · 1 and friends) floating over the new one, gliding along with the camera. The layer that holds notes and frames is a composited layer, and when a switch emptied it while only its position kept changing, macOS's webview kept showing the layer's old picture. That layer is now dropped and rebuilt for one frame on every table switch.
v0.7 · 2026-08-28 · what the site serves
Rebuilt from 89ab531, at mess.eryk.be/download/mess.zip. New since
v0.6: the smoothness batch (clicks select instantly, drags start
without a stutter, drag-select frames down from 350ms to 21ms, and
selection staying cheap on multi-thousand-photo tables), honest
sidebar counts, recursive folder drops that skip duplicate files by
content, and the 2026-08-26 sorting refinements (filename-order
lightbox and gather, Space previews the selection, shift-click range
select, the reworked compare layouts).
2026-08-27
- Clicking a photo selects instantly. The click's ring flip on the photo's sidebar tile made the browser repaint a big slice of the thumbnail masonry, and the whole frame (selection box included) waited for it. Off-screen sidebar tiles now skip layout and paint entirely (content-visibility), and the sidebar's ring update itself waits one frame - the canvas answers the click first, the sidebar catches up imperceptibly later.
- Grabbing photos no longer stutters at the start. Picking up a selection raises it to the top of the pile, and the sidebar list is ordered by exactly that - so the whole thumbnail masonry rebuilt itself right as the drag began. The sidebar now freezes its view while a gesture is live and catches up once, on release.
- Drag-select without the lag. Several rounds of profiling the live app during real laggy drags (3-5 fps at worst). Round one: thousands of per-photo watchers (every canvas box and sidebar row asking "am I selected?") added up to ~25ms per marquee move; one watcher now flips the highlight directly on the affected elements. Round two, caught by an in-app frame recorder: the input handlers asked the browser for the canvas position and size on every mouse movement, which forced the engine to re-lay-out the whole interface each time (those reads are cached now, refreshed only when the window or sidebar actually resizes, and the marquee runs at most once per screen frame). And the decisive pair: the sweep wrote the selection to the store on every change, and its ring flips forced the image-stuffed sidebar to repaint every frame - a constant ~350ms. The sweep now draws its live highlight on the WebGL photo layer, which redraws per frame anyway, and the store, toolbar, and sidebar learn the selection once, on release. Frame times measured in the live app: 350ms before, 21ms after. The highlight itself is subtle: a faint blue tint, plus a hairline ring only on photos big enough on screen to carry one - zoomed way out, the tint alone marks the catch instead of a wall of blue boxes.
- Sidebar counts stay honest. Each table's photo count in the sidebar now updates with every save instead of freezing at whatever it was when the app started.
- Folder drops: everything inside, each photo once. A dropped folder now brings in every photo anywhere inside it, subfolders included (hidden files and symlinks still skipped), in natural filename order; drops of more than 200 photos ask first, so a stray drop of a whole archive can't flood the table. Recursive trees often hold the same photo several times (roll folders, curated copies) - each distinct file lands once, by content, with a note saying how many duplicates were skipped. And while a big import is still landing, the provisional grid leaves room for portrait photos instead of stacking them on the next row.
2026-08-26
- The lightbox walks in filename order. Left/right arrows follow the filenames (numbers compared by value, so -2 comes before -10), the same order imports land in - not the photos' positions on the table.
- Space previews what you mean. With several photos selected, Space opens the lightbox on just those; with one selected it starts there and walks the whole table; with nothing selected, a tap of Space previews the whole table from the first filename. Holding Space to pan still works - the preview only opens if the hold wasn't used for a pan.
- Shift-click selects the run between. Click one photo, shift-click another: everything between them joins the selection - along a row, down a column, or the whole block in a grid.
- Gather here piles in filename order. The gathered grid reads like an import (alphabetical), not like wherever the photos happened to sit.
- Quieter flag marks. The lightbox's "pick / reject" badge and the compare view's little green/red circles are gone - the highlighted Pick/Reject button already tells the story.
- Compare view: pick your layout, no more dead space. A small switcher above the photos chooses between one row and 2x2 (for four shots). Cells now hug each photo's real width, so portrait shots sit next to each other instead of centered in window-wide columns. In 2x2 the filename and Pick/Reject move beside each photo (left column on the left, right column on the right), giving the photos the full row height.
v0.6 · 2026-08-25 night
New since v0.5: releases are numbered and browsable.
2026-08-25
- What's New. The mess menu opens the changelog inside the app, with each release folding under its version number; the site serves the same log at /changelog (unlinked, direct address only).
- Version numbers. Builds are versioned (this is v0.6); the build script stamps the app from the newest release entry so the download, the About box and this list always agree.
v0.5 · 2026-08-25 evening
Rebuilt from a6b42c5, at mess.eryk.be/download/mess.zip. New since
the afternoon share: a full menu bar (File / View / Help with the
"Show ? on the Table" toggle), window dragging finally works (the
start-dragging permission was never granted), classic traffic-light
placement, the ? pill, demo defaults (flat, 4x), and Gather-here's
flying animation.
2026-08-25
- A full menu bar. File (New Table, Switch Table…, Export…, Copy Slide as Image), View (Fit Table / Selection, Zoom to 100%, Start Demo, Toggle Sidebar / Toolbar) and Help (Keyboard Shortcuts, a "Show ? on the Table" toggle that hides the floating ? pill but keeps the sheet reachable from the menu, and the mess website). The storage items stay in the mess menu.
- A real titlebar. A classic 40px bar across the top with the traffic lights and the table's name in it; grab it anywhere to move the window. The sidebar, toolbar and canvas start below it. Hidden in demo mode.
- The shortcut sheet is easier to find: "Keyboard Shortcuts" in the mess menu (⇧/) and a small ? button in the bottom-right corner, on top of the ? key. Demo has its own section in the sheet, and the window's traffic lights sit in a classic-height titlebar band that is draggable along the whole top edge.
- Demo mode defaults to flat slides at 4× speed; M lifts them into hops, arrows still adjust pace and framing. M has its own line in the cheatsheet now.
v0.4 · 2026-08-25 · what friends and the site had
Rebuilt from ed6f383, served at mess.eryk.be/download/mess.zip (zip
contains mess.app + READ-ME-FIRST.txt). New since the previous share:
Gather-here photos fly into the pile, the demo-mode polish (hops, M,
speed/zoom keys, directional motion trail, fisheye), the lightbox info
panel (I), quieter selection handles, and all of the 2026-08-21 fixes
below.
v0.3 · 2026-08-21 afternoon
Rebuilt from dbe7ad2 (everything below through 2026-08-21). Apple
Silicon only, ad-hoc signed, Desktop/mess-share/mess.zip +
READ-ME-FIRST.txt. Highlights of this share: photos rendered by the
GPU (smooth at every zoom, no more far-out lag, memory under control),
demo mode (D) with hops, motion trail and live controls, the I info
panel in the lightbox, quieter selection (handles on hover, T pins),
sidebar multi-select, boards renamed to tables, and the site rewritten
around the table with a tl;dr.
2026-08-21
- App: file info in the full-screen view. Press I (or the ⓘ button) while looking at a photo and a panel lists what the original file knows: dimensions and size, when it was taken, camera, lens, focal length, aperture, shutter, ISO, colour profile, software, GPS if any, duration and codecs for clips, plus the crop, rotation and mark on the table. Read through macOS Spotlight, so no new dependency. The panel stays open as you browse with the arrows.
- App: the ▶ badge on video clips is back. It had slipped under the new graphics layer. It is now drawn by that layer, at a fixed size whatever the zoom, and disappears on clips too small to carry it. Playing a clip (open it full screen) never changed.
- App: keeper glow is back, and stays on while you move. The first GPU build drew keepers with a thin hard ring that read as a grid of boxes at overview and vanished during scrolling. Keepers now carry a soft halo sized to the photo, drawn by the graphics card, visible at all times.
- App: clicking right after a scroll no longer throws the view back. A click within a fraction of a second after scrolling or zooming made the camera jump to where it was before the scroll. Fixed.
- App: quieter selection. The eight resize handles now appear only while the pointer is over the selected photo (or group), and T pins them on. The hairline outline stays. During a Z flight or a pinch the outline used to scale up into a fat white frame; the selection chrome now hides while the camera is zooming and returns the moment it lands.
- App: photos now render on the graphics card. The table's photos, slide backgrounds, reject dimming and keeper rings are drawn by a WebGL layer instead of hundreds of browser image elements. Nothing changes in how you work: clicking, dragging, marquee, crop, frames, notes, export are all the same. What changes is the ceiling: panning and zooming far out over a 500-photo table, which used to be the slow spot, costs the GPU a couple of milliseconds, and tiny photos stop shimmering thanks to mipmaps. Graphics memory has a hard budget so it cannot creep over a long session.
- App: demo mode. Press D and the table turns into a slideshow: the sidebar, toolbar, selection handles and cursor disappear, and every few seconds the camera flies to another photo, slowly, with the travel-then-dive move. It never picks one of the nearest photos, so each move crosses the table as a hop: the camera lifts off the photo while travelling, higher the farther it goes, and dives back down onto the next one (M switches to flat slides and back). It never crops into a photo. Hold Space to pull back and see the whole table for as long as you like; let go and it carries on. If two or more photos are selected it only cycles through those; otherwise every photo that is not rejected. ←/→ change the pace (half speed to 6×), ↑/↓ zoom in and out on the photos (from showing the table around each one to cropping into it), and a real motion blur follows the camera: a streak along the direction of travel for pans, a radial one for zooms, its length set by the speed that frame, nothing at takeoff and landing, plus a light fisheye warp that grows with speed and flattens as the camera lands. Drawn by the graphics card. Any other key or a click stops it. Nothing is changed on the table.
- App: stops hoarding full-size previews in memory. A profile of the "gets laggier the longer I move around" problem showed the Mac running out of memory mid-session and the browser engine throwing away and rebuilding everything, frame after frame. Two habits caused it: photos that had scrolled off screen kept their 2048px preview decoded (16MB each, for hundreds of photos), and the zoom-in pre-loading from this morning was too eager. Off-screen photos now fall back to the 512px preview, and pre-loading of the big version is limited to the dozen photos that are actually about to need it.
- App: ⌥⇧D opens Safari's Web Inspector (from the ⌥⇧P readout), so a slow stretch can be profiled properly instead of inferred from counters. No effect unless you press it.
- App: ⌥⇧P shows a performance readout and records it. A small box in the corner with frames per second, the worst frame, how many frames ran long, and how often the canvas re-rendered in the last half second. While it is on, every half second is appended as a line to
perf.login the vault folder (table name, zoom, fps, worst frame, long frames, commits, canvas renders, item count, moving or not), with every key press logged in between (not text typed into notes or fields), so you can roam a table and hand over the file. Turning it off shows where the log went. Off by default.
- App: rejected photos never load full resolution on the table. A reject is dimmed and out of the running, so it is now capped at the 512px preview no matter how far you zoom in; the 2048px decodes go only to photos still being judged. Rejecting a photo drops it to the preview at once, un-rejecting brings the sharp version back. The full-screen view is unchanged, so a reject can still be re-judged at full quality.
- "Boards" are now "tables", in the app and on the site. Sidebar header, ⌘K switcher, toolbar (Fit table, Rename table, Whole table export), cheatsheet, Storage and Archived dialogs, the app menu (Archived Tables…), toasts, the empty-state hint, the default name (Untitled table) and the whole-table export filename (
-table.png). Files on disk are unchanged: the folder is stillboards/and the document is stillboard.json, so existing vaults open as before.
- Site: the table is the product, the carousel is an extra. Hero, title, meta descriptions, the "How it works" third step, the features page intro, and the Canvas and Carousels section intros all now describe mess as a fast table for moving and sorting photos, with frames and 1080px export named as an optional tool on top. A new tl;dr section under the hero says the same in four plain paragraphs for someone who has never seen the app - written after a content review found the site never said the word Instagram or defined board, keeper, frame or carousel. CLAUDE.md's one-liner matches.
- App: sharp photos arrive sooner when you zoom in. Before, the higher-resolution version of a photo was only requested once the zoom had fully stopped, so it always popped in a beat late. Now, while you are still zooming in, the app quietly loads and decodes the version the photos on screen are about to need, so the swap at rest comes from memory. Capped at six loads at a time; zooming away drops the leftovers. And the swap itself no longer waits for you to stop: the moment a photo grows past the size its current preview can cover, the sharper version is put on screen while the zoom is still going.
- App: multi-select in the sidebar. Photo rows and tiles follow Finder conventions: click flies to the photo and selects it, ⌘-click adds or removes it from the selection without moving the camera, ⇧-click selects the run from the last clicked photo. Frames and notes accept ⌘-click too.
- Site: keyboard map redesigned. Grouped into Navigate / Culling / Create & edit / Arrange / Boards & files cards, key beside (or over) its meaning, no more orphaned wraps; canvas Z and lightbox Z spelled out separately.
v0.2 · 2026-08-21 morning
Rebuilt from bc7b832 (all of 2026-08-20 below). Apple Silicon only,
ad-hoc signed, Desktop/mess-share/mess.zip + READ-ME-FIRST.txt.
2026-08-20
- App: Z flies the camera, properly. Z zooms to fit: the selection when there is one, the whole board otherwise, and pressing Z again while sitting at the selection fit toggles back out to the full board (the lightbox keeps its own Z, the 1:1 zoom). The flight travels first and dives second: the camera center moves on the fast curve while the zoom holds back on an ease-in-out, so Z glides over the target and then plunges (520ms in, 420ms out, slowed from 260ms per Eryk's ask). And a Z pressed mid-flight now toggles to the other destination instead of restarting the same flight, which used to read as a dead key for a couple of seconds.
- App: flights at gesture smoothness. Measured with synthetic input and window recording on the 502-photo board: gestures held 40fps while Z and Cmd-0 flights dropped to 18fps with 200-400ms stalls. The causes, all fixed: Z first had to mount hundreds of culled offscreen photos (culling now starts at 1000 items, so all of Eryk's boards stay fully mounted); the resolution picker upgraded every photo to its 2048px variant at the keypress (only the dive target upgrades now, and the takeoff commit writes the destination camera, so photos mount at their final preview size straight from the warm cache); flights now strip motion decorations like gestures do and pre-mount their destination before the first frame; and mid-gesture reveal commits over-mount a larger ring, so React re-renders a couple of times per zoom-out instead of every few frames. After: worst flight gap 60-70ms, was 400ms.
- App: quieter selection chrome. Hairline border at 55% opacity with smaller, dimmer resize handles - and below 36px on screen the handles step aside entirely (they used to hide the photo), leaving just the hairline.
- Site: a real window on the homepage. A "Not a mockup" section between the hero animation and the claims: a live capture of the FE4 board (sidebar, toolbar, carousel strip), linking to the showcase. First a still, then an 8 second loop of the real window, re-recorded with the day's polish in frame (travel-then-dive Z flight, broken-white selection, no chop): Z dives into one selected photo, Z again pulls back to the full board. Recorded live via granted Accessibility access (synthetic Z keystrokes during screencapture -v).
- Site: one nav everywhere. Home / Features / Showcase with the active page highlighted; Get updates button removed.
- Site: homepage fix. Versioned asset URLs plus a
_headersfile so the 4 hour edge cache on mess.eryk.be can never pair new HTML with old CSS again. Hero lockup dropped (the header owns the name), brand-noun repetition in the copy toned down.
v0.1 · 2026-08-20
Baseline: rebranded "mess", Apple Silicon only, ad-hoc signed.
Everything up to and including the import ordering work
(f37cd50 Imports sort naturally).