Skip to content

Conversation

@webdevcody
Copy link
Collaborator

@webdevcody webdevcody commented Jan 7, 2026

  • Introduced a new docker-compose.dev-server.yml for running the backend API in a container, enabling local Electron to connect to it.
  • Updated dev.mjs to include a new option for launching the Docker server container.
  • Enhanced the UI application to support external server mode, allowing session-based authentication and adjusting routing logic accordingly.
  • Added utility functions to check and cache the external server mode status for improved performance.
  • Updated various components to handle authentication and routing based on the server mode.

Summary by CodeRabbit

  • New Features

    • Added support for external API server mode, enabling the application to connect to containerized backend servers while maintaining full functionality.
    • Enhanced authentication flow to support session-based authentication in external server deployments.
  • Chores

    • Added Docker development configuration for streamlined local testing with containerized services.

✏️ Tip: You can customize this high-level summary in your review settings.

- Introduced a new `docker-compose.dev-server.yml` for running the backend API in a container, enabling local Electron to connect to it.
- Updated `dev.mjs` to include a new option for launching the Docker server container.
- Enhanced the UI application to support external server mode, allowing session-based authentication and adjusting routing logic accordingly.
- Added utility functions to check and cache the external server mode status for improved performance.
- Updated various components to handle authentication and routing based on the server mode.
@coderabbitai
Copy link

coderabbitai bot commented Jan 7, 2026

📝 Walkthrough

Walkthrough

This pull request introduces external Docker server mode support to the Electron application, enabling it to connect to a backend API running in a Docker container instead of using an embedded server. The changes include detection mechanisms via IPC, conditional control flow to skip embedded server startup, modified authentication for session-based auth, and developer tooling to run the Docker container locally.

Changes

Cohort / File(s) Summary
External Server Mode Detection
apps/ui/src/lib/http-api-client.ts, apps/ui/src/preload.ts
New async and sync functions to detect and cache external server mode; exposes checkExternalServerMode() and isExternalServerMode() for querying Docker API availability.
Main Process & IPC Handlers
apps/ui/src/main.ts
Introduces SKIP_EMBEDDED_SERVER logic to conditionally skip embedded server startup and API key generation; adds IPC handlers auth:getApiKey and auth:isExternalServerMode; waits for external server readiness before proceeding.
Authentication & Routing
apps/ui/src/routes/__root.tsx
Updates initAuth to check external server mode and adjust routing guards; treats external mode like web mode for session-based auth; redirects conditioned on needsSessionAuth instead of just isElectronMode.
Development Tooling
dev.mjs, scripts/launcher-utils.mjs
Adds new menu option (4) for Electron + Docker API mode; implements launchDockerDevServerContainer() to orchestrate Docker Compose with live-reload, health checks, and coordinated Electron launch.
Docker Configuration
docker-compose.dev-server.yml
New development-only Compose file for backend server; exposes port 3008, mounts source for live updates, includes health checks, and runs npm setup/dev tasks as non-root.

Sequence Diagram(s)

sequenceDiagram
    participant Electron Main
    participant Renderer
    participant HTTP Client
    participant External Server
    participant IPC Bridge

    Electron Main->>Electron Main: Check SKIP_EMBEDDED_SERVER
    alt External Server Mode
        Electron Main->>External Server: Poll /api/health
        External Server-->>Electron Main: 503 (not ready)
        Note over Electron Main: Retry with backoff
        External Server-->>Electron Main: 200 (healthy)
        
        Electron Main->>Renderer: Create window<br/>Set PORT/VITE_SERVER_URL env vars
        
        Renderer->>IPC Bridge: window.electronAPI.isExternalServerMode()
        IPC Bridge->>Electron Main: ipcMain.invoke('auth:isExternalServerMode')
        Electron Main-->>IPC Bridge: true
        IPC Bridge-->>Renderer: Promise resolves true
        
        Renderer->>HTTP Client: checkExternalServerMode()
        HTTP Client->>IPC Bridge: window.electronAPI.isExternalServerMode()
        IPC Bridge-->>HTTP Client: true
        HTTP Client->>HTTP Client: Cache result
        HTTP Client-->>Renderer: true
        
        Renderer->>Renderer: Set needsSessionAuth = true
        Renderer->>Renderer: Skip to /login<br/>(session-based auth)
        
        Renderer->>External Server: API requests to localhost:3008
        External Server-->>Renderer: Responses
    else Default Mode (Embedded Server)
        Electron Main->>Electron Main: Generate/Load API key
        Electron Main->>Electron Main: Find available port
        Electron Main->>Electron Main: Start embedded server
        Electron Main->>Renderer: Create window
        
        Renderer->>Renderer: Set needsSessionAuth = false
        Renderer->>Renderer: Assume API-key auth ready
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

Suggested labels

Enhancement, Testers-Requested

Poem

🐰 A Docker dream takes flight today,
External servers now have their way,
No embedded code within the shell,
Just IPC bridges weaving spells,
The Electron hops to distant streams! 🌊

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the primary change: adding external server mode support with Docker integration, which aligns with the main objectives of the PR.
Docstring Coverage ✅ Passed Docstring coverage is 80.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings

