Repository navigation
[Feature]: Let direct/self-hosted web clients discover newer releases #5299
Description
Before submitting
- I searched existing issues and did not find a duplicate.
- I am describing a concrete problem or use case, not just a vague idea.
Area
apps/web
Problem or use case
The direct/self-hosted web app served by t3 serve cannot discover that a newer T3 release exists.
Because the web assets and server come from the same installed package, APP_VERSION and serverVersion always match. resolveVersionMismatch() therefore returns null. The existing update pill is Electron-only, so a long-running headless server can remain on an old nightly indefinitely without any update indication in its directly served web UI.
Observed example:
- direct web client:
0.0.32-nightly.20260730.955 - headless server:
0.0.32-nightly.20260730.955 - current npm
nightlydist-tag:0.0.32-nightly.20260803.986 - result: no warning or update action because client and server match each other
This is easy to miss when the direct Tailscale HTTPS URL is installed as a browser site app and used as the primary UI. The server can support serverSelfUpdate: "respawn", but that capability is only surfaced after version skew already exists.
The hosted channels are a useful workaround: latest.app.t3.codes currently serves stable and nightly.app.t3.codes serves the current nightly. However, they are not equivalent to the direct/self-hosted web app for users who deliberately prefer the direct endpoint, want it to keep working independently of the hosted frontend, or need direct pairing for an HTTP endpoint.
Related but not duplicate:
- Add one-click update for remote environment version drift #3598 added one-click updates after remote version drift already exists.
- [Bug]: Version drift banner says Update server when the macOS client is behind #5253 / fix(web): offer Update client when the app is behind the server #5254 address choosing the correct update direction when client and server differ.
- This request is about release discovery when a direct web client and its server match but are both stale.
Proposed solution
Let direct/self-hosted web clients check for a newer release on their own channel and offer an explicit, user-initiated server update.
A possible flow:
- Detect the channel from the current packaged version (
-nightly.→nightly; stable → the stable/latest dist-tag), or expose the channel explicitly in server config. - On startup/focus, or via a
Check for updatesaction in About, resolve the corresponding published version from trusted release metadata. - Compare it with
APP_VERSIONusing semver. - When a newer version exists and the connected server advertises
respawnorboot-service, showUpdate availableand call the existing server self-update RPC with the exact target version. - After restart, the server serves the matching newer web bundle and the browser reconnects/reloads.
- For servers without self-update capability, show/copy the exact
npx t3@<version>command.
This should not run for Electron, hosted web deployments, development builds, or versions that cannot be mapped safely to a release channel.
No silent installation is requested. The update should remain user initiated so active agent runs are not interrupted.
Why this matters
Headless T3 is explicitly useful as an always-on remote coding server. Direct web access over Tailscale is also an officially supported path. Without release discovery, that combination silently stops receiving security fixes, protocol fixes, and nightly improvements unless another independently updated client happens to connect.
A small update indicator would make the direct web/headless architecture operationally complete without requiring users to run Desktop only as an update detector or build an external watchdog.
Smallest useful scope
Add a manual Check for updates action to About for direct packaged web builds. If a newer version exists, show the exact target version and reuse the existing ServerUpdateAction behavior. Automatic periodic checks can come later.
Alternatives considered
- Use
nightly.app.t3.codes: works and correctly follows the hosted nightly channel, but introduces a hosted frontend dependency and does not cover direct-only/HTTP pairing use cases. - Open T3 Desktop periodically: works as an independent version detector, but defeats the purpose of a browser-first headless setup.
- External cron/watchdog against npm: functional workaround, but every headless operator should not need to build this separately.
- Automatically update the server: rejected because it could interrupt active runs.
Risks or tradeoffs
- Release metadata must be trusted and channel-aware; the UI must never offer a downgrade. Direction-aware semver handling from fix(web): offer Update client when the app is behind the server #5254 is relevant.
- The check should be lightweight and rate-limited.
- A browser-side request to npm/GitHub may have privacy/CORS implications; a server-side check or first-party metadata endpoint may be cleaner.
- Update availability does not guarantee a safe migration during active work, so installation must remain explicit.
Examples or references
- Updating docs: https://github.com/pingdotgg/t3code/blob/main/docs/user/updating.md
- Hosted channel routing/release behavior: https://github.com/pingdotgg/t3code/blob/main/docs/operations/release.md
- Remote one-click server update: Add one-click update for remote environment version drift #3598
- Version-direction bug: [Bug]: Version drift banner says Update server when the macOS client is behind #5253 and fix(web): offer Update client when the app is behind the server #5254
Contribution
- I would be open to helping implement this.
Activity