FLESHNOTE / DOCS / ARCHITECTURE & IPC

System Architecture & 3-Layer IPC

v1.3.0

Technical specifications for the application stack, Electron preload bridge, Python FastAPI daemon, and data flow conventions.

Technology Stack #

FleshNote is built on a high-performance desktop hybrid stack. It leverages Electron for native OS integration and multi-window rendering, React + Vite for rapid component updates, TipTap (ProseMirror) for rich manuscript editing, and a local Python FastAPI daemon backed by SQLite in Write-Ahead Logging (WAL) mode.

Layer Technology Core Responsibilities
Desktop Shell Electron Frameless window controls, native file dialogs, background daemon lifecycle, IPC dispatch.
Renderer (Frontend) React 18 + Vite State ownership (`FleshNoteIDE.jsx`), entity panels, focus mode canvases, context popups.
Manuscript Editor TipTap (ProseMirror) Custom EntityLinkMark (`<span data-entity-type>`), formatting extensions, time gutter sync.
Styling System Vanilla CSS (Custom Props) `index.css` (~2000 lines), zero CSS framework overhead, CSS logical properties for RTL mirror.
Backend Server Python 3.13 (FastAPI) Local HTTP daemon (`localhost:8000`), JSON validation, file I/O, NLP computation.
Database Engine SQLite (WAL Mode) Zero-server relational persistence at `{project}/fleshnote.db` with UUID keys.
Linguistic NLP spaCy, HuSpaCy, NLTK Sensory radar extraction, show-don't-tell audits, and dynamic AppData model installation.

3-Layer IPC Communication Pipeline #

All operations that communicate with the project database or filesystem follow this 3-layer chain:

Data Flow Chain
React (Renderer) ──▶ Preload (window.api) ──▶ Electron Main (ipcMain) ──▶ Python FastAPI (localhost:8000)

1. Renderer Layer (`src/renderer/src/components`)

React components invoke asynchronous methods exposed on the global window.api object without knowing the underlying network or IPC protocols:

React / TypeScript
// Example: Saving chapter content from React Editor
const handleSave = async (contentMarkdown: string) => {
  const response = await window.api.saveChapterContent({
    project_path: currentProjectPath,
    chapter_id: activeChapterId,
    content: contentMarkdown
  });
  if (response.status === 'ok') {
    setLastSaved(new Date());
  }
};

2. Preload Layer (`src/preload/index.ts`)

Uses Electron's contextBridge.exposeInMainWorld('api', { ... }) to safely expose sanitized wrapper methods calling ipcRenderer.invoke('api:channelName', payload).

TypeScript / Electron Preload
// src/preload/index.ts
import { contextBridge, ipcRenderer } from 'electron';

contextBridge.exposeInMainWorld('api', {
  saveChapterContent: (payload: { project_path: string; chapter_id: string; content: string }) =>
    ipcRenderer.invoke('api:saveChapterContent', payload),
  getEntities: (payload: { project_path: string }) =>
    ipcRenderer.invoke('api:getEntities', payload),
});

3. Main Process Layer (`src/main/index.ts`)

Electron Main handles the IPC invoke message and delegates the request to the Python backend via the backendPost() helper:

TypeScript / Electron Main
// src/main/index.ts
import { ipcMain } from 'electron';
import http from 'http';

async function backendPost(endpoint: string, data: any): Promise<any> {
  return new Promise((resolve, reject) => {
    const postData = JSON.stringify(data || {});
    const req = http.request({
      hostname: '127.0.0.1',
      port: 8000,
      path: endpoint,
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Content-Length': Buffer.byteLength(postData)
      }
    }, (res) => {
      let body = '';
      res.on('data', (chunk) => body += chunk);
      res.on('end', () => resolve(JSON.parse(body)));
    });
    req.on('error', reject);
    req.write(postData);
    req.end();
  });
}

ipcMain.handle('api:saveChapterContent', async (_event, payload) => {
  return await backendPost('/chapter/save', payload);
});
All Endpoints Use HTTP POST Every FastAPI backend route uses @router.post with a Pydantic request body. project_path is always included in the payload so the backend knows which project SQLite database to open dynamically.

Development Environment Setup #

Follow these steps to configure your local developer workstation:

Step 1: Prerequisites
- Node.js v18+ (npm included)
- Python 3.13 (ensure Python is added to system PATH)
- Git
Step 2: Install and Run
# Navigate into fleshnote-ide directory
cd fleshnote-ide

# Install frontend packages
npm install

# Setup backend virtual environment
cd backend
python -m venv .venv

# Activate environment (Windows)
.venv\Scripts\activate
# Or on macOS/Linux:
# source .venv/bin/activate

# Install runtime dependencies
pip install -r requirements.txt
cd ..

# Launch hot-reload dev mode
npm run dev

Project & AppData Directory Structure #

The FleshNote repository is structured cleanly into frontend and backend domains:

Repository Directory Tree
fleshnote-ide/
├── src/
│   ├── main/
│   │   └── index.ts               # Electron main process, IPC dispatchers, daemon runner
│   ├── preload/
│   │   └── index.ts               # contextBridge window.api method definitions
│   └── renderer/src/
│       ├── components/            # React UI components (Editor, Panels, Focus Modes)
│       │   ├── focus-modes/       # Hemingway, Zen, Kamikaze, Fog, Momentum
│       │   └── ide-panels/        # Entity Inspector, Location Tree, Twists
│       ├── extensions/            # TipTap custom marks (EntityLinkMark.js)
│       ├── index.css              # Global styles (~2000 lines, custom properties)
│       └── App.jsx                # View router (picker -> questionnaire -> setup -> ide)
│
├── backend/
│   ├── main.py                    # FastAPI application, route mounting, loopback server
│   ├── db_setup.py                # 11-table SQLite generator, migrations, presets
│   ├── nlp_manager.py             # spaCy / HuSpaCy background subprocess installer
│   ├── nltk_manager.py            # NLTK WordNet and sensory auditor
│   ├── migration_engine.py        # v1 integer -> v2 UUID schema migrator
│   ├── remote_sync_session.py     # HLC sync, change_log, 3-way prose merge
│   └── routes/                    # Domain-specific FastAPI router modules
│       ├── chapters.py            # Chapter CRUD, entity markdown conversion
│       ├── characters.py          # Character management, birth dates, ages
│       ├── locations.py           # Location trees, hierarchical weather
│       ├── entities.py            # Lore entities, quick notes, search scoring
│       ├── knowledge.py           # Epistemic facts and POV visibility
│       ├── twists.py              # Twists, foreshadowing, leak detection
│       ├── planner.py             # Plot arcs and milestone blocks
│       └── sync.py                # Sync payloads, version vectors, apply diffs
│
└── {userData}/                    # OS AppData Directory (AppData/Roaming/fleshnote)
    ├── fleshnote_config.json      # Global settings (recent projects, dark theme)
    └── spacy_models/              # Dynamically installed neural NLP wheels
On This Page