How I Built a Desktop Trading Journal with Electron, React, and SQLite
Source: Dev.to
Overview
Last week I shipped a desktop app called Aurafy, a trading journal for futures traders that runs entirely locally—no cloud, no accounts, no subscription. I wanted to share the technical decisions behind it because the “local‑first” approach is underrated for tools that handle sensitive financial data.
Architecture
The app is organized as a monorepo with three pieces:
Server
- Express.js + better‑sqlite3
- Runs inside the Electron main process (no child process spawn, which cuts startup time to under 2 seconds)
- SQLite in WAL mode handles all persistence
- Every write uses
synchronous = FULLto guarantee durability
Client
- React, Vite, Tailwind CSS, Recharts
- Standard SPA that talks to the Express server over
localhost - TanStack Query handles data fetching and caching
Electron Wrapper
- The main process starts the Express server in‑process, opens a
BrowserWindowpointing tolocalhost, and handles native features such as screen‑recording permissions and floating camera windows.
Data Storage & Security
Trading data (P&L, account sizes, mistakes) is highly sensitive. With SQLite, everything lives in:
~/Library/Application Support/aurafy/data/journal.db- Users can back up, move, or delete the file themselves.
- No API keys, OAuth flows, or login prompts.
- Trade‑off: no cross‑device sync, which hasn’t been an issue because traders typically journal at their desk.
Built‑in Screen Recorder
A key feature is the ability to record trading sessions for later review, similar to how athletes watch game film.
Electron’s
desktopCapturerAPI provides screen capture.Combined with
getUserMediafor microphone input.Audio streams are mixed using the Web Audio API and fed into a
MediaRecorder.The camera overlay runs in a separate
BrowserWindowwith:{ transparent: true, alwaysOnTop: true, frame: false }It floats above all apps like Loom’s camera bubble. The HTML is a simple circular
containing aelement that shows the webcam feed.
CSV Import from Trading Platforms
Traders export data from platforms such as Tradovate and NinjaTrader as CSV files. Each platform uses different column names, date formats, and instrument naming conventions (e.g., MNQM6 vs. MNQ 06-26).
I built a parser that:
- Auto‑detects the platform by checking column headers.
- Normalizes instrument names using regex (stripping the contract month code).
- Matches to a local instruments table with tick sizes and point values.
- Pairs entry/exit executions and calculates P&L.
The import flow is:
Drop CSV → preview detected trades → confirmNo manual mapping is required.
Performance Optimizations
- In‑process server: The first version spawned a Node child process for Express, adding >3 seconds to startup and causing macOS code‑signing issues (the OS treated it as two separate apps). Running Express inside Electron’s main process via
require()eliminated both problems. - SQLite WAL mode: Without WAL, writes block reads. With
journal_mode = WALandsynchronous = FULL, concurrent reads are possible during writes, and durability is guaranteed on crash.
Auto‑update Challenges
electron-updater creates draft releases on GitHub, which return 404 until manually published. I added a CI step that auto‑publishes the release after both macOS and Windows builds complete.
Development Gotchas
ELECTRON_RUN_AS_NODE: If this environment variable is set (common in some development setups), Electron runs as plain Node.js andrequire('electron')returns a string instead of the module. This caused hours of debugging.
Availability
Aurafy is free and available at . The code handles futures contracts (ES, NQ, CL, MES, MNQ) with proper point values and tick sizes.
Questions
If you’re interested in the Electron + Express + SQLite architecture pattern, feel free to ask questions in the comments.