# How Open Notebook's Three-Tier Architecture Works: Frontend, API, and Database

> Explore Open Notebook's three-tier architecture. Understand how the React frontend, FastAPI backend, and SurrealDB database interact via HTTP REST and SurrealQL for efficient data management.

- Repository: [Luis Novo/open-notebook](https://github.com/lfnovo/open-notebook)
- Tags: architecture
- Published: 2026-06-15

---

**Open Notebook implements a three-tier architecture that separates a React/Next.js frontend (port 3000), a FastAPI backend (port 5055), and a SurrealDB database (port 8000), with tiers communicating via HTTP REST and SurrealQL protocols.**

The `lfnovo/open-notebook` repository is an open-source knowledge management system built for local-first, AI-powered note-taking. Its modular three-tier architecture ensures clean separation between user interface, business logic, and data persistence, enabling private deployment without external API dependencies for data storage.

## Frontend Tier: React and Next.js

The presentation layer runs on **port 3000** and is built with **Next.js** and **React**. According to the root [[`CLAUDE.md`](https://github.com/lfnovo/open-notebook/blob/main/CLAUDE.md)](https://github.com/lfnovo/open-notebook/blob/main/CLAUDE.md), the frontend provides the notebook interface, source-upload widgets, chat interfaces, semantic search, and podcast generation controls.

State management relies on **Zustand**, while data fetching uses **TanStack Query** to communicate with the FastAPI backend. The UI component library consists of **shadcn/ui** styled with **Tailwind CSS**. All user actions trigger HTTP requests to the REST endpoints exposed by the API tier, ensuring the frontend remains strictly responsible for presentation and user interaction.

## API Tier: FastAPI

The application layer operates on **port 5055** using **FastAPI** as the web framework. This tier implements all business logic, orchestrates LangGraph workflows, and mediates every request between the frontend and database.

### REST Endpoints and Business Logic

The API exposes REST endpoints for core entities including notebooks, sources, notes, and chat sessions. In [`api/main.py`](https://github.com/lfnovo/open-notebook/blob/main/api/main.py), the FastAPI application initializes with CORS configuration and registers routers such as [`api/routers/notebook.py`](https://github.com/lfnovo/open-notebook/blob/main/api/routers/notebook.py), which handles CRUD operations for notebook resources.

### LangGraph Workflow Orchestration

The API utilizes **LangGraph** state machines to manage complex workflows. The `open_notebook/graphs/*` directory contains graph definitions for:

- Source ingestion and text extraction
- Content transformation pipelines
- Conversational chat with context retrieval
- Podcast generation workflows

### Model Management via Esperanto

LLM calls route through the **Esperanto** library via [`open_notebook/ai/model_manager.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/ai/model_manager.py). The `ModelManager` class abstracts provider-specific implementations, supporting OpenAI, Anthropic, Ollama, and other compatible endpoints through a unified interface.

### Async Database Connectivity

All database operations use an async SurrealDB driver. The [`open_notebook/database/manager.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/database/manager.py) file implements the async wrapper that handles connection pooling, query execution, and automatic schema migrations at startup.

## Database Tier: SurrealDB

The data persistence layer runs on **port 8000** using **SurrealDB**. As documented in [`open_notebook/database/CLAUDE.md`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/database/CLAUDE.md), SurrealDB stores the graph relationships between notebooks, sources, notes, and chat sessions.

SurrealDB's native vector support holds embeddings for semantic search, enabling fast Retrieval-Augmented Generation (RAG) queries without requiring a separate vector database. The API connects to SurrealDB asynchronously using the SurrealQL protocol, applying migrations automatically when the application initializes.

## Inter-Tier Communication and Data Flow

The architecture follows a strict communication pattern:

```

[Browser] → HTTP (REST) → FastAPI → async SurrealQL → SurrealDB

```

When a user uploads a source file, the frontend POSTs to the API, which extracts text, generates embeddings via the configured AI provider, and stores the vectorized data in SurrealDB. For chat queries, the API retrieves relevant sources using vector similarity search, passes the context to the LLM through the ModelManager, and returns the generated response to the frontend.

## Key Implementation Files

Understanding the three-tier architecture requires familiarity with these specific files:

- [`frontend/src/pages/index.tsx`](https://github.com/lfnovo/open-notebook/blob/main/frontend/src/pages/index.tsx) — Main UI entry point using Zustand stores and TanStack Query
- [`api/main.py`](https://github.com/lfnovo/open-notebook/blob/main/api/main.py) — FastAPI initialization and router registration
- [`api/routers/notebook.py`](https://github.com/lfnovo/open-notebook/blob/main/api/routers/notebook.py) — Notebook CRUD endpoints
- `open_notebook/graphs/*` — LangGraph workflow definitions
- [`open_notebook/database/manager.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/database/manager.py) — Async SurrealDB connection and migration handler
- [`open_notebook/ai/model_manager.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/ai/model_manager.py) — Esperanto-based provider selection
- [`CONFIGURATION.md`](https://github.com/lfnovo/open-notebook/blob/main/CONFIGURATION.md) — Environment variables for port configuration and database URLs

## Implementation Examples

### Creating a Notebook via the API

```python
import httpx

BASE = "http://localhost:5055"

async def create_notebook(name: str):
    async with httpx.AsyncClient() as client:
        resp = await client.post(
            f"{BASE}/notebooks",
            json={"title": name}
        )
        resp.raise_for_status()
        return resp.json()

```

### Querying SurrealDB Directly

```python
from surrealdb import Surreal

db = Surreal("ws://localhost:8000")
await db.signin({"user": "root", "pass": "root"})
await db.use("open_notebook", "my_namespace")

async def get_notes(notebook_id: str):
    query = f"SELECT * FROM note WHERE notebook = '{notebook_id}'"
    result = await db.query(query)
    return result[0]["result"]

```

### Running a LangGraph Podcast Workflow

```python
from open_notebook.graphs.podcast import podcast_graph

async def generate_podcast(source_id: str):
    state = {"source_id": source_id}
    result = await podcast_graph.ainvoke(state)
    return result["podcast_url"]

```

## Summary

- **Open Notebook's three-tier architecture** strictly separates the Next.js frontend (port 3000), FastAPI backend (port 5055), and SurrealDB database (port 8000).
- The frontend uses **Zustand** for state and **TanStack Query** for API communication, while the backend orchestrates **LangGraph** workflows and manages LLM providers via **Esperanto**.
- **SurrealDB** handles both relational graph data and vector embeddings, enabling semantic search without additional services.
- All tiers communicate asynchronously, with the API layer translating HTTP REST requests into SurrealQL database operations.

## Frequently Asked Questions

### What ports does Open Notebook use for each tier?

The frontend runs on **port 3000**, the FastAPI backend listens on **port 5055**, and SurrealDB operates on **port 8000**. These defaults are configurable via environment variables defined in [`CONFIGURATION.md`](https://github.com/lfnovo/open-notebook/blob/main/CONFIGURATION.md).

### How does the API handle different LLM providers?

The [`open_notebook/ai/model_manager.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/ai/model_manager.py) implements the **Esperanto** library abstraction, which routes LLM calls to multiple providers including OpenAI, Anthropic, and Ollama through a unified interface, allowing users to switch models without changing application code.

### Why does Open Notebook use SurrealDB instead of PostgreSQL or MongoDB?

SurrealDB was selected for its native **graph database capabilities** and built-in **vector storage**, which eliminates the need for separate databases to handle document relationships and semantic search embeddings required for the RAG functionality.

### How does data flow when I upload a document?

The frontend sends the file via HTTP POST to the FastAPI backend, which processes the content through LangGraph ingestion workflows, generates embeddings using the configured AI provider, and stores both the text and vectors in SurrealDB using async SurrealQL queries.