VaultaMark

Chrome Web Store listing — copy and assets

Drafted in Phase 0, finalized in Phase 13. Every field the dashboard asks for has an answer here, so that submission day is transcription rather than authorship, and so the permission justifications were written while the reasoning was fresh rather than reconstructed months later.

The submission process itself — accounts, secrets, the upload workflow — is in RELEASE §6–§8.

Every field now has an answer, including the one that was blocked. The privacy-policy URL was a hard blocker for as long as the repository was private: the Store requires a publicly reachable one and there was nowhere to serve the finished document from. Settled 2026-08-15 (PLAN.md §2.5, D36) — the repository is public and GitHub Pages serves the policy from main/docs:

https://zyndata.github.io/vaulta-mark/PRIVACY

The same setting had removed three other fields, and all three are restored with it: the support URL, the homepage URL, and the closing “open source” line of the detailed description. They were written out in full below and held back rather than deleted, because a listing that advertises a repository and links to a 404 is worse than one that says nothing — and because holding them back is reversible in a way that rewriting them later is not.

The Pages URL is live only once a release merge lands on main, since that is the branch it serves. Check it resolves before pasting it into the dashboard, not after.


1. Asset checklist

All produced. The images live in docs/store/ and are regenerated by two scripts, so a retake is a command rather than an afternoon:

Asset Spec File
Store icon 128 × 128 PNG, artwork at 96 × 96 with transparent padding, as Google specifies docs/store/icon-128.png
Extension icons 16 / 32 / 48 / 128, shipped in the package public/icons/icon*.png
Screenshots 1280 × 800 PNG, five of them docs/store/screenshot-{1..5}-*.png
Small promo tile 440 × 280 PNG docs/store/promo-440x280.png
Marquee promo tile 1400 × 560 PNG — only needed if the listing is ever considered for featuring not produced; optional
Short description ≤ 132 characters §2 below (129) — rewritten 2026-08-18, still unpublished; reaches the listing only in a package, and 1.2.0 is the one that carries it
Detailed description Leads with the differentiators; states the no-recovery warning; explains both sync tiers §3 below — one bullet edited 2026-08-18, editable in the dashboard without a package
Category Privacy & Security chosen 2026-08-15 — see below
Language English (United States), plus Polish from 1.2.0 §11 — the name never translates, the short description ships in the package, the detailed description is pasted in the dashboard
Privacy policy URL https://zyndata.github.io/vaulta-mark/PRIVACY Pages, from main/docsPRIVACY.md
Single-purpose statement one sentence §4 below
Permission justifications one or two sentences each §5 below
Data-usage disclosures “No data collected” across the board §6 below
Support URL https://github.com/zyndata/vaulta-mark/issues restored 2026-08-15
Homepage URL https://github.com/zyndata/vaulta-mark restored 2026-08-15

The category

Privacy & Security, decided at the dashboard on 2026-08-15. Phase 0 wrote Productivity and carried it to Phase 13 unexamined; it was never a decision, only the obvious label for “a bookmark manager”. The listing that was actually written argues from the other side — the short description is four privacy claims in a row, four of the six differentiators are privacy properties, and §4’s single purpose is a vault. A browsing category is where a person decides what a thing is for, and this one is for keeping bookmarks out of somebody else’s reach.

It also costs nothing to be wrong about: the category is editable on a published listing without a new package. PLAN §9 Phase 0 still names Productivity in its description of what that phase was asked to draft, which is left as written — it is a record of the task, not of the listing.

The icon

