amira/ARCHITECTURE.md
2026-02-10 16:09:09 -05:00

6.2 KiB
Raw Blame History

Hydra Browser Architecture

This document explains the Hydra Browser architecture for a developer who knows Python but is new to frontend and Electron. It focuses on how the app is structured, how data flows, and how the main features work.

1. What This App Is

Hydra is a desktop app (Electron) that renders web pages inside a canvas of linked windows. Each window is a React Flow node. Links can open new windows and form a graph of browsing paths.

Key ideas:

  • Electron runs a desktop window using Chromium.
  • The renderer is a React app (frontend UI).
  • A local proxy server fetches web pages and injects scripts to intercept clicks.
  • Zustand store holds all app state (nodes, edges, UI state).

2. High-Level Architecture

flowchart LR
  subgraph Electron App
    Main[Main Process
src/main/index.js]
    Renderer[Renderer Process
React UI]
  end

  Renderer -->|HTTP| Proxy[Local Proxy Server
src/server/proxy.js]
  Renderer <-->|IPC| Main
  Proxy -->|Fetch| Internet[Websites]

Roles

  • Main Process: bootstraps Electron and starts the proxy server.
  • Renderer: React UI + state. Renders the canvas and windows.
  • Proxy Server: fetches web content, injects scripts, returns HTML to iframes.

3. Key Modules

3.1 Main Process (Electron)

File: src/main/index.js

Responsibilities:

  • Create the Electron window.
  • Start the local proxy server (port 3001).
  • Provide IPC handlers for file-based session save/load.

3.2 Proxy Server

File: src/server/proxy.js

Responsibilities:

  • Fetch remote pages (via Axios).
  • Inject a script into HTML to:
    • intercept clicks
    • intercept form submissions
    • intercept programmatic navigations
    • send postMessage events back to the renderer
    • provide page text for summaries/chat

3.3 Renderer

Root: src/renderer

Key pieces:

  • components/ReactFlowCanvas.tsx: canvas and node types
  • components/BrowserWindowNode.tsx: web window node
  • components/NoteWindowNode.tsx: notes
  • components/SummaryWindowNode.tsx: AI summary output
  • components/ChatWindowNode.tsx: AI chat window
  • store/hydraStore.ts: Zustand store (all app state)

4. Data Flow: Opening a Page

sequenceDiagram
  participant UI as BrowserWindowNode
  participant Store as Hydra Store
  participant Proxy as Proxy Server
  participant Web as Website

  UI->>Store: addBrowserWindow(url)
  Store->>UI: node created (BrowserWindowNode)
  UI->>Proxy: GET /fetch?url=...
  Proxy->>Web: fetch page
  Web->>Proxy: HTML response
  Proxy->>Proxy: inject link interception script
  Proxy->>UI: HTML (blob URL)
  UI->>UI: iframe loads blob

When the injected script sees a link click or navigation, it sends:

window.parent.postMessage({
  type: 'HYDRA_LINK_CLICK',
  url: 'https://example.com',
  openInNewWindow: true|false
}, '*')

The renderer listens for these messages and either:

  • opens a new node and connects it with an edge, or
  • navigates within the same node
flowchart TD
  Click[User clicks link] --> Script[Injected script]
  Script -->|postMessage| Renderer
  Renderer -->|openInNewWindow| StoreAdd[addBrowserWindow]
  Renderer -->|same window| StoreNav[navigateBrowserWindow]

6. State Management (Zustand)

File: src/renderer/store/hydraStore.ts

The store keeps:

  • nodes: all windows on the canvas
  • edges: relationships between windows
  • theme: dark/light
  • AI settings: provider, API key, model
  • session info: file path + name

Example: Creating a Browser Window Node

addBrowserWindow(url, parentId?)
  • Creates a new React Flow node
  • Optionally creates an edge from the parent
  • Re-layouts the graph so windows align

7. Layout Engine

File: src/renderer/store/hydraStore.ts

A custom layout function positions nodes:

  • Root nodes are stacked vertically
  • Children appear to the right of their parent
  • Subtrees never overlap
graph LR
  A[Root 1] --> B[Child 1]
  A --> C[Child 2]
  D[Root 2] --> E[Child]

8. Node Types

Type Purpose File
browserWindow Render a web page BrowserWindowNode.tsx
noteWindow Editable note NoteWindowNode.tsx
summaryWindow AI summary output SummaryWindowNode.tsx
chatWindow AI chat UI ChatWindowNode.tsx

9. AI Features

9.1 Summaries

  • Renderer requests page text via postMessage.
  • Sends request to /summarize on the proxy.
  • Proxy calls OpenAI/Anthropic API.
  • Summary text displayed in a Summary node.
sequenceDiagram
  participant UI as BrowserWindowNode
  participant Proxy as Proxy Server
  participant LLM as AI Provider

  UI->>Proxy: POST /summarize {text, url}
  Proxy->>LLM: summarize
  LLM->>Proxy: summary
  Proxy->>UI: summary

9.2 Chat

  • Chat node sends messages to /chat on proxy.
  • Proxy adds context text and calls LLM API.

10. Session Files (File-Based)

Sessions are saved to disk using file dialogs. No in-app storage.

  • Save: user chooses a .hydra file.
  • Load: user selects a .hydra file.

Flow:

flowchart LR
  UI -->|IPC| Main
  Main -->|showSaveDialog/openDialog| OS
  OS --> Main
  Main -->|read/write file| FileSystem

11. Important Constraints

  • Some sites block iframes (X-Frame-Options, CSP frame-ancestors).
  • JavaScript-driven navigation can bypass the proxy if not intercepted.
  • Removing allow-same-origin increases safety but prevents direct DOM access.

12. Mental Model (Python Developer Friendly)

Think of it as:

  • Electron Main = Python if __name__ == '__main__': boot process
  • Renderer = GUI app logic (like a web app)
  • Proxy Server = a local Flask server that fetches and rewrites HTML
  • Zustand Store = a global state dictionary
  • React Flow = a canvas + graph UI library

13. Where to Start Reading

Recommended order:

  1. src/main/index.js app bootstrap
  2. src/server/proxy.js page fetching and injection
  3. src/renderer/store/hydraStore.ts core data model
  4. src/renderer/components/ReactFlowCanvas.tsx node registration
  5. src/renderer/components/BrowserWindowNode.tsx core window node

If you want a deeper walkthrough of any module, ask and Ill expand that section.