Skip to content

feat(desktop): serve packaged renderer locally - #8101

Open
tarik02 wants to merge 4 commits into
pingdotgg:mainfrom
tarik02:feature/desktop-static-renderer
Open

feat(desktop): serve packaged renderer locally#8101
tarik02 wants to merge 4 commits into
pingdotgg:mainfrom
tarik02:feature/desktop-static-renderer

Conversation

@tarik02

@tarik02 tarik02 commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

What Changed

Packaged desktop builds now serve the bundled renderer directly through t3code://app/ instead of proxying those assets through the local backend HTTP server.

Development builds continue proxying t3code-dev://app/ to Vite. The packaged protocol handler includes path containment checks, SPA fallback, and the existing content security policy.

Backend readiness and window creation are unchanged.

Why

Packaged renderer assets do not need to come from the backend HTTP server. Serving them from the desktop bundle removes that unnecessary dependency while preserving the existing startup and readiness flow.

The renderer already receives explicit backend HTTP and WebSocket endpoints through desktop IPC.

Validation

  • vp test run apps/desktop/src/electron/ElectronProtocol.test.ts apps/desktop/src/app/DesktopEnvironment.test.ts (14 tests passed)
  • vp run --filter @t3tools/desktop typecheck
  • Targeted lint on the changed desktop files

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • No visual UI changes, so screenshots are not applicable
  • No animation or interaction changes, so a video is not applicable

Prepared with GPT-5.6 Codex through T3 Code.


Note

Medium Risk
Touches Electron custom-protocol handling and static file serving, including path containment and CSP. Incorrect sanitization could leak files or weaken renderer isolation.

Overview
Packaged desktop builds now load the UI from local files on t3code://app/ instead of proxying through the backend HTTP server. Dev still proxies t3code-dev://app/ to Vite.

Adds registerDesktopFileProtocol, which serves assets from rendererRootPath (serverRoot/apps/server/dist/client) with SPA fallback to index.html. Requests are limited to host app, GET/HEAD, and paths contained under the renderer root. The existing CSP is still applied.

ElectronProtocol.layer now depends on NodeServices for FileSystem/Path.

Reviewed by Cursor Bugbot for commit 57a5d07. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Serve packaged renderer from local disk in production desktop builds

  • In production, DesktopApp now registers a file protocol that serves renderer assets from environment.rendererRootPath instead of proxying to the backend origin; development behavior is unchanged.
  • Adds rendererRootPath to DesktopEnvironment.Service, computed as path.join(serverRoot, "apps/server/dist/client").
  • Adds registerDesktopFileProtocol, resolveRendererFilePath, and serveRendererFile to ElectronProtocol, serving static files with SPA fallback to index.html, CSP headers, host/method enforcement, and path-traversal rejection.
  • Wires NodeServices.layer into ElectronProtocol.layer so file protocol handlers have FileSystem/Path access.
  • Risk: resolveRendererFilePath in ElectronProtocol.ts rejects malformed or traversal paths by returning null; verify the SPA fallback and content-type handling cover all expected renderer asset types.

Macroscope summarized 57a5d07.

@coderabbitai

coderabbitai Bot commented Aug 24, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: d3c4881a-8d8b-4b0f-860e-1afb6787c0ca

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@tarik02 tarik02 changed the title Feature/desktop static renderer feat(desktop): serve packaged renderer locally Aug 24, 2026
@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Aug 24, 2026

@macroscopeapp macroscopeapp Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Effect service conventions review of the packaged renderer protocol changes. Two findings in apps/desktop/src/electron/ElectronProtocol.ts around dependency acquisition and runtime boundaries; the rest of the diff (service tag/interface additions, error classes, DesktopEnvironment field, DesktopApp wiring) follows the conventions.

Posted via Macroscope — Effect Service Conventions

Comment thread apps/desktop/src/electron/ElectronProtocol.ts Outdated
Comment thread apps/desktop/src/electron/ElectronProtocol.ts Outdated

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit ae5a743. Configure here.

Comment thread apps/desktop/src/app/DesktopApp.ts Outdated
Comment thread apps/desktop/src/app/DesktopApp.ts Outdated
@macroscopeapp

macroscopeapp Bot commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — Production desktop startup now relies on a new Electron local protocol that resolves and serves packaged renderer files, including SPA fallback, filesystem containment, and CSP behavior. This cross-cutting runtime and security-boundary change merits human review.

Not approved because:

  • 1 blocking correctness issue found at or above your repo's Minimum Blocking Severity

Adjust the Minimum Blocking Severity for this repo — including turning it Off — in Settings. You can add or adjust custom eligibility rules. Learn more.

Comment thread apps/desktop/src/window/DesktopWindow.ts Outdated
showConnectingSplash,
handleBackendConfigured: Effect.gen(function* () {
yield* Ref.set(backendReadyRef, true);
yield* createMainIfBackendReady;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Medium window/DesktopWindow.ts:864

handleBackendConfigured and handleBackendReady can concurrently create two main BrowserWindows, leaving one orphaned when the later setMain overwrites it. Both paths call the non-atomic createMainIfBackendReady, which checks for an existing window before createWindow and setMain; serialize this creation or otherwise make it single-flight.

🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/desktop/src/window/DesktopWindow.ts around line 864:

`handleBackendConfigured` and `handleBackendReady` can concurrently create two main `BrowserWindow`s, leaving one orphaned when the later `setMain` overwrites it. Both paths call the non-atomic `createMainIfBackendReady`, which checks for an existing window before `createWindow` and `setMain`; serialize this creation or otherwise make it single-flight.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed in 57a5d07. Only the existing handleBackendReady path creates the window, so this PR no longer adds a competing creation path.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I'm unable to act on this request because you do not have permissions within this repository.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L 100-499 changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant