Electron Desktop App Architecture — Full Stack with AI

Electron Desktop App Architecture — Full Stack with AI

Architecture for an offline-first desktop application built with Electron, bundling a Next.js frontend, Express.js backend, and Python AI service into a single distributable app.


Tech Stack

Layer Technology Purpose
Desktop Shell Electron Window management, IPC bridge, app:// protocol
Frontend Next.js (Pages Router) + TypeScript UI, routing, dual-path API client (IPC or fetch)
Styling Tailwind CSS + CSS variables Custom theme system with data-theme attribute
State React Context + Zustand + custom hooks Global state, complex UI state, server state
Backend Express.js + TypeScript REST API, file uploads (Multer), business logic
ORM / DB Prisma + SQLite Type-safe queries, local database
AI Service Python FastAPI + Uvicorn RAG engine, LLM orchestration, vector search
Local LLM Any GGUF model via llama-cpp-python Offline AI generation
Cloud LLMs OpenAI, Anthropic, Gemini, DeepSeek, Groq Online AI generation
Vectors ChromaDB + sentence-transformers Embeddings, similarity search
Licensing LemonSqueezy (via website middleman) License activation, validation, device management
Packaging electron-builder + PyInstaller Windows .exe / macOS .dmg

System Architecture


Request Flow


License Activation

  • Website is the API middleman (holds the LemonSqueezy API key)
  • Local SQLite stores activation state for offline use
  • 14-day offline grace period after last successful validation
  • Machine fingerprint prevents key sharing across devices

Dev vs Production

Aspect Dev Production (packaged)
Frontend http://localhost:3000 app://./index.html (static export)
Backend ts-node-dev index.ts node backend/dist/index.js
AI Service .venv/Scripts/python -m api.main aiservice.exe (PyInstaller)
Database backend/database/app.db AppData/Roaming/AppName/data/app.db
Vectors aiservice/data/chroma/ AppData/Roaming/AppName/data/chroma/
Uploads backend/uploads/ AppData/Roaming/AppName/uploads/
Detection app.isPackaged = false app.isPackaged = true

Build Commands

Command What It Does
npm run dev Backend + frontend in browser (localhost:3000)
npm run desktop Compiles all + launches Electron window
npm run pack Builds unpacked directory (for testing)
npm run dist:win Builds Windows distributable
npm run dist:mac Builds macOS distributable

File Structure

desktop-app/
├── frontend/
│   ├── api/                    # Dual-path API client (IPC + fetch)
│   ├── components/             # Shared reusable components
│   │   ├── ui/                 # Atoms (Button, Modal, VirtualList, etc.)
│   │   ├── layout/             # Container, Header, Sidebar
│   │   ├── forms/              # Checkbox, ColorPicker, FormField, etc.
│   │   └── data-display/       # EmptyState, Grid, List
│   ├── contexts/               # React Context providers
│   ├── hooks/                  # Custom hooks (per module)
│   ├── modules/                # Feature modules
│   ├── pages/                  # Next.js Pages Router
│   ├── services/               # Business logic layer
│   ├── store/                  # Zustand stores
│   ├── utils/                  # Per-module utilities
│   ├── styles/                 # Tailwind + CSS variable theme system
│   └── public/assets/          # Static assets (themes, images, fonts)
│
├── backend/
│   ├── index.ts                # Express entry point
│   ├── paths.ts                # Path utilities (dev vs packaged)
│   ├── routes/                 # Route groups
│   ├── database/               # Service layers + Prisma client
│   ├── prisma/                 # schema.prisma + seed.ts
│   └── uploads/                # File storage (fonts, music, images, themes)
│
├── aiservice/                  # Python AI Service
│   ├── api/                    # FastAPI server + routes
│   ├── services/               # AI service helpers
│   ├── prompts/                # Prompt templates
│   ├── models/                 # Local LLM model (GGUF)
│   └── data/chroma/            # ChromaDB vectors (dev mode)
│
├── electron/                   # Electron desktop wrapper
│   ├── main.ts                 # IPC handlers, service spawner, app:// protocol
│   └── preload.ts              # Secure bridge (window.electronAPI)
│
├── electron-builder.yml        # Packaging configuration
├── afterPack.js                # Post-build script
└── package.json                # Root scripts (dev, desktop, pack, dist)