Skip to main content

Overview

The Olis Desktop Client is an Electron-based application that provides a native desktop experience for the Olis AI assistant. It combines Electron’s native capabilities with Next.js for a modern React-based UI.

Technology Stack

Electron

Native desktop wrapper for cross-platform support

Next.js 14

React framework with App Router and static export

TypeScript

Type-safe development across the entire stack

Tailwind CSS

Utility-first CSS framework for styling

Project Structure

apps/electron-client/
├── electron/              # Electron main process
   ├── main.ts           # Main process entry point
   └── preload.ts        # Preload script for IPC
├── src/
   ├── app/              # Next.js App Router pages
   ├── page.tsx      # Main chat interface
   └── settings/     # Settings pages
   ├── components/       # React components
   └── lib/              # Utilities and helpers
├── native/
   └── sidecar/          # Rust native module
├── local-llm/            # Bundled llama-server binaries
├── public/               # Static assets
└── release/              # Build artifacts

Development Setup

Prerequisites

  • Node.js 18+
  • pnpm 9.15.4+
  • Rust (for native sidecar)

Installation

1

Navigate to the client directory

cd apps/electron-client
2

Install dependencies

pnpm install
3

Build native sidecar

pnpm run sidecar:build
This compiles the Rust native module and copies it to native/sidecar/index.node.
4

Start development server

pnpm run electron:dev
This starts:
  1. Next.js dev server on http://localhost:3000
  2. Electron app that loads the dev server

Available Scripts

# Run Next.js dev server only
pnpm run dev

# Run Electron + Next.js together (recommended)
pnpm run electron:dev

# Build native Rust sidecar
pnpm run sidecar:build

# Lint code
pnpm run lint
# Build Next.js static export
pnpm run build

# Compile Electron main process
pnpm run build:electron

# Package installers for distribution
pnpm run package

# Rebuild native dependencies
pnpm run install-app-deps

Building for Production

1

Build the renderer

pnpm run build
Creates a static Next.js export in the out/ directory with:
  • assetPrefix: "./" for relative paths
  • trailingSlash: true for file:// protocol
  • output: "export" for static generation
2

Compile the main process

pnpm run build:electron
Compiles TypeScript to JavaScript in dist-electron/.
3

Package the application

pnpm run package
Uses electron-builder to create installers in release/:
  • Windows: NSIS installer (.exe)
  • macOS: DMG and ZIP
  • Linux: AppImage, Snap, DEB
Windows Note: Stop all running Electron instances before packaging. Running instances can lock keytar.node and cause EPERM errors during the build.

Configuration

Environment Variables

Create a .env file in the app root:
# Intent Detection
OLIS_INTENT_MODEL=phi3
OLIS_INTENT_REMOTE_URL=http://localhost:11434
OLIS_INTENT_MODEL_DOWNLOAD_URL=https://example.com/model.gguf
OLIS_INTENT_TIMEOUT_MS=30000

# Document Context
OLIS_DOCS_FOLDER=C:\Users\YourName\Documents\olis-docs

# API Configuration
OLIS_API_URL=http://localhost:8000
For production builds, place .env.production in the resources/ directory.

Next.js Configuration

The next.config.mjs is optimized for Electron:
/** @type {import('next').NextConfig} */
const nextConfig = {
  output: 'export',        // Static export
  assetPrefix: './',       // Relative paths for file://
  trailingSlash: true,     // Ensures /page.html works
  images: {
    unoptimized: true      // No Image Optimization API needed
  }
}

Electron Builder Configuration

The electron-builder.json5 defines package settings:
{
  "appId": "com.olis.app",
  "productName": "Olis",
  "directories": {
    "output": "release",
    "buildResources": "resources"
  },
  "files": [
    "out/**/*",
    "dist-electron/**/*",
    "native/**/*",
    "local-llm/**/*"
  ],
  "win": {
    "target": ["nsis"],
    "icon": "resources/icon.ico"
  },
  "mac": {
    "target": ["dmg", "zip"],
    "icon": "resources/icon.icns"
  }
}

Features

Intent Detection

The desktop client supports multiple intent detection backends:
Chooses the best option based on hardware and configuration:
  1. SLM if available and hardware supports it
  2. LLM if remote service is configured
  3. NLP as fallback

Document Context

Users can configure a document folder for context:
OLIS_DOCS_FOLDER=C:\Users\YourName\Documents\olis-docs
Supported formats:
  • .txt - Plain text
  • .md - Markdown
  • .json - JSON data
  • .csv - CSV files
Documents are automatically loaded and used as context for queries.

Settings Interface

The settings interface provides three main sections:

General

  • Theme selection
  • Language preferences
  • Default behaviors
  • Notification settings

Integrations

  • API connections
  • Third-party services
  • OAuth configurations
  • Webhook settings

Security

  • Authentication
  • Encryption settings
  • Privacy controls
  • Data retention

Native Sidecar (Rust)

The native sidecar provides high-performance native operations:
// Example: File system operations
#[napi]
pub fn read_file_sync(path: String) -> Result<String> {
  std::fs::read_to_string(path)
    .map_err(|e| Error::from_reason(e.to_string()))
}

Building the Sidecar

cd native/sidecar
cargo build --release

# Copy to correct location
cp ../../target/release/index.node ./

Using in Electron

// In renderer process
const sidecar = require('./native/sidecar/index.node')
const content = sidecar.readFileSync('/path/to/file.txt')

Troubleshooting

Problem: Errors building Rust sidecarSolution:
# Ensure Rust is installed
rustc --version

# Clean and rebuild
cd native/sidecar
cargo clean
cargo build --release

# Copy manually if needed
cp ../../target/release/index.node ./
Problem: EPERM error with keytar.nodeSolution:
  1. Close all Electron instances
  2. Kill any Node processes: taskkill /F /IM electron.exe (Windows)
  3. Run pnpm run install-app-deps
  4. Try packaging again: pnpm run package
Problem: Electron opens but shows blank windowSolution:
  1. Ensure Next.js dev server is running on port 3000
  2. Check electron/main.ts loads correct URL
  3. Open DevTools: Ctrl+Shift+I (Windows) or Cmd+Option+I (Mac)
  4. Check console for errors
Problem: PowerShell blocks script executionSolution:
# Use .cmd wrapper instead
pnpm.cmd run electron:dev
pnpm.cmd run sidecar:build

# Or enable script execution (admin required)
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser

Best Practices

Development

  • Use electron:dev for hot reloading
  • Test on all target platforms
  • Keep native modules updated
  • Profile performance regularly

Production

  • Test packaged builds before release
  • Code sign applications
  • Use auto-update mechanism
  • Monitor crash reports

Security

  • Enable context isolation
  • Disable Node integration in renderer
  • Validate all IPC messages
  • Use secure storage (keytar)

Performance

  • Lazy load components
  • Optimize bundle size
  • Cache expensive operations
  • Use native modules wisely

Next Steps