Docs
The hosted product in three steps. The app itself is documented in its README.
1. Start a trial
On the pricing section, start the 30-day trial. Checkout is Stripe. $0 is due today if this is your first Favorites Pro subscription — the trial is one per customer. Cancel before the trial ends and you are never charged.
2. Copy your license key
It arrives by email as soon as checkout finishes, and the thank-you page shows it too. The key is your sync token: store it in a password manager. Manage or cancel the subscription at account.tgwab.us, signing in with the email you used at checkout.
3. Paste it in the app
Open app.favoritespage.us → Settings → Sync → paste the key → Save, on every device.
What this Worker stores
A token:<sha256> → sync_user_id mapping in KV, and a
licence row in D1. It does not store the favorites JSON. See
Privacy.
Self-host the app
The app is MIT: one HTML file (favorites/public/index.html) and a Worker
(favorites/worker.js) that keeps each person's favorites in Workers KV. It fits
Cloudflare's free Workers plan for a few people; KV's free allowance is 1,000 writes a day. The
$3/year subscription is for the hosted instance we run, and your own instance issues its own
tokens. You need a Cloudflare account, wrangler 4 logged in with
wrangler login, and openssl.
-
Clone favoritespage-app and
work in its
favorites/directory. -
In
wrangler.toml, setaccount_idto your own account, and point the[[routes]]pattern at a hostname in your zone, or delete that block to serve from your workers.dev address. -
Run
wrangler kv namespace create favorites-state. Put the id it prints in the[[kv_namespaces]]entry ofwrangler.toml(keepbinding = "SHORTCUTS_KV") and inNAMESPACE_IDat the top ofissue-token.sh. - Run
wrangler deploy. -
Run
./issue-token.sh you, whereyouis a user id of up to 32 lowercase letters, digits, hyphens, or underscores. It prints a new token once and stores only its SHA-256 hash in KV. - Open your instance, go to Settings (⚙) → Sync, paste the token into the License key field, and save. Do the same on each device: the app syncs with the site it was loaded from.