|
1 | | -# TabCommand — Unlisted Chrome Web Store upload guide |
2 | | - |
3 | | -Everything in this `store/` folder is **prepped and ready**. The steps below are |
4 | | -the parts only you can do (they need your Google account and a credit card). |
5 | | - |
6 | | -## What "unlisted" actually means — read first |
7 | | - |
8 | | -- **Unlisted ≠ private or instant.** An unlisted item is simply hidden from Web |
9 | | - Store search and category browsing. Anyone with the **direct link can still |
10 | | - install it**, and it is **not** an internal/whitelist-only channel. |
11 | | -- **Unlisted still goes through Google's review.** Publishing as unlisted does |
12 | | - *not* skip review. First-time review for a new item commonly takes anywhere |
13 | | - from a few hours to a couple of weeks, especially with sensitive permissions |
14 | | - (see the `tabs` / `processes` note below). Plan for a wait; it is not a |
15 | | - same-day private share. |
16 | | -- If you need to hand a build to a handful of people *today* with no review, |
17 | | - use **"Load unpacked"** from `build/` in `chrome://extensions` (Developer |
18 | | - mode on), or zip `build/` and have them load it unpacked. That is the true |
19 | | - instant path; the Web Store is the durable, auto-updating one. |
| 1 | +# TabCommand — Chrome Web Store upload guide (Public listing, v0.16) |
| 2 | + |
| 3 | +Everything in this `store/` folder is **prepped and ready** for a **public** |
| 4 | +listing. The steps below are the parts only you can do — they need your Google |
| 5 | +account and a credit card. |
20 | 6 |
|
21 | 7 | ## One-time requirement: paid developer account |
22 | 8 |
|
23 | | -- Publishing anything to the Chrome Web Store requires a **registered Chrome |
24 | | - Web Store developer account**, which costs a **one-time US $5 fee** (not per |
25 | | - extension, not recurring). |
26 | | -- Register and pay at the **Developer Dashboard**: |
| 9 | +- Publishing to the Chrome Web Store requires a registered developer account, |
| 10 | + which costs a **one-time US $5 fee** (not per extension, not recurring). |
| 11 | +- Register and pay at the Developer Dashboard: |
27 | 12 | https://chrome.google.com/webstore/devconsole |
28 | | -- You will also be asked to verify a contact email and accept the developer |
29 | | - agreement before your first item can be submitted. |
| 13 | +- You'll also verify a contact email and accept the developer agreement before |
| 14 | + your first item can be submitted. |
| 15 | + |
| 16 | +## What "public" means |
| 17 | + |
| 18 | +- The item is **listed** — it appears in Web Store search and category browsing, |
| 19 | + and anyone can find and install it. |
| 20 | +- Expect **review to take longer and be stricter than unlisted**. TabCommand |
| 21 | + requests `tabs`, which Google treats as access to sensitive user data (browsing |
| 22 | + activity), so a permissions/privacy review is likely. First review for a new |
| 23 | + public item commonly runs from a few days to a couple of weeks. |
| 24 | +- If you need to hand the build to someone **today**, don't wait on review: have |
| 25 | + them load `build/` unpacked via `chrome://extensions` → Developer mode → Load |
| 26 | + unpacked. |
30 | 27 |
|
31 | 28 | --- |
32 | 29 |
|
33 | 30 | ## What's already prepared in this folder |
34 | 31 |
|
35 | 32 | | File | What it is | Where it goes in the dashboard | |
36 | 33 | |---|---|---| |
37 | | -| `tabcommand-0.14.zip` | The packaged extension (manifest at the zip root, version **0.14**) | "Package" → Upload new package | |
| 34 | +| `tabcommand-0.16.zip` | The packaged extension (manifest at the zip root, version **0.16**) | Package → Upload new package | |
38 | 35 | | `icon/tabcommand-icon-128.png` | 128×128 store icon | Store listing → Store icon | |
39 | | -| `screenshots/01…05-*.png` | Five 1280×800 screenshots | Store listing → Screenshots | |
40 | | -| `store-listing.md` | Title, summary, full description, permission justifications, privacy answers | Store listing + Privacy tabs | |
| 36 | +| `screenshots/01…05-*.png` | Five 1280×800 screenshots, in upload order (5 is the max allowed) | Store listing → Screenshots | |
| 37 | +| `promo/small-tile-440x280.png` | 440×280 small promo tile — **required to publish** | Store listing → Small promo tile | |
| 38 | +| `promo/marquee-1400x560.png` | 1400×560 marquee tile — optional, needed to be eligible for featuring | Store listing → Marquee promo tile | |
| 39 | +| `store-listing.md` | Title, summary, description, permission justifications, privacy answers | Store listing + Privacy tabs | |
| 40 | +| _(hosted)_ `https://codeyam.com/tabcommand/privacy` | Privacy policy page, in the `codeyam-local` repo | Privacy → Privacy policy URL | |
41 | 41 |
|
42 | 42 | > The `.zip` is gitignored (the repo ignores `*.zip` and `build/`). Regenerate it |
43 | 43 | > any time with the commands at the bottom of this file. |
44 | 44 |
|
45 | 45 | --- |
46 | 46 |
|
| 47 | +## Before you upload: ship the privacy policy page |
| 48 | + |
| 49 | +The Privacy tab requires a **working** privacy policy URL. TabCommand's policy is |
| 50 | +a page on the CodeYam site, added in the `codeyam-local` repo as |
| 51 | +`dashboard/app/routes/tabcommand.privacy.tsx`. **It must be merged and deployed |
| 52 | +to production before you submit**, or Google will hit a 404 and reject. |
| 53 | + |
| 54 | +Confirm this URL loads in a logged-out browser before submitting: |
| 55 | +https://codeyam.com/tabcommand/privacy |
| 56 | + |
| 57 | +--- |
| 58 | + |
47 | 59 | ## Upload steps (you do these) |
48 | 60 |
|
49 | 61 | 1. **Register / sign in** at https://chrome.google.com/webstore/devconsole and |
50 | 62 | pay the one-time $5 fee if you haven't already. |
51 | | -2. Click **"Add new item"** and upload **`tabcommand-0.14.zip`**. |
| 63 | +2. Click **"Add new item"** and upload **`tabcommand-0.16.zip`**. |
52 | 64 | 3. **Store listing** tab: |
53 | 65 | - Item name, Summary, Detailed description → copy from `store-listing.md`. |
54 | 66 | - Store icon → `icon/tabcommand-icon-128.png`. |
55 | | - - Screenshots → upload all five from `screenshots/` (drag to order them). |
56 | | - - Category → Productivity. Language → English (US). |
| 67 | + - Screenshots → upload all five from `screenshots/` in numbered order. |
| 68 | + (Five is the cap; the form will reject a sixth.) |
| 69 | + - Small promo tile → `promo/small-tile-440x280.png`. **This one is required** |
| 70 | + — the listing cannot be submitted without it. |
| 71 | + - Marquee promo tile → `promo/marquee-1400x560.png`. Optional, but without it |
| 72 | + the extension is not eligible for marquee featuring. |
| 73 | + - Category → **Productivity**. Language → **English (US)**. |
57 | 74 | 4. **Privacy** tab: |
58 | 75 | - Single-purpose description → from `store-listing.md`. |
59 | | - - Permission justifications → paste the table rows from `store-listing.md`. |
60 | | - - Data usage → "No data collected" (TabCommand stores everything locally via |
61 | | - `chrome.storage.local`). Certify the policy compliance checkbox. |
| 76 | + - Permission justifications → paste the table rows from `store-listing.md` |
| 77 | + (one per permission — Google rejects blanks here). |
| 78 | + - Privacy policy URL → `https://codeyam.com/tabcommand/privacy` |
| 79 | + (**not** `/privacy` — that's the company policy and it describes data |
| 80 | + collection TabCommand doesn't do) |
| 81 | + - Data usage → **no** data-collection categories checked. Tick all three |
| 82 | + certification checkboxes. |
62 | 83 | 5. **Distribution** tab: |
63 | | - - Visibility → **Unlisted**. |
64 | | -6. Click **Submit for review**. You'll get email when it's approved; the install |
65 | | - link appears on the item's dashboard page. |
| 84 | + - Visibility → **Public**. |
| 85 | + - Regions → All (or narrow if you prefer). |
| 86 | +6. Click **Submit for review**. You'll get email on approval; the public install |
| 87 | + link then appears on the item's dashboard page. |
| 88 | + |
| 89 | +### If review comes back with questions |
| 90 | + |
| 91 | +The most likely question is about `tabs`. The answer: TabCommand reads tab titles |
| 92 | +and URLs **only to display, search, and organize them locally for the user**; it |
| 93 | +reads no page content and transmits nothing. That's already the wording in |
| 94 | +`store-listing.md` and `PRIVACY.md`. |
66 | 95 |
|
67 | 96 | --- |
68 | 97 |
|
69 | 98 | ## Note: the `processes` permission was removed |
70 | 99 |
|
71 | | -- The `processes` permission has been **dropped** from `manifest.json` for this |
72 | | - build. `chrome.processes` is a Dev/Canary-only API and would have drawn a |
73 | | - likely review question on a stable-channel extension. |
| 100 | +- `processes` was dropped from `manifest.json`. `chrome.processes` is a |
| 101 | + Dev/Canary-only API and would have drawn a review question on a stable-channel |
| 102 | + extension. |
74 | 103 | - No functionality is lost on stable Chrome: `service_worker.js` checks |
75 | 104 | `processesApiAvailable()` and falls back to `system.cpu` / `system.memory`, |
76 | | - which is exactly what stable Chrome uses anyway. Verified — all 70 worker/popup |
77 | | - tests pass after removal. |
| 105 | + which is what stable Chrome uses anyway. |
78 | 106 | - The only effect: on Dev/Canary you no longer get the richer per-tab process |
79 | | - breakdown. The Browser Load gauge and Heaviest Tabs panel still work from |
| 107 | + breakdown. The Browser Load gauge and Heaviest Tabs still work from |
80 | 108 | system-level CPU/memory. |
81 | 109 |
|
82 | 110 | --- |
83 | 111 |
|
| 112 | +## What the production build deliberately excludes |
| 113 | + |
| 114 | +`npm run build` strips all codeyam artifacts from the package: |
| 115 | + |
| 116 | +- The isolation harness (`.codeyam/harness/isolate.jsx`) is swapped for a stub |
| 117 | + that renders `<App/>` directly. The harness only does anything when the URL has |
| 118 | + `?isolate=`, which never happens in a packaged extension. |
| 119 | +- With it go `ISOLATION_PROPS` and the `codeyam:components` / |
| 120 | + `codeyam:component-scenarios` manifests — i.e. all **scenario mock data**. |
| 121 | + |
| 122 | +Before this, the published `.zip` contained internal URLs (Notion, Linear, Figma) |
| 123 | +and placeholder favicon links pointing at `google.com/s2/favicons`. Now it doesn't. |
| 124 | +Bundle dropped 351 kB → 338 kB. |
| 125 | + |
| 126 | +Dev is untouched: `npm run dev` still loads the real harness, so `?isolate=` and |
| 127 | +codeyam scenario capture work exactly as before. Set `CODEYAM_KEEP_HARNESS=1` to |
| 128 | +force the harness into a build if you ever need to. |
| 129 | + |
| 130 | +Sanity-check any new package before uploading: |
| 131 | + |
| 132 | +```bash |
| 133 | +unzip -qq store/tabcommand-<version>.zip -d /tmp/zc |
| 134 | +grep -rl "codeyam\|s2/favicons\|notion.so\|fonts.googleapis" /tmp/zc # → no matches |
| 135 | +``` |
| 136 | + |
84 | 137 | ## Regenerate the package (if you change code) |
85 | 138 |
|
86 | 139 | ```bash |
87 | | -# 1. bump the version in manifest.json (Web Store rejects re-used versions) |
| 140 | +# 1. bump the version in manifest.json (the Web Store rejects re-used versions) |
88 | 141 | # 2. rebuild |
89 | 142 | npm run build |
90 | 143 | # 3. repackage — manifest.json must be at the ZIP ROOT |
91 | 144 | cd build && zip -rqX "../store/tabcommand-<version>.zip" . -x ".*" && cd .. |
92 | 145 | ``` |
| 146 | + |
| 147 | +## Regenerate the promo tiles |
| 148 | + |
| 149 | +The tiles are built from `promo/tiles.html` (self-contained: the icon is embedded |
| 150 | +as a base64 data URI, so there are no external assets). Render each element with |
| 151 | +Playwright at `deviceScaleFactor: 2`, then downscale to the exact spec — this is |
| 152 | +sharper than rendering at 1×: |
| 153 | + |
| 154 | +```bash |
| 155 | +# renders #small and #mq from promo/tiles.html, then: |
| 156 | +sips -z 280 440 small@2x.png --out store/promo/small-tile-440x280.png |
| 157 | +sips -z 560 1400 mq@2x.png --out store/promo/marquee-1400x560.png |
| 158 | +``` |
| 159 | + |
| 160 | +Sizes must be **exact** (440×280 / 1400×560); the dashboard rejects anything else. |
| 161 | + |
| 162 | +## Regenerate the screenshots |
| 163 | + |
| 164 | +They're downscaled straight from codeyam scenario captures (2880×1800 → 1280×800, |
| 165 | +same 1.6 aspect ratio, so no cropping): |
| 166 | + |
| 167 | +```bash |
| 168 | +S=.codeyam/scenarios/screenshots |
| 169 | +sips -z 800 1280 "$S/home-open-and-saved-tabs--desktop.png" --out store/screenshots/01-tab-groups.png |
| 170 | +sips -z 800 1280 "$S/search-active-results--desktop.png" --out store/screenshots/02-search-everything.png |
| 171 | +sips -z 800 1280 "$S/home-running-hot--desktop.png" --out store/screenshots/03-browser-load-gauge.png |
| 172 | +sips -z 800 1280 "$S/home-settings-popover-open--desktop.png" --out store/screenshots/04-auto-close-settings.png |
| 173 | +sips -z 800 1280 "$S/history-populated--desktop.png" --out store/screenshots/05-history.png |
| 174 | +``` |
| 175 | + |
| 176 | +Exactly five — the Web Store rejects a sixth. (A dark-mode shot was cut for this.) |
0 commit comments