The docs for Textual (TUI library for Python) build screenshots along with the docs. Technically not really screenshots, they are SVGs, but principle is the same. They never get out of date.
https://github.com/ericfortis/mockaton/tree/main/pixaton-tes...
NoMethodError at /self-updating-screenshots undefined method `name' for nil:NilClass
Ruby title-for: in handle, line 12 Web GET interblah.net/self-updating-screenshots
followed by a very detailed traceback when I try to access the page
Bonus: since you're generating screenshots programmatically anyway, you can generate a pair of each with your app's light/dark theme, and swap them in/out depending on prefers-color-scheme: dark. <picture> elements work in GitHub READMEs, too: https://github.com/CyberShadow/CyDo#readme
For the small casual games I've been vibe coding, I always start from a place where the application has a CLI where it can run headless, rendering to offscreen texture, with a a screenshot command as well as performance instrumentation. It takes no time to include all this, and gives the agent a way to automate the ui and inspect important things. It also lets me trivially have the agent update screenshots.
Not as neat as being part of the build process, but I will now add that.
App stores require screenshots, but generating N images for NUMBER_OF_SCREEN_SIZES times NUMBER_OF_LOCALIZATIONS can be a chore.
In the past I wrote my own scripts for that, today tools like Fastlane[1] help.
I use Fastlane for my logic puzzle game Nonoverse[2], you can see sample screenshots in its App Store page.
I also automated App Preview video recording, complete with multiple scenes. If anyone wants to read more let me know, perhaps this is a good topic for an article.
[2]: https://apps.apple.com/us/app/nonoverse-nonogram-puzzles/id6...
F
Related: Sabotaging projects by overthinking, scope creep, and structural diffing – https://news.ycombinator.com/item?id=47890799
Worked well. Not quite the same as this, but that’s what this reminds me of.
Granted manually updating the screenshots isn't the most laborious task in the world, but the "upload-apk + take-screenshot + transfer-back-to-PC + edit" process is usually barely annoying enough that you end up almost never doing it otherwise (similar to the OP's experience in the closing paragraph).
In some cases it does. Which engine?
I have an offscreen screenshot path, as well as a CLI arg for world pos/camera view vector, and scripted benchmark runs with a simple text-based input format that has rows of named segments of n game ticks length with control inputs per segment. Use that extensively for A/B testing of visuals and performance while working on the game code.
We had such a vibrant indie game scene when Adobe flash was about and since then nothing's really touched that level of ease of development. I think vibe coding is the first tool that actually exceeds it.
> 100% open source under the MIT license
See: https://docs.fastlane.tools/
It doesn’t support App Preview automation, this is something that I had to script myself.
And for those of you: https://XCancel.com/search?q=%23vibejam&src=typed_query
Fortunately, this was not an airborne platform, so failing safely was much simpler than what a true aviation stack or medical stack would need to do.
I think this might be the neatest thing I’ve built in Jelly that nobody will ever notice.
If you’ve ever maintained a help centre or documentation site for a web application, you’ll know the particular misery of screenshots. You write a lovely help article, carefully capture a screenshot of the feature you’re documenting, crop it, maybe add a border and a shadow, upload it, and it looks great. Then you change the UI slightly – tweak a colour, move a button, update some copy – and suddenly every screenshot that includes that element is stale. You know they’re stale. Your users might not notice, but you know, and it gnaws at you.
Or maybe that’s just me.
Either way, I decided to fix it. The help centre in Jelly has a build system where screenshots are captured automatically from the running application, and they update themselves whenever you rebuild.
The help articles are written in Markdown, which gets processed into HTML via Redcarpet and then rendered as ERB views in the Rails app. So far, so ordinary. But scattered through the Markdown are comments like this:
<!-- SCREENSHOT: acme-tools/inbox | element | selector=#inbox-brand-new-section -->

That HTML comment is an instruction to the screenshot system. It says: “go to the inbox page for the Acme Tools demo team, find the element matching #inbox-brand-new-section, and capture a screenshot of it.” The image tag below it is where the result ends up.
Under the hood, it’s a Rake task that fires up a headless Chrome browser via Capybara and Cuprite. It scans every Markdown file for those SCREENSHOT comments, groups them by team (so it only needs to log in once per team), navigates to each URL, and captures the screenshot.
The capture modes are:
And there are a handful of options that handle the fiddly cases:
<!-- SCREENSHOT: nectar-studio/manage/rules | full_page | click=".rule-create-button" wait=200 crop=0,800 -->
That one navigates to the rules page, clicks a button to open a form, waits 200 milliseconds for the animation, then captures a full-page screenshot cropped to a specific region. The click option is the one that really makes it sing – so many features live behind a button press or a popover, and being able to capture those states automatically is wonderful.
There’s also torn – which applies a torn-paper edge effect via a CSS clip-path – and hide, which temporarily hides elements you don’t want in the shot (dev toolbars, cookie banners, that sort of thing).
The whole pipeline runs with just this:
rails manual:build
That captures every screenshot and then builds all the help pages. When I change the UI, I run that command and every screenshot updates to match. No manual cropping, no “oh I forgot to update that one”, no slowly-diverging screenshots that make the help centre look abandoned.
The markdown files live in public/manual/, organised by section – basics, setup, advanced – and the build step processes them into ERB views in app/views/help/, complete with breadcrumbs and section navigation, all generated from the source markdown files.
This also makes it easy to update the help centre at the same time I’m working on the feature; the code and the documentation live together and can be kept in sync within the same PR or even commit.
I put off building this for ages because it seemed like a lot of work for a “nice to have”. It was a fair bit of work, honestly. Handling the edge cases – elements that need scrolling into view, popovers that need clicking, images that need cropping to avoid showing irrelevant content – took longer than the happy path.
But now that it exists, I update the help centre far more often than I used to, because the friction is almost gone. Change the UI, run the build, commit the results. The screenshots are always current, and I never have to open a browser and fumble around with the macOS screenshot tool.