Lowkey

Lowkey Documentation

Desktop Application

Lowkey's desktop application is built with Tauri 2 and React.

Technology Stack

Layer Technology Purpose
Framework Tauri 2 Cross-platform desktop runtime
Frontend React 19 + TypeScript UI components
Build Vite Fast development and bundling
Styling CSS Custom Properties Design system
State React Context Global state management

Directory Structure

apps/desktop/
├── src/
│   ├── main.tsx              # React entry point
│   ├── App.tsx               # Root component
│   ├── app/
│   │   └── state.tsx         # AppState context and reducer
│   ├── screens/
│   │   ├── ColdStart.tsx     # Initial setup wizard
│   │   ├── Home.tsx          # Main dashboard
│   │   ├── Network.tsx       # Network status
│   │   ├── Library.tsx       # Shared files
│   │   ├── FilePreview.tsx   # File viewer
│   │   └── Settings.tsx      # Configuration
│   ├── ui/
│   │   ├── Buttons.tsx       # Button components
│   │   ├── Cards.tsx         # Card components
│   │   ├── AudioPlayer.tsx   # Custom audio player
│   │   └── Sidebar.tsx       # Navigation sidebar
│   └── lib/
│       └── tauri.ts          # Type-safe IPC bindings
├── src-tauri/
│   ├── src/main.rs           # Tauri commands
│   ├── Cargo.toml
│   └── tauri.conf.json       # Tauri configuration
└── package.json

Tauri IPC

Command Definitions (Rust)

#[tauri::command]
async fn engine_start_with_config(
    state: State<'_, AppState>,
    config: EngineConfig,
) -> Result<(), String> {
    let mut engine = state.engine.lock().await;
    engine.start_with_config(config)
        .map_err(|e| e.to_string())
}

#[tauri::command]
async fn engine_share_file(
    state: State<'_, AppState>,
    file_path: String,
    title: String,
) -> Result {
    let engine = state.engine.lock().await;
    engine.share_file(&file_path, &title)
        .map_err(|e| e.to_string())
}

#[tauri::command]
async fn engine_search(
    state: State<'_, AppState>,
    query: String,
) -> Result, String> {
    let engine = state.engine.lock().await;
    engine.search(&query)
        .map_err(|e| e.to_string())
}

TypeScript Bindings

// lib/tauri.ts
import { invoke } from '@tauri-apps/api/core';

export async function engineStartWithConfig(
    config: EngineConfig
): Promise {
    await invoke('engine_start_with_config', { config });
}

export async function engineShareFile(params: {
    filePath: string;
    title: string;
}): Promise {
    return invoke('engine_share_file', params);
}

export async function engineSearch(
    query: string
): Promise {
    return invoke('engine_search', { query });
}

export async function engineGetStreamUrl(
    fileId: string
): Promise {
    return invoke('engine_get_stream_url', { fileId });
}

Screens

Application Routes

Route Screen Purpose
coldStart ColdStart Initial setup wizard
home Home Dashboard with search and share
network Network Peer connections and stats
library Library User's shared files
preview FilePreview File viewer with media player
settings Settings Privacy mode configuration

State Management

interface AppState {
    route: AppRoute;
    config: EngineConfig | null;
    status: EngineStatus | null;
    logs: LogEntry[];
    search: {
        query: string;
        results: SearchResult[];
        searching: boolean;
    };
    selected: {
        file: FileInfo | null;
    };
    share: {
        sharing: boolean;
        lastShared: string | null;
    };
    toasts: Toast[];
}

Media Streaming

HTTP Streaming (Windows/Linux)

const streamUrl = await engineGetStreamUrl(fileId);
// Returns: http://127.0.0.1:54321/stream/{file_id}

// Use in video/audio element

Asset Protocol (macOS)

macOS WebKit blocks localhost HTTP. Uses Tauri's asset protocol instead:

import { convertFileSrc } from '@tauri-apps/api/core';
import { platform } from '@tauri-apps/plugin-os';

async function getMediaSource(fileId: string): Promise {
    const currentPlatform = await platform();

    if (currentPlatform === 'macos') {
        // Download to temp, serve via asset protocol
        const tempPath = await downloadToTemp(fileId);
        return convertFileSrc(tempPath);
    } else {
        // Use HTTP streaming
        return engineGetStreamUrl(fileId);
    }
}

Tauri Plugins

Plugin Purpose
@tauri-apps/plugin-dialog File picker, save dialog
@tauri-apps/plugin-process App restart
@tauri-apps/plugin-log Logging
@tauri-apps/plugin-fs File system access
@tauri-apps/plugin-os Platform detection

Development Commands

# Development with hot reload
npm run tauri:dev

# Production build
npm run tauri:build

# Frontend only (no Tauri)
npm run dev

# Linting
npm run lint

Build Artifacts

Platform Artifact
Windows Lowkey_x64-setup.exe
macOS Lowkey_universal.dmg
Linux lowkey_amd64.deb