📜 Recent review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c713cef and 66557b2.

📒 Files selected for processing (7)
  • apps/ui/src/lib/http-api-client.ts
  • apps/ui/src/main.ts
  • apps/ui/src/preload.ts
  • apps/ui/src/routes/__root.tsx
  • dev.mjs
  • docker-compose.dev-server.yml
  • scripts/launcher-utils.mjs
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Always import from shared packages (@automaker/*), never from old relative paths

Files:

  • apps/ui/src/preload.ts
  • apps/ui/src/main.ts
  • apps/ui/src/lib/http-api-client.ts
  • apps/ui/src/routes/__root.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Use resolveModelString() from @automaker/model-resolver to convert model aliases (haiku, sonnet, opus) to full model names

Files:

  • apps/ui/src/preload.ts
  • apps/ui/src/main.ts
  • apps/ui/src/lib/http-api-client.ts
  • apps/ui/src/routes/__root.tsx
🧠 Learnings (1)
📚 Learning: 2025-12-30T01:02:07.114Z
Learnt from: illia1f
Repo: AutoMaker-Org/automaker PR: 324
File: apps/ui/src/components/views/board-view/components/kanban-card/kanban-card.tsx:122-131
Timestamp: 2025-12-30T01:02:07.114Z
Learning: Tailwind CSS v4 uses postfix syntax for the important modifier: append ! at the end of the utility class (e.g., backdrop-blur-[0px]! or hover:bg-red-500!). The older v3 style used a prefix (!) at the start (e.g., !backdrop-blur-[0px]); prefer the postfix form for consistency across TSX files.

Applied to files:

  • apps/ui/src/routes/__root.tsx
🧬 Code graph analysis (4)
apps/ui/src/main.ts (2)
apps/ui/src/lib/http-api-client.ts (1)
  • isExternalServerMode (165-165)
apps/server/src/services/dev-server-service.ts (1)
  • findAvailablePort (106-131)
apps/ui/src/routes/__root.tsx (3)
apps/ui/src/lib/http-api-client.ts (3)
  • checkExternalServerMode (141-160)
  • isElectronMode (124-132)
  • isExternalServerMode (165-165)
apps/ui/src/store/auth-store.ts (1)
  • useAuthStore (25-29)
apps/ui/src/components/ui/loading-state.tsx (1)
  • LoadingState (10-17)
dev.mjs (1)
scripts/launcher-utils.mjs (4)
  • choice (387-389)
  • prompt (337-349)
  • launchDockerDevServerContainer (897-1002)
  • log (88-90)
scripts/launcher-utils.mjs (1)
dev.mjs (1)
  • processes (40-45)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: e2e
🔇 Additional comments (14)
dev.mjs (1)

30-30: LGTM! Clean integration of the new Docker server mode option.

The new development option follows the established pattern: the import, menu prompt update, and choice branch are all consistent with the existing options. The launchDockerDevServerContainer function is called with the same signature as launchDockerDevContainers.

Also applies to: 100-100, 176-181

apps/ui/src/preload.ts (1)

28-30: LGTM! Properly exposes the external server mode check.

The new IPC method follows the established pattern and correctly matches the handler registered in main.ts. The return type is appropriate for the boolean check.

apps/ui/src/lib/http-api-client.ts (1)

134-165: LGTM! Well-implemented caching for external server mode detection.

The caching pattern is consistent with other cached values in this module (e.g., cachedApiKey). Key points:

  • Early return on cache hit avoids redundant IPC calls
  • Proper null/undefined checks before accessing window.electronAPI
  • Graceful fallback to false on errors
  • The sync accessor correctly returns null when not yet initialized, allowing callers to distinguish "not checked" from "checked and false"
apps/ui/src/routes/__root.tsx (4)

21-22: Imports are correctly sourced from the shared package path.

The imports follow the coding guidelines by using the @/lib/http-api-client alias path.


193-200: Auth initialization correctly handles external server mode.

The logic properly distinguishes between:

  • Standard Electron mode (API key auth) → auto-authenticated
  • External server mode (Docker API) → requires session verification like web mode

The async checkExternalServerMode() call ensures the cache is populated before auth state is finalized.


243-273: Routing guards properly account for external server mode.

The needsSessionAuth computation correctly unifies web mode and external server mode under session-based authentication. Using isExternalServerMode() === true safely handles the null case (returns false when not yet checked).

The guard at line 253 ensures no redirects occur until auth check completes for session-auth modes.


362-376: Render-time guards are consistent with routing logic.

The same needsSessionAuth pattern is correctly applied to prevent rendering protected routes before authentication is verified in web/external-server modes.

apps/ui/src/main.ts (4)

135-137: Clean module-level flag for external server mode tracking.

The boolean flag is appropriately scoped at module level to be accessible by both the startup logic and IPC handlers.


695-723: External server mode startup logic is well-structured.

Key behaviors when SKIP_EMBEDDED_SERVER=true:

  • Uses the default port 3008 (matching Docker container)
  • Waits for external server with increased timeout (60 attempts)
  • Skips API key generation, enabling session-based auth
  • Proper logging explains the auth flow

The comment on line 709-712 clearly documents the session-based authentication expectation.


736-738: Server startup correctly gated on external mode flag.

The embedded server is only started when not using an external Docker server.


938-950: IPC handlers correctly expose external server mode state.

  • auth:getApiKey returns null in external mode, signaling the renderer to use session-based auth
  • auth:isExternalServerMode provides the explicit boolean check for routing decisions
docker-compose.dev-server.yml (1)

1-103: Well-structured Docker Compose configuration for server-only development.

The configuration correctly:

  • Uses Dockerfile.dev for development builds with live reload
  • Mounts source code for hot reloading
  • Uses named volume for node_modules to avoid platform conflicts
  • Includes a healthcheck for server readiness detection
  • Handles permissions properly via the entrypoint script

Note: Users will need to create docker-compose.override.yml to mount their projects directory (as mentioned in the comment on line 63). Consider adding a sample override file or documenting this requirement in the README.

scripts/launcher-utils.mjs (2)

503-503: Menu correctly updated with new option description.

The description clearly indicates this option runs a local Electron with a container-based API.


897-1002: Well-implemented Docker server + Electron launcher function.

The function properly orchestrates:

  1. Starting the Docker server container
  2. Waiting for health with generous timeout (2 minutes for first-run npm install)
  3. Building shared packages (required for Electron UI)
  4. Launching Electron with SKIP_EMBEDDED_SERVER=true

The Promise.race on lines 997-1001 exits when either process terminates. While this doesn't automatically stop the other process, the cleanup handlers registered in dev.mjs via createCleanupHandler and setupSignalHandlers will terminate both processes on Ctrl+C, which is the expected user interaction.


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 and usage tips.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @webdevcody, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the development workflow by introducing an "external server mode" for the Electron application. This mode allows developers to run the backend API within a Docker container while the Electron UI runs locally, connecting to the containerized backend. This setup facilitates a more isolated and consistent development environment for the backend, while still leveraging the rapid iteration capabilities of local Electron development. The changes include new Docker Compose configurations, updates to the Electron application's authentication and routing logic to accommodate this new mode, and modifications to development scripts for easy launching.

Highlights

  • External Server Mode Integration: Introduced a new development mode allowing the Electron UI to connect to a backend API running in a Docker container, facilitating a more isolated and consistent development environment.
  • Docker Compose for Backend: Added docker-compose.dev-server.yml to define and manage the Dockerized backend API, complete with volume mounts for live reload capabilities and a health check.
  • UI Authentication & Routing Updates: Modified the Electron UI to detect and adapt to the external server mode, switching to session-based authentication and adjusting routing logic accordingly.
  • Development Workflow Enhancement: Updated the dev.mjs script and launcher-utils.mjs to provide a new option for launching the Docker server alongside the local Electron application, streamlining the development setup.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a new external server mode, allowing the Electron app to connect to a backend running in a Docker container. The changes are well-structured, including a new Docker Compose file for the server, updates to the development launcher scripts, and modifications to the Electron main and renderer processes to handle the new authentication and routing logic.

My review focuses on improving maintainability and type safety. I've pointed out a few areas for improvement:

  • In apps/ui/src/routes/__root.tsx, there's some duplicated logic that can be refactored.
  • In scripts/launcher-utils.mjs, a hardcoded port number could be extracted into a constant.
  • In apps/ui/src/lib/http-api-client.ts, a type assertion as any is used, which could be avoided by updating the relevant type definition.

Overall, this is a solid implementation of a useful new development feature.

Comment on lines +147 to +148
const api = window.electronAPI as any;
if (api?.isExternalServerMode) {
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The use of as any to access isExternalServerMode indicates that the type definition for window.electronAPI (likely ElectronAPI) is missing this new property. While this works, it bypasses TypeScript's type safety. To improve maintainability and type safety, the ElectronAPI interface should be updated to include the optional isExternalServerMode method. This would remove the need for the type assertion.

Comment on lines +362 to +363
// Check if we need session-based auth (web mode OR external server mode)
const needsSessionAuth = !isElectronMode() || isExternalServerMode() === true;
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

This logic to define needsSessionAuth is duplicated from line 250. To improve maintainability and avoid potential inconsistencies, this constant should be defined only once at the top of the RootLayoutContent component and then reused in both the useEffect hook and this rendering logic.


// Wait for the server to become healthy
log('Waiting for server to be ready...', 'yellow');
const serverPort = 3008;
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The port number 3008 is hardcoded here. This value is also used when launching Electron on lines 987-988. Using a hardcoded "magic number" in multiple places makes the code harder to maintain.

To improve maintainability, please define a constant for this port at the top of the launchDockerDevServerContainer function and use it in all relevant places.

@webdevcody
Copy link
Collaborator Author

GHSA-8r9q-7v3j-jr4g

I'll keep an eye on this cve

@webdevcody webdevcody merged commit 77f253c into main Jan 7, 2026
9 of 10 checks passed
@webdevcody webdevcody deleted the electron-with-docker-api branch January 7, 2026 02:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants