Bundle frontend in desktop app and add server connection picker#434
Bundle frontend in desktop app and add server connection picker#434skulldogged wants to merge 3 commits into
Conversation
WalkthroughAdds Tauri desktop instance management: new backend utilities for environment and URL handling, a provider hook to manage desktop instance state, UI components and dialog to configure the instance, App integration, and replacement of hard-coded paths with assetUrl/getApiBaseUrl across several routes. Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes 🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
📝 Coding Plan
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. Comment Tip CodeRabbit can generate a title for your PR based on the changes.Add |
There was a problem hiding this comment.
Pull request overview
Updates the Tauri desktop packaging to bundle the Vite-built frontend and introduces a desktop-only “server connection picker” so the UI can point at a user-selected Spacebot backend, while keeping the web UI same-origin.
Changes:
- Added desktop backend URL detection/normalization + localStorage persistence, and routed API/asset URL construction through this layer.
- Introduced a desktop-only provider/dialog + first-run gate to prompt for/select the backend server.
- Adjusted desktop build/dev flow (Tauri config hooks) and removed the WKWebView zoom hack in favor of full-height layout constraints.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| interface/src/ui/style/style.scss | Makes html/body/#root full-height and hides body overflow to avoid viewport issues on desktop. |
| interface/src/routes/AgentWorkers.tsx | Switches hardcoded /api and embed asset paths to backend-aware URL helpers. |
| interface/src/main.tsx | Removes Tauri-only body.style.zoom hack. |
| interface/src/lib/backend.ts | Adds desktop detection, instance URL storage/normalization, and getApiBaseUrl() / assetUrl() helpers. |
| interface/src/hooks/useDesktopInstance.tsx | Adds React context/provider for desktop instance URL and dialog state. |
| interface/src/components/TopBar.tsx | Adds desktop-only “change server” button showing current host label. |
| interface/src/components/Sidebar.tsx | Removes stray whitespace line (no functional change). |
| interface/src/components/DesktopInstanceDialog.tsx | Adds connect gate (first run) and change-server dialog UI. |
| interface/src/components/ConnectionBanner.tsx | Desktop-only link to open the change-server dialog when disconnected. |
| interface/src/api/client.ts | Switches BASE_PATH/IS_TAURI/API base to read from backend.ts. |
| interface/src/App.tsx | Wraps app in desktop instance provider and gates router until configured on desktop. |
| desktop/src-tauri/tauri.conf.json | Bundles interface/dist and adds pre-dev / pre-build commands to build/run the frontend. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
interface/src/api/client.ts (1)
3-5: Avoid freezing the backend URL at module import.
API_BASEis captured once here, butinterface/src/routes/AgentWorkers.tsxnow resolvesgetApiBaseUrl()at runtime. That splits the app between cached and live backend resolution. A shared accessor would keep every request path on the same source of truth.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@interface/src/api/client.ts` around lines 3 - 5, API_BASE is captured at module import causing stale backend URLs; replace the frozen const with a runtime accessor: remove the const API_BASE and export a function (e.g., getApiBase or getApiBaseRuntime) that returns getApiBaseUrl() when called, and update all callers to call that accessor instead of referencing API_BASE; keep BASE_PATH and IS_TAURI as-is but ensure any code that previously imported API_BASE now uses the new getApiBase() so backend resolution is consistent at runtime.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@interface/src/components/DesktopInstanceDialog.tsx`:
- Around line 41-50: The Input in DesktopInstanceDialog (id
"desktop-instance-url") lacks an accessible label and the error text isn't
associated with the field; add a visible <label> or an aria-label on the Input
(e.g., aria-label="Server URL") and mark invalid state with
aria-invalid={!!error}, and give the error <p> an id like
"desktop-instance-url-error" and set Input's aria-describedby to that id when
error exists so screen readers receive both the field name and the error
message.
In `@interface/src/lib/backend.ts`:
- Around line 12-25: normalizeDesktopInstanceUrl currently strips the full path,
search and hash and returns only url.origin which breaks reverse-proxied/subpath
deployments; change the logic in normalizeDesktopInstanceUrl to preserve the
base pathname (but strip trailing slash and clear search/hash), e.g. keep
url.pathname (treat "/" as empty), remove any trailing "/" from the pathname,
then return url.origin + pathname (so a value like "https://host/spacebot"
becomes "https://host/spacebot"); also apply the same change to the other
URL-normalization occurrence mentioned in the review to ensure consistent
behavior.
---
Nitpick comments:
In `@interface/src/api/client.ts`:
- Around line 3-5: API_BASE is captured at module import causing stale backend
URLs; replace the frozen const with a runtime accessor: remove the const
API_BASE and export a function (e.g., getApiBase or getApiBaseRuntime) that
returns getApiBaseUrl() when called, and update all callers to call that
accessor instead of referencing API_BASE; keep BASE_PATH and IS_TAURI as-is but
ensure any code that previously imported API_BASE now uses the new getApiBase()
so backend resolution is consistent at runtime.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: e68ec4ef-fa64-456f-baef-48dfd462e095
⛔ Files ignored due to path filters (1)
desktop/src-tauri/tauri.conf.jsonis excluded by!**/*.json
📒 Files selected for processing (11)
interface/src/App.tsxinterface/src/api/client.tsinterface/src/components/ConnectionBanner.tsxinterface/src/components/DesktopInstanceDialog.tsxinterface/src/components/Sidebar.tsxinterface/src/components/TopBar.tsxinterface/src/hooks/useDesktopInstance.tsxinterface/src/lib/backend.tsinterface/src/main.tsxinterface/src/routes/AgentWorkers.tsxinterface/src/ui/style/style.scss
💤 Files with no reviewable changes (2)
- interface/src/main.tsx
- interface/src/components/Sidebar.tsx
…, a11y, bun --cwd
There was a problem hiding this comment.
🧹 Nitpick comments (1)
interface/src/components/ConnectionBanner.tsx (1)
25-31: Add an explicit accessible name for the server-change button.Using only
currentLabelas button text can make the action unclear to screen readers.♿ Optional accessibility tweak
{isDesktop ? ( <button type="button" onClick={openDialog} + aria-label={`Change server (current: ${currentLabel})`} className="shrink-0 text-xs text-current underline underline-offset-4 opacity-90 hover:opacity-100" > {currentLabel} </button> ) : null}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@interface/src/components/ConnectionBanner.tsx` around lines 25 - 31, The button rendering in ConnectionBanner uses only {currentLabel} which can be ambiguous to screen readers; update the <button> (the one with onClick={openDialog} and className containing "shrink-0 text-xs...") to include an explicit accessible name by adding an aria-label (e.g., aria-label={`Change server, currently ${currentLabel}`}) or by including visually hidden descriptive text inside the button; ensure the label mentions the action ("change server" or similar) and references currentLabel so the screen reader hears both the action and current selection.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@interface/src/components/ConnectionBanner.tsx`:
- Around line 25-31: The button rendering in ConnectionBanner uses only
{currentLabel} which can be ambiguous to screen readers; update the <button>
(the one with onClick={openDialog} and className containing "shrink-0
text-xs...") to include an explicit accessible name by adding an aria-label
(e.g., aria-label={`Change server, currently ${currentLabel}`}) or by including
visually hidden descriptive text inside the button; ensure the label mentions
the action ("change server" or similar) and references currentLabel so the
screen reader hears both the action and current selection.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 679708a9-bed6-4ed6-af94-6172d76b0c29
⛔ Files ignored due to path filters (1)
desktop/src-tauri/tauri.conf.jsonis excluded by!**/*.json
📒 Files selected for processing (3)
interface/src/components/ConnectionBanner.tsxinterface/src/components/DesktopInstanceDialog.tsxinterface/src/lib/backend.ts
🚧 Files skipped from review as they are similar to previous changes (2)
- interface/src/components/DesktopInstanceDialog.tsx
- interface/src/lib/backend.ts
|
Hey @skulldogged — thank you for putting this together. The local frontend bundling, the connection picker, and the accessibility improvements were all well thought out and cleanly implemented. Since this was opened, the desktop app work landed on A few things from your PR that directly influenced or improved the final result:
Going to close this out since the functionality is covered, but your contribution is appreciated and parts of it clearly shaped what shipped. Hope to see more PRs from you! |
Summary
http://127.0.0.1:19898), saved to localStoragebody.style.zoom = "1.1"Tauri hack; replaced with properhtml/body/#rootheight constraintsbeforeDevCommandto Tauri config sobun run tauri:devstarts the Vite dev server automaticallyChanges
interface/src/lib/backend.ts— desktop detection, URL normalization, localStorage persistence,getApiBaseUrl()/assetUrl()interface/src/hooks/useDesktopInstance.tsx— React context for saved backend URL and change-server dialog stateinterface/src/components/DesktopInstanceDialog.tsx— connect gate (first run) and change-server dialoginterface/src/api/client.ts—API_BASE/BASE_PATH/IS_TAURInow read frombackend.tsinterface/src/App.tsx— gates onhasConfiguredInstancebefore rendering router on desktopinterface/src/components/TopBar.tsx— change-server button showing current host (desktop only)interface/src/components/ConnectionBanner.tsx— shows backend URL when disconnected (desktop only)interface/src/routes/AgentWorkers.tsx— hardcoded/api/paths replaced withgetApiBaseUrl()/assetUrl()interface/src/main.tsx— removedzoom: 1.1desktop hackinterface/src/ui/style/style.scss— full-height constraint on html/body/#root, hidden body overflowdesktop/src-tauri/tauri.conf.json—frontendDistpoints tointerface/dist, addedbeforeDevCommandandbeforeBuildCommandTest plan
./scripts/preflight.sh— passcargo clippy --all-targets— passcargo fmt --all -- --check— passbun run build(interface) — passNote
Desktop frontend bundling and server connection picker now integrated. The desktop app loads the UI locally and connects to a configurable Spacebot server via URL, with UI controls to switch servers and view connection status.
Written by Tembo for commit 7c61ebf. This will update automatically on new commits.