Repository navigation
App Store screenshots
The <screenshot> URLs in appinfo/info.xml decide which images the Nextcloud App Store shows for a release. How they are written decides whether a new image ever reaches it.
Tip
TL;DR: Point every screenshot at the release tag, https://raw.githubusercontent.com/<owner>/<repo>/v<X.Y.Z>/<path>, once by hand. From then on make version moves the tag along with every bump, and each release shows its own screenshots.
- Why a branch URL stays old
- The tag-pinned form
- How make version keeps it current
- Switching an app over
The App Store does not link a screenshot URL directly. It stores each one as https://usercontent.apps.nextcloud.com/<base64 of the source URL>, and that proxy serves the image with an expiry date in 2038. The cache key is the source URL alone.
A screenshot that points at a branch, https://raw.githubusercontent.com/<owner>/<repo>/main/doc/screenshots/<file>, therefore keeps the same source URL across every release. The proxy fetches it once and never again, so replacing the file on main leaves the old image in the App Store for good.
A URL that names the release tag instead of the branch changes with every release, so the proxy fetches each one once and that one image matches it for good. The App Store replaces the screenshots of an app with those of each uploaded release, so every release brings the screenshots of its own state.
Two forms are recognised, for the <screenshot> URL and its small-thumbnail attribute alike:
<screenshot>https://raw.githubusercontent.com/<owner>/<repo>/v1.4.0/doc/screenshots/settings.png</screenshot>
<screenshot small-thumbnail="https://cdn.jsdelivr.net/gh/<owner>/<repo>@v1.4.0/doc/screenshots/settings-small.png">https://cdn.jsdelivr.net/gh/<owner>/<repo>@v1.4.0/doc/screenshots/settings.png</screenshot>The tag is vX.Y.Z or a pre-release such as vX.Y.Z-rc.1, the tags make tag creates.
The cost of a tag in every URL is that it has to move with each release. make version does that in the bump commit, together with info.xml, composer.json and package.json:
- Every tag-pinned URL inside a
<screenshot>element gets the tag of the new version,v<new version>. - Only URLs into the app's own repository move.
<owner>/<repo>comes from theoriginremote, so a URL into another repository stays as it is. - A URL on a branch stays as it is too. The tag-pinned form is opt-in.
- The new tag is cut from the working tree, so each
<path>has to exist there.make versionwarns about every one that does not. - On a
stableX.Ybranch the same applies, with the version of that line.
The new tag does not exist until make tag pushes it, so the URLs in the release pull request answer 404 until then. The App Store reads them only when the release is published, after the tag. make consistency-audit names such a URL link-pending while its file is in the working tree, and link-dead once it is not (Checkout audit).
Once per app, replace the branch in each screenshot URL by the tag of the current version, the one info.xml carries:
-<screenshot>https://raw.githubusercontent.com/<owner>/<repo>/main/doc/screenshots/settings.png</screenshot>
+<screenshot>https://raw.githubusercontent.com/<owner>/<repo>/v1.3.2/doc/screenshots/settings.png</screenshot>Commit it like any other change. The next make version moves the URLs to the new tag, and the release after that bump is the first whose screenshots the App Store fetches fresh.
© 2026 [ernolf] Raphael Gradenwitz · MIT-licensed · Report an issue
For app developers
- Getting started
- How ncmake understands your app
- Building and packaging
- Bundle analysis
- Build tools
- Checkout audit
- Lint
- Releasing
- Integrity signature
- Translations
- Per-app tuning
- Target reference
- AI assistant
CI workflows
App Store
For app users
Git
Background
Reference