Feature request: images-focused page with an image-board-style layout
Feature request from Ilya, recorded by ChatGPT.
Add an images-focused page to ZenMemes, with an image-board-style layout. Make attached images the main thing people browse, rather than small thumbnails beside a text-first feed.
Proposed starting scope:
Show image posts in a visual grid that works on mobile and desktop.
Let each image lead to its post and discussion.
Include a short caption or title and reply count so the conversation is discoverable.
Keep image proportions recognizable within sensible layout limits and serve appropriately sized previews.
The core request is a dedicated visual browsing page. Exact layout, ordering, filters, and whether to include images from replies remain design decisions.
Most of the plumbing for this already exists in v3, so here's what I found reading the code, plus the two things that would need new work.
What's there: each post carries at most one Image-v1 line, and that line already records the width, height and a description. So a grid can reserve the right aspect ratio for every tile before anything loads, and the description can be the alt text. (The current list thumbnails use alt="", which a gallery shouldn't copy.) ListThumbnails::forPosts() already turns a page of post IDs into image entries in one query, and it works the same for replies as for thread roots. Including reply images costs nothing extra; each tile would just link to /posts/<id> instead of the thread.
What's missing:
Real previews. Today the board and Recent thumbnails point straight at /images/<sha256>.<ext>, which is the original upload (up to 2048 px a side, 5 MiB). Fine for a few rows, but a grid of 40 would pull 40 originals. I'd generate a small preview per hash with GD (already loaded for upload validation) and cache it outside the git repo. It's derived from the hash, so it can always be rebuilt and never needs signing.
A way to find image posts without scanning bodies. forPosts() starts from IDs the page already has. A gallery has to ask "newest posts with an image," and right now that means instr(body, 'Image-v1:') across the whole posts table. That's fine at today's size. Longer term, a has_image column (or a small images table) filled in at import time would keep it cheap.
For a first version I'd skip filters: newest first, roots and replies mixed, title or first line plus reply count under each tile, and keep it behind a feature flag the way list thumbnails are. Ordering by likes could come later.
Built it. There's now a Gallery page at /gallery/, next to Recent in the nav: every post with an attached image shows up as a tile, newest first, replies included. Tiles keep each image's shape (very tall or very wide ones are cropped a bit), show the thread title and reply count, and open the post in its thread.
Images load as small previews, at most 480 px on the long side and generated once per image, so a page of 48 tiles doesn't pull full-size uploads. It can be switched off with the new "Image gallery" setting in Feature flags.
Two things you might want different: reply images are mixed in with thread images, and Gallery takes a spot in the main nav, which is easy to move if the navbar gets rearranged.