Skip to content

Conversation

@ammar-agent
Copy link
Collaborator

Replace hash-based URL handling with proper URL routing using react-router-dom.

URL Structure

URL View
/ Welcome screen (no project selected)
/project?path=/path/to/project ProjectPage (workspace creation)
/workspace/:workspaceId AIView (active workspace)

Key Changes

New Files

  • src/browser/contexts/RouterContext.tsx - Router provider wrapping MemoryRouter with navigation context
  • src/browser/hooks/useRouterUrlSync.ts - URL parsing and browser URL synchronization

Modified Files

  • WorkspaceContext.tsx - State derived from URL instead of internal useState
  • AppLoader.tsx - Wrapped in RouterProvider
  • App.tsx - Removed old hash syncing code

Architecture

Uses MemoryRouter (not BrowserRouter) because Electron's file:// protocol in production doesn't support HTML5 pushState. The router state syncs to the browser URL via history.replaceState() so the URL bar shows proper routes.

Backward Compatibility

  • Legacy hash URLs (#workspace=abc, #/path/to/project) are converted to proper routes on load
  • localStorage workspace is restored when loading at root URL
  • Existing navigation APIs (setSelectedWorkspace, beginWorkspaceCreation) continue to work

Testing

  • All 751 browser tests pass
  • Static checks pass

Generated with mux • Model: anthropic:claude-opus-4-5 • Thinking: high

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Replace hash-based URL handling with proper URL routing using react-router-dom.

## Changes

**New URL Structure:**
- `/` → Welcome screen (no project selected)
- `/project?path=<projectPath>` → ProjectPage (workspace creation)
- `/workspace/:workspaceId` → AIView (active workspace)

**Architecture:**
- Add react-router-dom with MemoryRouter for Electron compatibility
- Create RouterContext to provide navigation functions and parse current route
- Derive selectedWorkspace and pendingNewWorkspaceProject from URL state
- Sync router state to browser URL via history.replaceState()

**Backward Compatibility:**
- Legacy hash URLs (`#workspace=abc`, `#/path/to/project`) are converted to proper routes
- localStorage workspace is restored when loading at root URL
- Existing navigation APIs (setSelectedWorkspace, beginWorkspaceCreation) continue to work

**Files Changed:**
- package.json: Add react-router-dom dependency
- RouterContext.tsx: New - router provider and navigation context
- useRouterUrlSync.ts: New - URL parsing and sync logic
- WorkspaceContext.tsx: Derive state from router instead of internal state
- AppLoader.tsx: Wrap app in RouterProvider
- App.tsx: Remove old hash syncing code

---
_Generated with `mux` • Model: `anthropic:claude-opus-4-5` • Thinking: `high`_
The parseInitialUrl function now correctly treats .html paths (from file:// URLs
in packaged Electron) as root URLs, allowing localStorage workspace restoration
to work in production builds.
In Electron with file:// protocol, updating the browser URL to /workspace/abc
would cause page.reload() to fail with ERR_FILE_NOT_FOUND. The MemoryRouter
state is sufficient for in-app navigation; only browser/server mode needs
the URL bar to reflect current state.
In Storybook, the pathname is /iframe.html with query params for story selection.
This should still restore the selected workspace from localStorage.
Dead code from initial implementation:
- workspaceUrl() - only used internally
- projectUrl() - only used internally
- useAppNavigate() - never imported; RouterContext has same logic
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.

1 participant