A bookmark ribbon with a keyhole cut through it: the two things the extension is, in the order someone reads them — it is a bookmark, and it is locked. The badge is the interface’s own accent blue (--vm-accent, #2f4bc4) run a shade either side of itself, so it has depth at 128 px without becoming a different colour at 16 px.

16 and 32 are drawn without the keyhole’s slot. The slot is 6 units wide out of 128, which at 16 px is three quarters of a pixel and resolves as a grey smudge on the ribbon rather than as a hole. Those sizes keep the round part only. The silhouette is identical at every size, which is the part a person recognises in a toolbar.

The screenshots

# File What it shows
1 screenshot-1-vault.png The vault list: folders, favicons, tags, a selected bookmark whose preview is drawn inline in the detail pane. Light.
2 screenshot-2-add.png The toolbar popup, composed on a branded backdrop — it is 422 px wide and would be a postage stamp in a 1280 × 800 frame.
3 screenshot-3-search.png tag:crypto narrowing the vault, reaching into folders. Light.
4 screenshot-4-sync.png Settings: both tiers, Drive disconnected, the quota bar. Light.
5 screenshot-5-no-recovery.png Setup step 2 — the no-recovery warning, and the phrase you have to type. Dark.

Retaken for 1.2.0: shots 1, 3 and 4. Both sidebar shots gained the Duplicates row, shot 1 gained the Show QR code button in the detail pane, and shot 4 was the one that had to be retaken rather than merely could be: it showed a Locking checkbox reading “Lock when I switch to another app”, which is a sentence the shipped product no longer contains, and it predated the whole Toolbar appearance section. Shots 2 and 5 came back byte-identical. (For 1.1.0 it was 1 and 3, when folder rows gained the pencil tag rows have had since Phase 6.)

That is worth knowing about the capture: it is deterministic, so a rerun that changes a file is telling you the UI changed, and a rerun that changes nothing is not a wasted afternoon. Two things it is not deterministic about, both worth a second run before believing a diff: the favicon warm-up is best-effort over the network, so a flaky run swaps a real icon for Chrome’s generic globe — one run here lost seat61.com and the next brought it back — and until 1.2.0 the script took its language from the operating system, which on a Polish machine meant it did not run at all. Pinned now, the way test/e2e/harness.ts pins it, and for the same reason: these are the English listing’s pictures.

Everything in them is invented. Real, well-known destinations, so the favicons and domains look like a person’s vault rather than a lorem-ipsum one, with titles, folders, tags and notes written for the capture script. No real vault is opened and no URL belongs to anybody, so there is nothing to blur.

Shot 5 deviates from what Phase 0 sketched, which asked for “the unlock screen, plus the no-recovery warning”. Those are two different screens: unlocking shows a password box and nothing else, and the warning lives on the screen where the vault is created. The stated purpose — that the constraint is visible before install — is served by the creation screen and not by the unlock one, so that is what was captured.

Light mode for 1–4 and dark for 5, so both themes appear in the strip.

2. Short description (≤ 132 characters)

Bookmarks Chrome doesn’t know about. No omnibox autocomplete, opens in incognito, encrypted, optional sync via your Google Drive.

129 characters, and this is also the manifest’s extDescription — the same string is the Store’s short description and the toolbar tooltip’s subtitle, so there is one place to change it: public/_locales/en/messages.json.

⚠️ Pending upload since 2026-08-18. The 1.1.0 package went up only as a draft, to prove the automation, and was never submitted — so 1.2.0 is the upload that carries this text. It is not what the published 1.0.0 listing says, and unlike §3 it cannot be fixed in the dashboard — the short description is the manifest’s description, so it reaches the Store only in a new package. The published text is the previous wording, kept here so the two can be told apart:

Password-encrypted bookmarks kept out of Chrome’s bookmarks and omnibox. Opens in incognito. Optional sync via your Google Drive.

RELEASE §4 step 9 is what surfaces this at release time.

Why it stopped leading with “password-encrypted” (2026-08-18)

A competitive survey of the Store found the “encrypted bookmark vault” niche already occupied, by free and open-source extensions with the same cryptography — so the first four words of the old text were the one claim eight other listings also make, spent in the scarcest 132 characters the listing has. What no competitor was found to combine is the three properties this text now leads with: nothing reaches the omnibox (the one competitor with real storage outside chrome.bookmarks does not sync at all), every open is incognito, and sync goes to the user’s own Drive rather than to somebody’s server.

The edit is a reordering, not a new claim. Every fact survives, including “optional” — Drive is opt-in and Chrome sync is the default, so a listing that read synced via your Google Drive flat would be untrue. “Encrypted” survives as the fourth clause rather than the first two words: it is still a category signal and a search term, it is just no longer the differentiator. The opening sentence is the one the detailed description (§3) and the promo tile already open with, so the three now read as one voice.

Length history: the wording settled in PLAN.md §11 said your own Google Drive and was recorded as 131 characters. It was 133, nobody counted it, and the 1.0.0 upload was rejected for it — the limit is a hard 132 and the Store refuses the package rather than truncating the text. scripts/verify-manifest.mjs measures the built locale now, so the next one fails in npm run verify instead of at the upload form. This rewrite is 129 as well; that is a coincidence, not a constraint.

3. Detailed description (submitted 2026-08-16; one bullet amended 2026-08-18)

The field renders plain text. Markdown is not a formatting choice here, it is a bug: **bold** and backticks show up literally, so the structure has to come from capitalised headings, blank lines and plain hyphens. Paste this verbatim — 2,302 characters of 16,000.

Bookmarks Chrome doesn't know about.

VaultaMark keeps your bookmarks in a password-encrypted vault stored completely outside Chrome's bookmark and history systems. Chrome never learns those URLs are bookmarked, so they can never surface in address-bar autocomplete while someone is watching you type.

WHAT MAKES IT DIFFERENT

- Stored outside Chrome's bookmarks. This is the whole point: vaulted URLs cannot autocomplete in the address bar. They still sync across your devices, encrypted.
- Every vaulted link opens in an incognito window. No history, no cache, no trace.
- One-click history cleanup for domains you have vaulted, closing the "but I visited it once" leak that bookmark-only tools miss.
- Link previews captured once, when you save the page, then encrypted. Browsing your vault afterwards makes zero network requests.
- Optional sync through your own Google Drive, using the narrow drive.file scope, so the extension can only see the file it created. There is no VaultaMark server, because there is no VaultaMark company.
- Zero config by default. Chrome sync works immediately, with no sign-in and no extra permissions.

HOW THE ENCRYPTION WORKS

Your master password is stretched with PBKDF2-HMAC-SHA256 (600,000 iterations) into a key that unwraps a random 256-bit vault key. Every title, URL, folder name, tag, note and thumbnail is encrypted with AES-256-GCM before it is stored anywhere. The password is never stored and never transmitted.

THERE IS NO PASSWORD RECOVERY

None. Not by the developer, not by Google, not by anyone. No recovery key exists and no backdoor exists. If you forget your master password, your vault is permanently unreadable. That is the design. Use the built-in encrypted export as your backup.

PRIVACY

No telemetry. No analytics. No error reporting. No accounts. No network requests at all, except to your own Google Drive when you have connected it. This is enforced by automated checks that fail the build, not just promised in a listing.

TWO SYNC TIERS

Chrome sync (default): no setup, roughly 600 bookmarks, no thumbnails.
Google Drive (opt-in): effectively unlimited, with encrypted preview thumbnails.

Open source, GPL-3.0-only: https://github.com/zyndata/vaulta-mark

The closing line is restored (2026-08-15), verbatim as it was drafted and held back while the repository was private. Two things changed on submission day, both of them shortening: em dashes became commas and periods, and the Drive paragraph, which the draft carried twice — once in the feature list and again under “Two sync tiers” — is stated once in each place with the duplication gone. No claim was added. Everything the table below verifies survives word for word, which is why the table still applies to the text above it.

What the draft was competing with is worth recording, because it is the failure mode of leaving copy to submission day: the field had been filled by hand with 368 characters that nobody had proofread, opening “VaultaMark is a extension”.

One sentence was added on 2026-08-18, to the first differentiator: They still sync across your devices, encrypted. Both halves of that were already in the listing — the bullet said the vault lives outside chrome.bookmarks, and two bullets below say it syncs — but they were never joined, and the join is the differentiator. The competitive survey behind §2 found the one competitor with real storage outside chrome.bookmarks does not sync at all, so “outside Chrome, and still synced” is the combination nothing else on the Store offers. It is stated as a property of this extension and never as a comparison: a listing may not make a claim about a named competitor, and this one could not verify such a claim anyway. Nothing else in the text moved, so the verification table below still applies word for word. This field is editable in the dashboard without a package upload — unlike §2, it does not have to wait for a release.

Checked against the shipped 1.0.0 build, claim by claim:

Claim Why it is true
“roughly 600 bookmarks” on Chrome sync Phase 7 measured 1,100 (~100 KB) with a warning at 800. The published figure is deliberately the comfortable one, and it carries no notes — a vault full of notes reaches the quota sooner.
“zero network requests” while browsing INV-4, asserted end to end: test/e2e/journey.spec.ts records and aborts every http(s) request a whole session makes and requires the count to be zero.
“captured when you bookmark it, then encrypted” Once, at add time, by the page’s own connection, under k_thumbs. There is no re-fetch and no timer (ARCHITECTURE §14).
“opens in an incognito window” Every open goes through openVaulted; without incognito access the extension explains rather than opening in a normal window.
“no telemetry … enforced by automated checks that fail the build” npm run verify:invariants — INV-1 to INV-3 and INV-9 run against the real dist/, in CI and locally.
PBKDF2 600,000 / AES-256-GCM / 256-bit key D3, D4; known-answer tested against committed vectors in test/fixtures/.
“no password recovery” No verifier blob and no escrow exists to build one from. Stated at creation behind a typed confirmation.

No sentence above promises a feature that slipped. The one thing deliberately not claimed is a byte-for-byte reproducible build: the zip is deterministic, the bundle is not promised to be — see RELEASE §7. The public specification, which was the second withheld claim, is now simply true and the “open source” closing line carries it.

4. Single-purpose statement

Store, organize, and open bookmarks from a password-encrypted vault that is kept separate from Chrome’s own bookmarks.

Chrome Web Store policy requires one narrow purpose. Every permission below must trace back to this sentence — if one does not, the permission is the thing that is wrong.

5. Permission justifications

Each field has a character limit; keep each to one or two sentences. Copy verbatim from RELEASE §8 — these two tables must stay identical.

Permission Justification
storage Stores the encrypted vault and user settings locally and syncs the encrypted vault across the user’s own Chrome profiles.
activeTab Reads the title and URL of the current tab when the user explicitly saves it, and reads that page’s Open Graph preview image at that moment.
scripting Injects a single script into the current tab, only when the user saves it, to read the page’s Open Graph preview metadata.
contextMenus Adds a “Save to VaultaMark” right-click entry.
alarms Locks the vault automatically after the user’s configured idle timeout.
favicon Displays each bookmark’s site icon from Chrome’s local favicon cache, so no icon request is sent to a third party.
identity (optional) Only when the user enables Google Drive sync: obtains an OAuth token for the drive.file scope so the encrypted vault can be stored in their own Drive.
https://www.googleapis.com/* (optional) Only when the user enables Google Drive sync: uploads and downloads the encrypted vault file.
history (optional) Only when the user runs the history-cleanup tool, enables clearing on lock, or enables quick-close: removes history entries so vaulted URLs stop appearing in address-bar autocomplete.
bookmarks (optional) Only when the user imports existing Chrome bookmarks into the vault, and optionally deletes the originals afterwards at their request.
idle (optional) Only when the user enables locking on system idle.

No host permissions are requested at install time. activeTab is granted by all four save entry points (toolbar button, context menu, keyboard shortcut, popup), which is why preview capture needs no broad host access. If a reviewer asks why an extension that reads page metadata has no host permission, that is the answer.

6. Data-usage disclosures

The dashboard asks about each category. The answer is the same everywhere:

Question Answer
Personally identifiable information Not collected
Health, financial, authentication information Not collected
Personal communications Not collected
Location Not collected
Web history Not collected — the vault is on the user’s device, encrypted with their password; the developer has no access to it and no server exists to receive it
User activity Not collected
Website content Not collected — a page’s title and preview image are read only at the moment the user saves that page, and are stored encrypted on the user’s own device

Three certifications, all true:

The only data transfer that happens at all is the user moving their own encrypted file into their own Google Drive, at their instruction — which is the user’s transfer, not the developer’s.

7. Remote code

Answer: “No, I am not using remote code.”

Every executable byte is in the package. The Content Security Policy is exactly script-src 'self'; object-src 'self'; frame-ancestors 'none', with no unsafe-eval, no unsafe-inline, and no WASM relaxation. The build runs automated scanners (INV-1 / INV-2) that fail if a remote script tag, a remote import(), eval, or new Function appears anywhere in the output. Those scripts are in the repository — a useful thing to point a reviewer at if the question comes back.

8. Likely review questions, and the answers

Prepared in advance, because the review turnaround on a bad answer is a week.

Question Answer
Why scripting with no host permission? Injection happens only into the active tab, only after a user gesture, under activeTab.
Why does a bookmark manager want history? It is optional and requested only when the user runs history cleanup. That feature exists because a URL in history autocompletes in the omnibox, which defeats the extension’s entire purpose.
Why bookmarks? Optional, requested only for importing existing bookmarks. Deleting the originals is a separate, separately confirmed action, never automatic.
Where does the OAuth token go? Nowhere. chrome.identity holds it; it is used against https://www.googleapis.com/ and never persisted by the extension.
Can the developer read user vaults? No. Keys are derived from a password that is never stored or transmitted, and no server exists to receive anything.
What happens if a user forgets the password? The vault is unreadable, permanently. Stated in the listing, at vault creation with a typed acknowledgement, and in onboarding.

9. Submission day, in order

The first upload is manual: the Store API can only update an item, never create one (RELEASE §6.1). Everything after this is the gated workflow_dispatch.

  1. Check the privacy-policy URL resolveshttps://zyndata.github.io/vaulta-mark/PRIVACY, 200 and text/html. It serves from main, so it is only live once the release merge has landed.
  2. Register the developer account ($5, one-time) and complete the publisher profile.
  3. npm run build — the production build, not --mode development. The Store assigns the extension id and a manifest key that disagrees with it breaks the upload, which is exactly why key is emitted for development builds only. Then npm run zip.
  4. Upload the zip by hand. Note the extension id from the dashboard URL — that is CWS_EXTENSION_ID (RELEASE §6.5).
  5. Paste §2, §3, §4 and the §5 justifications. Upload the five screenshots, the 128 × 128 store icon and the 440 × 280 promo tile from docs/store/.
  6. Answer §6 (nothing collected, three certifications) and §7 (no remote code).
  7. Category Privacy & Security, language English (United States).
  8. Submit, then register the extension id against the Drive OAuth client’s Item ID (RELEASE §5.3) — the id changes from the development one, and Drive fails with redirect_uri_mismatch until it is updated.
  9. After review clears, git tag-driven releases take over and §8’s answers are worth rereading only if a review question comes back.

10. Test instructions (Access → Test instructions)

Nothing scoped this field until submission day, and it is the one place where “there is no account” stops being a feature and becomes a problem: the reviewer installs the extension and is met by a password gate with no test credentials to type, because none exist anywhere in the product. Left blank, that is a review question at best. The field is capped at 500 characters; this is 493.

No account or test credentials needed.

1. Click the toolbar icon and create a vault with any password of 10+ characters. There is no recovery, so use a throwaway one.
2. On any http/https page, click "Add this page" in the popup, or use the right-click entry.
3. Click the saved item to open it in incognito. Enable "Allow in Incognito" for the extension first; the popup guides you if not.

Everything stays local and encrypted. No network request unless Drive sync is connected in Settings.

The 10+ characters is MIN_PASSWORD_LENGTH in src/crypto/password.ts — the only hard rule at creation, since the strength meter warns but never refuses. If that constant moves, this text is wrong and nothing will catch it, which is the cost of copy living in a dashboard.

Step 3 exists because it is the step a reviewer will otherwise report as broken: without Allow in Incognito the extension explains rather than opening, and an explanation screen looks like a failure to someone who does not know it is a Chrome-level toggle we cannot set ourselves.


11. Polish (Phase 18)

pl is the second locale VaultaMark ships, and the Store presents a listing per language. Five fields make up that listing; three are translated here and two deliberately are not.

# Field Polish? Where it comes from
1 Extension name No — never translated extName, which is the literal string VaultaMark. §1
2 Short description Yes, §11.1 extDescription in public/_locales/pl/messages.json — a package upload, not a dashboard edit
3 Detailed description Yes, §11.2 pasted into the dashboard under Language → Polish; editable without a package
4 Screenshots No — the English set is used §11.3 records why
5 Small promo tile No — the English set is used same decision as the screenshots

11.1 Short description — 130 characters

Zakładki, o których Chrome nie wie. Bez podpowiedzi w pasku adresu, otwierane w incognito, szyfrowane, opcjonalnie na Twoim Dysku.

130 of the 132 allowed, measured — and measured by scripts/verify-manifest.mjs, which reads every locale in the built package now rather than only en. The Store applies the same limit to each language and rejects the upload rather than truncating, which is how the 1.0.0 package was refused for a 133-character English line.

This line was written to the limit, not translated to it. A faithful rendering of the English — …szyfrowane, opcjonalna synchronizacja przez Twój własny Dysk Google — runs past 150 characters, because Polish inflects and has no short equivalent of “sync”. Every claim in §2 survives the compression, in the same order: nothing reaches the omnibox, opens in incognito, encrypted, optional sync to the user’s own Drive. What went is the word synchronizacja — fifteen characters for a noun that the phrase na Twoim Dysku (“on your Drive”) already implies — and Google, which Dysk capitalised carries in Polish. Opcjonalnie keeps the “optional” that §2 calls load-bearing: Drive is opt-in and Chrome sync is the default, so a line reading synced via your Google Drive flat would be untrue in either language.

11.2 Detailed description

Paste verbatim under Language → Polish. Plain text, same as §3 — Markdown renders literally.

Zakładki, o których Chrome nie wie.

VaultaMark trzyma Twoje zakładki w sejfie zaszyfrowanym hasłem, przechowywanym całkowicie poza systemem zakładek i historii Chrome. Chrome nigdy nie dowiaduje się, że te adresy są w zakładkach, więc nigdy nie mogą pojawić się w podpowiedziach paska adresu, gdy ktoś patrzy, jak piszesz.

CZYM SIĘ RÓŻNI

- Przechowywane poza zakładkami Chrome. O to właśnie chodzi: adresy z sejfu nie mogą trafić do podpowiedzi paska adresu. Nadal synchronizują się między Twoimi urządzeniami, zaszyfrowane.
- Każdy odnośnik z sejfu otwiera się w oknie incognito. Bez historii, bez pamięci podręcznej, bez śladu.
- Czyszczenie historii jednym kliknięciem dla witryn, które masz w sejfie — zamyka lukę „ale raz tam byłem”, której narzędzia zajmujące się samymi zakładkami nie widzą.
- Podglądy odnośników pobierane raz, w chwili zapisania strony, i szyfrowane. Późniejsze przeglądanie sejfu nie wykonuje ani jednego żądania sieciowego.
- Opcjonalna synchronizacja przez Twój własny Dysk Google, w wąskim zakresie drive.file, więc rozszerzenie widzi wyłącznie plik, który samo utworzyło. Nie ma serwera VaultaMark, bo nie ma firmy VaultaMark.
- Zero konfiguracji na start. Synchronizacja Chrome działa od razu, bez logowania i bez dodatkowych uprawnień.

JAK DZIAŁA SZYFROWANIE

Twoje hasło główne jest rozciągane algorytmem PBKDF2-HMAC-SHA256 (600 000 iteracji) do klucza, który odpakowuje losowy 256-bitowy klucz sejfu. Każdy tytuł, adres, nazwa folderu, etykieta, notatka i miniatura są szyfrowane algorytmem AES-256-GCM, zanim gdziekolwiek trafią. Hasło nigdy nie jest przechowywane ani przesyłane.

NIE MA ODZYSKIWANIA HASŁA

Żadnego. Ani przez autora, ani przez Google, ani przez nikogo. Nie istnieje klucz odzyskiwania i nie istnieje tylne wejście. Jeśli zapomnisz hasła głównego, Twój sejf będzie trwale nie do odczytania. Takie jest założenie projektu. Jako kopii zapasowej używaj wbudowanego zaszyfrowanego eksportu.

PRYWATNOŚĆ

Bez telemetrii. Bez analityki. Bez raportowania błędów. Bez kont. Bez żadnych żądań sieciowych poza Twoim własnym Dyskiem Google, gdy go podłączysz. Pilnują tego automatyczne testy, które zatrzymują kompilację, a nie sama obietnica w opisie.

DWA POZIOMY SYNCHRONIZACJI

Synchronizacja Chrome (domyślnie): bez konfiguracji, około 600 zakładek, bez miniatur.
Dysk Google (opcjonalnie): praktycznie bez ograniczeń, z zaszyfrowanymi podglądami stron.

Otwarte źródła, GPL-3.0-only: https://github.com/zyndata/vaulta-mark

Every claim §3’s verification table checks survives word for word; nothing was added and nothing dropped. Two things read differently on purpose:

11.3 Screenshots stay English — the decision, recorded

The five screenshots and the promo tile stay English, and the Polish listing shows them. PLAN Phase 18 asks for the decision either way, so here it is, with what would change it.

A Polish set is cheap to make once: scripts/capture-store-screenshots.mjs is deterministic and would only need a Polish build. What it is not is cheap afterwards — every retake becomes two sets, the fixture titles, folder names and notes in the capture script are English prose that would want translating too, and a set that goes stale in one language only is worse than one honest set. Each shot’s subject is legible without reading a label: a list of bookmarks, a sidebar, a settings panel, a warning behind a phrase you have to type.

Revisit on evidence, not on principle. Two things would change the answer: a third or fourth locale, at which point per-locale capture stops being a special case and becomes a loop; or Store metrics showing the Polish listing converting materially worse than the English one, which is the only measurement that could say the images are costing anything.

11.4 What is not translated, and why