This release completes the @username routing migration, overhauls the sign-up flow with NeoLogin 0.4/0.5 (including a required new NEOLOGIN_SECRET), adds a live /changelog page generated from git history, fixes premium fulfillment on Stripe success redirects, and polishes the help page, busy-button spinners, and reserved-username protection.
Breaking changes
- Sign-up now flows through /signup; NeoLogin bumped to 0.4 with a required new secretThe /join page and /claim bridge have been removed in favour of /signup, which NeoLogin 0.4 auto-registers. NeoLogin 0.4 splits signing keys: NEOLOGIN_KEY remains the public handoff key, but a new NEOLOGIN_SECRET is now required to sign the session cookie (0.2 signed it with the public key, which was forgeable). Deploying without NEOLOGIN_SECRET set will crash the container, and existing sessions are invalidated — users will need to re-authenticate via passkey.
3195b29 f986874
New
- System routes and impersonation words are now reserved and cannot be claimedA new reserved-username list blocks system routes and impersonation terms from being registered as handles. Every page route is asserted reserved in tests, and the changelog route word was added when that page shipped.
87a2a64 d4a7e1d - A /changelog page now shows release notes generated from git historyA new /changelog page SSR-fetches the helleze embed fragment with cursor pagination (Older releases link via X-Helleze-Next), a graceful empty state, and noindex on paged views. Each deploy runs helleze release --detach to turn new commits into entries automatically. A Changelog link (C hotkey) has been added to the shortcuts menu.
d4a7e1d 7629304
Improved
- Welcome page redesigned with a benefits pitch and improved name pickerThe /welcome page now opens with a benefits pitch and a "Snag your handle" intro that hugs the name input. The rdltr.app/@ prefix is corrected throughout, and the /welcome claim flow is unchanged.
3195b29 - Help page restructured with clearer sections, copy buttons, and accurate API examplesThe Help page is split into Extensions, Shortcut, and API sections with NeoLogin-accurate privacy copy and updated terminology. Code blocks now have copy buttons with a green flash on success. The curl example targets the correct origin, prints the HTTP status code, and uses clear placeholders instead of a fake identity. Stripe checkout URLs also use the centralized origin and /@handle.
b852aa7 c0a8d45
Fixed
- Claim and user-page URLs now consistently use the /@username formatThe /api/user/claim endpoint was still redirecting to /username after the @-prefix routing migration, causing 404s on claim. A centralized User.url() method now produces the correct /@name URL everywhere — API, views, shortcuts, and feed. Bare /name requests 302-redirect to /@name so existing links keep working, and stale /~/ robots.txt rules have been updated.
7588cf5 87a2a64 - NEOLOGIN_* secrets are now forwarded to the production containerNEOLOGIN_URL, NEOLOGIN_KEY, and NEOLOGIN_SECRET were missing from Kamal's env.secret list, causing the container to crash on boot. They are now included.
f986874 - Premium is now granted immediately on Stripe success redirect, not just via webhookPreviously the success redirect only flashed a message and waited for the async webhook to set premium status, so without webhook delivery (e.g. in local dev) the owner bounced back to "Payment due". The success page now verifies the session's paid status directly and upgrades the account immediately via a shared idempotent fulfill() that the webhook also calls as a backstop.
745a262 - Busy-button spinner is now correctly centered and shown on Pay and lock buttonsPico's higher-specificity margin-inline-end was knocking the aria-busy spinner off-center; it is now positioned with top/left + transform. The spinner also hides icon children (img/svg) via visibility so it cleanly replaces icons without resizing the button. The Pay button and the non-premium lock button both show the spinner while redirecting.
0ddab7f 0fc6b62