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 |