Play store listing copy
This document is the only copy of the listing text. The Console is where it is pasted, not where it lives — a value that exists only in a web form cannot be reviewed, translated as a set, or recovered when someone edits it by accident.
Three scripts read this file, so its headings are load-bearing:
| Script | Reads |
|---|---|
scripts/play-whatsnew.py |
the ## Release notes section, rendering every locale’s note in the one format the Console’s textarea accepts |
scripts/notes-gate.py |
the newest ### x.y.z heading, refusing a merge where it does not match versionName |
scripts/play-metadata.py |
the whole thing, generating the fastlane/metadata/ tree the publish workflow uploads |
The gate exists because of a real failure. A release shipped to production carrying the previous version’s release notes:
versionNamehad been bumped and the notes had not, nothing compared the two, and Play does not allow release notes to be edited on a live release. The correction had to wait for the next upload. Renaming a heading is cheaper.
Fields shared across both locales
| Field | Value |
|---|---|
| Privacy policy URL | https://maksforge.com/darts-scorer/privacy-policy — maksforge.com serves docs/ for nothing, which is why this repo has a docs/_config.yml. Play requires a hosted policy and an offline app has no server of its own |
| App icon (512²) | art/play-icon-512.png — generated by art/make-launcher-icon.py |
| Feature graphic (1024×500) | art/play-feature-graphic.png, plus art/play-feature-graphic-<tag>.png per translated listing — generated by art/make-feature-graphic.py (COPY). scripts/play-metadata.py uploads each with the listing, so a re-render goes up with the next promotion that has update_listing on; nothing to drop into the Console by hand |
| Phone screenshots | art/play-screenshots/ — captured by scripts/screenshots.py, padded by art/pad-screenshot.py. Upload in filename order; the numeric prefix is the upload position |
| App category | _ |
| Contact email | darts-scorer.support@maksforge.com — the per-app support address, set in Store settings, and the one ui/support/SupportConfig.kt compiles in. Not the account-level developer email, which is public on every app you own |
| Website | https://maksforge.com/darts-scorer/ — index.md. A release that adds something a user can see moves it in the same PR as the full description below |
English (default listing language)
Play counts characters, not words, and rejects at the limit rather than truncating. Keep the count in the heading and update it when you edit: it is the only warning you get before the Console refuses a paste.
App name — 0/30
The app name is not translated, in any locale. app_name is translatable="false" for the same
reason, so every listing carries the same name.
Darts Scorer
Short description — 0/80
The line that appears under the name in search results, and the most-read text in the listing.
Full description — 0/4000
No health or safety claims, here or on any page the listing links to — Play’s enforcement reads a linked page as part of the listing. Say what the app cannot do instead.
The shape the apps built from this template converged on, with headings in capitals because Play
renders no markup. The block below is what play-metadata.py uploads, so the outline stays out of it:
- One or two sentences: the problem, and what the app does about it.
HOW IT WORKS— what happens, in the order the user meets it.FREE, AND NOTHING LEAVES YOUR PHONE— no ads, no account, no server; “it does not request the internet permission” only whileaab-permissions.pyforbidsINTERNET; what it stores.WHAT IT CANNOT DO— the honest limits, and what a phone or the platform can stop.PERMISSIONS— one line each, in the user’s words.- A last line pointing at the source:
github.com/maks-sredniawa/darts-scorer.
Polish
App name — 0/30
Darts Scorer
Short description — 0/80
Full description — 0/4000
Release notes (Play’s “What’s new”, 500 chars per locale)
Don’t paste these by hand. The Console takes all languages in one textarea, tagged by locale,
and scripts/play-whatsnew.py renders exactly that from the blocks below:
python3 scripts/play-whatsnew.py # newest version here, to stdout
python3 scripts/play-whatsnew.py --version 0.2.0 # a named one
It reformats and never retypes, so this document stays the only copy. It exits non-zero if a note is over 500 characters, or if a language the app ships has no note at all — both of which Play accepts in silence and a user then reads.
The label above each block is parsed, not decorative: **<Language>** — <n>/500: on a
line of its own, with the fenced note under it. The count is what keeps a note from reaching Play
truncated, and play-whatsnew.py refuses a language the app ships and this section does not.
Write these about what changed for the person reading them. A schema migration is not a release note; the feature it made possible is. A release where nothing user-visible changed still needs a heading — rename it and say so in one line, so the decision is deliberate rather than made by default.
0.2.0 — the first build
0.1.0 was never tagged or released, so 0.2.0 is the first build anyone installs; the new launcher icon is not news to them, and the note stays “the first release”.
English — 18/500:
The first release.
Polish — 18/500:
Pierwsze wydanie.