Open Notebook Three-Tier System Architecture: Next.js, FastAPI, and SurrealDB
Open Notebook implements a classic three-tier architecture that separates Presentation, Application, and Data concerns across a Next.js 16 frontend, a FastAPI backend, and a SurrealDB graph database.
The lfnovo/open-notebook repository is an open-source knowledge management platform built around a strict three-tier system architecture. This design cleanly isolates user interface rendering, business logic orchestration, and persistent storage into independent layers that communicate over HTTP REST. Every request flows from the React-based presentation layer through FastAPI routers before reaching SurrealDB queries, enabling independent scaling and clear responsibility boundaries.
Presentation Tier: Next.js 16, React 19, and Zustand State Management
Responsibilities and Technology Stack
The presentation tier is a Next.js 16 application written in TypeScript that handles all user-facing interactions, including notebook management, source upload, note editing, chat, search, and podcast generation. State is managed with Zustand and server-state synchronization uses TanStack Query (React Query), while the UI component library is built on Tailwind CSS and Shadcn UI. All API communication is centralized through frontend/src/lib/api/client.ts, which abstracts every backend call into typed service functions.
Key Frontend Files
frontend/next.config.ts– Next.js configuration and build settings.frontend/src/lib/api/client.ts– Central API client used by all UI components.frontend/src/components/*– React components for notebooks, chat, and search interfaces.
Frontend API Call Example
When the user views their notebook list, the frontend calls the backend through a typed service method defined in frontend/src/lib/api/notebooks.ts:
// frontend/src/lib/api/notebooks.ts
import { apiClient } from '@/lib/api/client';
export async function listNotebooks() {
const { data } = await apiClient.get('/notebooks');
return data; // array of NotebookDTO
}
Application Tier: FastAPI 0.104+, Pydantic, and LangGraph
Responsibilities and Technology Stack
The application tier is a Python 3.11+ FastAPI service that exposes the REST API driving the UI. It handles request validation through Pydantic v2, orchestrates LangGraph workflows for source ingestion and chat, manages asynchronous jobs such as podcast generation, and selects AI providers via the Esperanto library. Router modules in api/routers/*.py map HTTP paths to domain services, while api/main.py handles application creation, CORS setup, and router registration.
Key Application Files
api/main.py– FastAPI app factory, CORS configuration, and event startup.api/routers/*.py– REST routers for notebooks, sources, search, and transformations.open_notebook/graphs/*.py– LangGraph workflow definitions for source ingestion, chat, and ask pipelines.api/transformations_service.py– Async job orchestration logic.
FastAPI Router Endpoint Example
The /notebooks endpoint in api/routers/notebooks.py delegates incoming requests to NotebookService, keeping HTTP concerns separate from business logic:
# api/routers/notebooks.py
from fastapi import APIRouter, Depends
from open_notebook.services.notebook_service import NotebookService
router = APIRouter()
@router.get("/notebooks")
async def get_notebooks(service: NotebookService = Depends()):
return await service.list_notebooks()
Data Tier: SurrealDB Graph Database with Async Driver
Responsibilities and Technology Stack
The data tier uses SurrealDB as its primary graph database, accessed through an async Python driver initialized at API startup. It stores all domain entities—Notebook, Source, Note, ChatSession, and Credential—along with their relationships, and provides built-in vector embeddings for semantic search. Automatic schema migrations in migrations/*.surql are executed when the FastAPI application boots, ensuring the schema stays synchronized with the domain models.
Key Data Files
open_notebook/database/__init__.py– Async SurrealDB connection manager and session handling.open_notebook/domain/models.py– Pydantic models representing database records.migrations/*.surql– Schema migration scripts executed automatically on startup.api/main.py– Contains the surrealdb connection bootstrap logic.
SurrealDB Query Example
The NotebookService translates domain operations into SurrealDB queries, returning fully typed records as shown in open_notebook/services/notebook_service.py:
# open_notebook/services/notebook_service.py
async def list_notebooks(self) -> List[Notebook]:
result = await self.db.query("SELECT * FROM notebook")
return [Notebook(**record) for record in result]
How the Three Tiers Communicate Over HTTP REST
The tiers communicate over standard HTTP REST: the Next.js frontend calls the FastAPI server, which in turn queries SurrealDB via its async driver. Because the layers are decoupled by network boundaries, each tier can be scaled independently—for example, running the API and database on separate containers or instances. This mirrors the classic three-tier pattern, with the frontend in frontend/, the API in api/, and the database logic in open_notebook/database/.
Summary
- Open Notebook uses a strict three-tier system architecture separating Presentation, Application, and Data concerns.
- The presentation tier (
frontend/) is built with Next.js 16, React 19, Zustand, and TanStack Query. - The application tier (
api/) runs on FastAPI 0.104+, validates requests with Pydantic v2, and orchestrates LangGraph workflows. - The data tier persists entities in SurrealDB, leveraging its native graph and vector embedding capabilities.
- All tiers communicate via HTTP REST, enabling independent deployment and scaling across containers.
Frequently Asked Questions
What technologies power each tier of the Open Notebook three-tier system?
The presentation tier uses Next.js 16 with React 19, TypeScript, Tailwind CSS, Shadcn UI, Zustand, and TanStack Query. The application tier runs FastAPI 0.104+ on Python 3.11+, using Pydantic v2 for validation and LangGraph for workflow orchestration. The data tier relies on SurrealDB as an async graph database with built-in vector support for semantic search.
How does the frontend communicate with the backend API?
The Next.js frontend communicates with the FastAPI backend over standard HTTP REST calls defined in frontend/src/lib/api/client.ts. Typed service functions like listNotebooks() map directly to FastAPI router endpoints such as /notebooks, ensuring end-to-end type safety and clean separation between UI and business logic.
Why does Open Notebook use SurrealDB instead of a relational database?
According to the lfnovo/open-notebook source code, SurrealDB was selected because it natively handles graph relationships between entities like Notebook, Source, and Note while providing built-in vector embeddings for semantic search. This eliminates the need for a separate vector store and simplifies the data model by keeping relationships and search vectors in a single system.
Can each tier of the Open Notebook architecture be deployed independently?
Yes. Because the presentation, application, and data layers communicate exclusively over HTTP REST and async database drivers, they can be containerized and scaled independently. The frontend static build, FastAPI server, and SurrealDB instance each run in separate processes, supporting classic containerized deployments where compute and storage resources are allocated per tier.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →