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:
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:
// 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).
// 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:
// 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);
});
@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:
- Node.js v18+ (npm included)
- Python 3.13 (ensure Python is added to system PATH)
- Git
# 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:
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