Architecture
Architecture
Section titled “Architecture”This document provides a comprehensive overview of MiniFy’s technical architecture, helping developers understand how the different parts of the application work together.
High-Level System Architecture
Section titled “High-Level System Architecture”┌─────────────────────────────────────────────────────────────────────────────┐│ MiniFy System Architecture │├─────────────────────────────────────────────────────────────────────────────┤│ ││ ┌───────────────────────────────────────────────────────────────────┐ ││ │ MiniFy Monorepo │ ││ │ │ ││ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ ││ │ │ apps/desktop │ │ apps/www │ │ apps/docs │ │ ││ │ │ Tauri + React │ │ Next.js │ │ Starlight │ │ ││ │ │ Desktop App │ │ Website │ │ Documentation │ │ ││ │ └────────┬────────┘ └────────┬────────┘ └────────┬────────┘ │ ││ │ │ │ │ │ ││ └────────────┼────────────────────┼────────────────────┼───────────┘ ││ │ │ │ ││ ▼ ▼ ▼ ││ ┌─────────────────────────────────────────────────────────────────────┐ ││ │ Build & Development Tools │ ││ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ ││ │ │ pnpm │ │ Turborepo│ │ Biome │ │ Oxlint │ │ ││ │ │ Workspace│ │ (Tasks) │ │ Format │ │ (Lint) │ │ ││ │ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │ ││ └─────────────────────────────────────────────────────────────────────┘ ││ │└──────────────────────────────────────────────────────────────────────────────┘Monorepo Structure
Section titled “Monorepo Structure”MiniFy uses a monorepo architecture with pnpm workspaces:
MiniFy/├── apps/│ ├── desktop/ # Tauri + React desktop application│ │ ├── src/ # React frontend code│ │ ├── src-tauri/ # Rust backend code│ │ ├── public/ # Static assets│ │ └── package.json│ ││ ├── www/ # Next.js marketing website│ │ ├── app/ # Next.js App Router pages│ │ ├── components/ # React components│ │ └── package.json│ ││ └── docs/ # Astro Starlight documentation│ ├── src/content/ # MDX documentation files│ └── package.json│├── package.json # Root package with workspace scripts├── pnpm-workspace.yaml # Workspace configuration├── turbo.json # Turborepo task configuration└── biome.json # Code formatting/linting configDesktop Application Architecture
Section titled “Desktop Application Architecture”The desktop app is the core of MiniFy, built with Tauri 2.0 (Rust backend) and React (TypeScript frontend).
Component Layers
Section titled “Component Layers”┌─────────────────────────────────────────────────────────────────────────────┐│ Desktop Application Layers │├─────────────────────────────────────────────────────────────────────────────┤│ ││ ┌───────────────────────────────────────────────────────────────────────┐ ││ │ Presentation Layer (React) │ ││ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌──────────────┐ │ ││ │ │ Views │ │ Layouts │ │ Components │ │ Hooks │ │ ││ │ │ • Player │ │ • LayoutA │ │ • Button │ │ • usePlaying │ │ ││ │ │ • Settings │ │ • LayoutB │ │ • Controls │ │ • useTheme │ │ ││ │ │ • AI DJ │ │ • LayoutC │ │ • TrackInfo │ │ • useLayout │ │ ││ │ └─────────────┘ └─────────────┘ └─────────────┘ └──────────────┘ │ ││ └───────────────────────────────────────────────────────────────────────┘ ││ │ ││ ▼ ││ ┌───────────────────────────────────────────────────────────────────────┐ ││ │ Service Layer (TypeScript) │ ││ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────────┐ │ ││ │ │ spotifyClient │ │ aiClient │ │ settingLib │ │ ││ │ │ (API Calls) │ │ (AI Provider) │ │ (Config Mgmt) │ │ ││ │ └─────────────────┘ └─────────────────┘ └─────────────────────┘ │ ││ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────────┐ │ ││ │ │ spotifyTools │ │ playerState │ │ themeLoader │ │ ││ │ │ (AI Tools) │ │ (State Store) │ │ (Theme Loading) │ │ ││ │ └─────────────────┘ └─────────────────┘ └─────────────────────┘ │ ││ └───────────────────────────────────────────────────────────────────────┘ ││ │ ││ Tauri IPC │ invoke() / listen() ││ ▼ ││ ┌───────────────────────────────────────────────────────────────────────┐ ││ │ Backend Layer (Rust) │ ││ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────────┐ │ ││ │ │ spotify_auth │ │ ai_keyring │ │ settings │ │ ││ │ │ (OAuth PKCE) │ │ (AI Key Mgmt) │ │ (JSON Config) │ │ ││ │ └─────────────────┘ └─────────────────┘ └─────────────────────┘ │ ││ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────────┐ │ ││ │ │ resize │ │ custom_themes │ │ debug │ │ ││ │ │ (Window Size) │ │ (Theme IO) │ │ (DevTools) │ │ ││ │ └─────────────────┘ └─────────────────┘ └─────────────────────┘ │ ││ └───────────────────────────────────────────────────────────────────────┘ ││ │ ││ ▼ ││ ┌───────────────────────────────────────────────────────────────────────┐ ││ │ OS Integration Layer │ ││ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────────┐ │ ││ │ │ Keyring │ │ File System │ │ WebView │ │ ││ │ │ (Credentials) │ │ (Settings) │ │ (UI Renderer) │ │ ││ │ └─────────────────┘ └─────────────────┘ └─────────────────────┘ │ ││ └───────────────────────────────────────────────────────────────────────┘ ││ │└──────────────────────────────────────────────────────────────────────────────┘Frontend Structure
Section titled “Frontend Structure”apps/desktop/src/├── main.tsx # Application entry point├── vite-env.d.ts # Vite type definitions│├── ui/│ ├── index.tsx # Root React component│ ├── global.css # Global styles with CSS variables│ ├── spotifyClient.ts # Spotify API client│ ││ ├── views/ # Full-page view components│ │ ├── PlayerView.tsx # Main player view│ │ ├── AIDJView.tsx # AI DJ chat interface│ │ ├── SettingsView.tsx # Settings panel│ │ └── ...│ ││ ├── layouts/ # Player layout variations│ │ ├── LayoutA.tsx # Compact horizontal layout│ │ ├── LayoutB.tsx # Standard layout│ │ └── LayoutC.tsx # Expanded layout│ ││ └── components/ # Reusable UI components│ ├── Button.tsx│ ├── TrackControls/│ ├── TrackDataComponent/│ └── LayoutTrackInfo/│├── hooks/ # React hooks│ ├── useCurrentlyPlaying.ts # Playback state hook│ └── useWindowLayout.ts # Layout management hook│├── lib/ # Utility libraries│ ├── aiClient.ts # AI provider client│ ├── playerState.ts # Player state management│ ├── settingLib.ts # Settings utilities│ ├── spotifyTools.ts # AI DJ Spotify tools│ └── trackInfoProps.ts # Track info type definitions│├── loader/ # Data loaders│ └── themeLoader.ts # Theme loading utilities│├── themes/ # Built-in theme definitions│ ├── dark.json│ ├── light.json│ ├── catppuccin.json│ ├── dracula.json│ └── ...│└── config/ # Configuration files └── shortcuts.json # Keyboard shortcut definitionsBackend Structure (Rust)
Section titled “Backend Structure (Rust)”apps/desktop/src-tauri/├── Cargo.toml # Rust dependencies├── Cargo.lock # Dependency lockfile├── build.rs # Build script├── tauri.conf.json # Tauri configuration│├── src/│ ├── main.rs # Application entry point│ ├── lib.rs # Library entry, command registration│ ││ ├── spotify_auth.rs # Spotify OAuth PKCE implementation│ │ - OAuth flow management│ │ - Token storage/retrieval│ │ - Token refresh logic│ │ - Callback server│ ││ ├── ai_keyring.rs # AI API key management│ │ - Key storage per provider│ │ - Key retrieval│ │ - Provider listing│ ││ ├── settings.rs # Settings management│ │ - Settings file IO│ │ - Default settings│ │ - Settings structure│ ││ ├── resize.rs # Window size management│ │ - Layout-based sizing│ │ - Window constraints│ ││ ├── custom_themes.rs # Custom theme handling│ │ - Theme file IO│ │ - Theme validation│ │ - Theme export│ ││ └── debug.rs # Debug utilities│ - DevTools opening│├── capabilities/ # Tauri capability configs│ └── default.json # Default permissions│└── icons/ # Application icons ├── icon.ico ├── icon.icns └── ...Data Flow Diagrams
Section titled “Data Flow Diagrams”Playback State Flow
Section titled “Playback State Flow”┌─────────────────────────────────────────────────────────────────────────────┐│ Playback State Flow │├─────────────────────────────────────────────────────────────────────────────┤│ ││ ┌────────────────┐ ││ │ useCurrently │ Polls every 1-5 seconds ││ │ Playing Hook │ (adjusts based on playback state) ││ └───────┬────────┘ ││ │ ││ ▼ ││ ┌────────────────┐ ┌────────────────┐ ┌────────────────────┐ ││ │ spotifyClient │─────▶│ Spotify API │─────▶│ CurrentlyPlaying │ ││ │ fetchCurrent() │ │ /v1/me/player │ │ Response │ ││ └────────────────┘ └────────────────┘ └─────────┬──────────┘ ││ │ ││ ▼ ││ ┌────────────────────┐ ││ │ State Update │ ││ │ { track, progress,│ ││ │ isPlaying } │ ││ └─────────┬──────────┘ ││ │ ││ ┌──────────────────────────────────┘ ││ ▼ ││ ┌────────────────┐ ┌────────────────┐ ┌────────────────┐ ││ │ Layout │ │ Track │ │ Progress │ ││ │ Component │ │ Controls │ │ Bar │ ││ │ (re-render) │ │ (re-render) │ │ (re-render) │ ││ └────────────────┘ └────────────────┘ └────────────────┘ ││ │└──────────────────────────────────────────────────────────────────────────────┘Token Refresh Flow
Section titled “Token Refresh Flow”┌─────────────────────────────────────────────────────────────────────────────┐│ Token Refresh Flow │├─────────────────────────────────────────────────────────────────────────────┤│ ││ ┌─────────────────────────────────────────────────────────────────────┐ ││ │ Background Task (Every 5 min) │ ││ │ │ ││ │ ┌─────────────┐ │ ││ │ │ Check token │ │ ││ │ │ expiry time │ │ ││ │ └──────┬──────┘ │ ││ │ │ │ ││ │ ▼ │ ││ │ ┌─────────────────────────┐ │ ││ │ │ Expires within 5 min? │ │ ││ │ └──────┬──────────────────┘ │ ││ │ │ │ ││ │ No │ Yes │ ││ │ ▼ ▼ │ ││ │ Done ┌─────────────────┐ ┌─────────────────┐ │ ││ │ │ refresh_token() │─────▶│ Spotify Token │ │ ││ │ │ (Rust backend) │ │ Endpoint │ │ ││ │ └─────────────────┘ └────────┬────────┘ │ ││ │ │ │ ││ │ ▼ │ ││ │ ┌─────────────────┐ │ ││ │ │ New Access Token│ │ ││ │ │ (Maybe new │ │ ││ │ │ refresh token) │ │ ││ │ └────────┬────────┘ │ ││ │ │ │ ││ │ ▼ │ ││ │ ┌─────────────────┐ │ ││ │ │ Store in │ │ ││ │ │ OS Keyring │ │ ││ │ └─────────────────┘ │ ││ │ │ ││ └──────────────────────────────────────────────────────────────────────┘ ││ │└──────────────────────────────────────────────────────────────────────────────┘Settings Data Flow
Section titled “Settings Data Flow”┌─────────────────────────────────────────────────────────────────────────────┐│ Settings Data Flow │├─────────────────────────────────────────────────────────────────────────────┤│ ││ React Frontend Rust Backend ││ ────────────── ──────────── ││ ││ ┌────────────────┐ ┌────────────────────┐ ││ │ Settings View │ │ settings.rs │ ││ │ Component │ │ │ ││ └───────┬────────┘ │ Tauri Commands: │ ││ │ │ • read_settings │ ││ │ invoke("read_settings") │ • write_settings │ ││ ├───────────────────────────▶│ • clear_settings │ ││ │ │ │ ││ │◀──────────────────────────│ Returns Settings │ ││ │ Settings JSON │ struct │ ││ │ └─────────┬──────────┘ ││ │ │ ││ ┌───────▼────────┐ │ ││ │ Update local │ ▼ ││ │ React state │ ┌─────────────────────────┐ ││ └───────┬────────┘ │ File System │ ││ │ │ ~/.config/MiniFy/ │ ││ │ User makes changes │ settings.json │ ││ ▼ └─────────────────────────┘ ││ ┌────────────────┐ ││ │ Update state │ ││ │ + invoke │ ││ │ write_settings │ ││ └────────────────┘ ││ │└──────────────────────────────────────────────────────────────────────────────┘Communication Patterns
Section titled “Communication Patterns”Frontend → Backend (Tauri Commands)
Section titled “Frontend → Backend (Tauri Commands)”Commands are synchronous request-response calls:
// Frontend: Invoke a Tauri commandimport { invoke } from '@tauri-apps/api/core';
// Reading settingsconst settings = await invoke<Settings>('read_settings');
// Saving an AI keyawait invoke('save_ai_api_key', { provider: 'openai', apiKey: 'sk-...'});
// Starting OAuth flowawait invoke('start_oauth_flow');// Backend: Define a Tauri command#[tauri::command]pub fn read_settings() -> Settings { // Load and return settings let path = get_settings_path(); // ...}
#[tauri::command]pub async fn save_ai_api_key(provider: String, api_key: String) -> Result<(), String> { // Save key to keyring // ...}Backend → Frontend (Events)
Section titled “Backend → Frontend (Events)”Events are one-way notifications from backend to frontend:
// Backend: Emit an eventuse tauri::Emitter;
#[tauri::command]fn complete_auth(app: tauri::AppHandle) -> Result<(), String> { // After successful auth... app.emit("oauth-success", serde_json::json!({}))?; Ok(())}
// On auth failure...app.emit("oauth-failed", serde_json::json!({ "error": "reason" }))?;// Frontend: Listen for eventsimport { listen } from '@tauri-apps/api/event';
await listen('oauth-success', (event) => { console.log('Auth successful!'); // Update UI state});
await listen('oauth-failed', (event) => { console.error('Auth failed:', event.payload.error); // Show error to user});State Management
Section titled “State Management”MiniFy uses React’s built-in state management with custom hooks:
Player State
Section titled “Player State”// useCurrentlyPlaying hookinterface CurrentlyPlayingState { track: SimplifiedTrack | null; progress_ms: number; duration: number; isPlaying: boolean; loading: boolean; error: string | null;}
function useCurrentlyPlaying() { const [state, setState] = useState<CurrentlyPlayingState>(initialState);
useEffect(() => { const poll = async () => { const data = await fetchCurrentlyPlaying(); setState(/* updated state */); };
const interval = setInterval(poll, pollInterval); return () => clearInterval(interval); }, []);
return state;}Settings State
Section titled “Settings State”// Settings are loaded via Tauri commandsconst settings = await readSettings(); // invoke('read_settings')
// And saved on changeawait writeSettings(newSettings); // invoke('write_settings', { settings })Key Technologies
Section titled “Key Technologies”Tauri 2.0
Section titled “Tauri 2.0”Tauri provides the native shell for the application:
| Feature | Description |
|---|---|
| Webview | System webview renders React UI (WebView2/WebKit) |
| IPC | Type-safe communication between frontend/backend |
| Plugins | fs, opener plugins for system integration |
| Security | Capability-based permission system |
React 18
Section titled “React 18”Frontend uses modern React patterns:
| Pattern | Usage |
|---|---|
| Functional Components | All components are functions with hooks |
| CSS Variables | Theming via CSS custom properties |
| Concurrent Features | useTransition for non-blocking updates |
Backend handles secure operations:
| Module | Purpose |
|---|---|
| keyring | Secure credential storage |
| reqwest | HTTP client for OAuth |
| axum | OAuth callback server |
| serde | JSON serialization |
Build Process
Section titled “Build Process”Development
Section titled “Development”pnpm desktop:devThis starts:
- Vite dev server with HMR (Hot Module Replacement)
- Tauri development window
- Rust compilation in debug mode
Production
Section titled “Production”pnpm desktop:buildBuild outputs:
- Optimized React bundle (Vite)
- Platform-specific installer (Tauri)
- Code signing (if configured)
Output locations:
- Windows:
src-tauri/target/release/bundle/msi/*.msi - macOS:
src-tauri/target/release/bundle/dmg/*.dmg - Linux:
src-tauri/target/release/bundle/deb/*.deb
Performance Considerations
Section titled “Performance Considerations”Bundle Size
Section titled “Bundle Size”| Component | Target | Actual |
|---|---|---|
| React bundle (gzipped) | < 200KB | ~150KB |
| Rust binary | < 10MB | ~8MB |
| Total download | < 15MB | ~10MB |
Runtime Performance
Section titled “Runtime Performance”| Metric | Target | Notes |
|---|---|---|
| Memory usage | < 50MB | Rust backend is lightweight |
| CPU idle | < 1% | Efficient polling intervals |
| Startup time | < 1s | Native app, no Electron overhead |
| API polling | 1-5s | Adjusts based on playback state |
Optimization Techniques
Section titled “Optimization Techniques”- Lazy loading: AI DJ view loads on demand
- Polling optimization: Faster polling when playing, slower when paused
- Image caching: Album art cached in memory
- Minimal re-renders: Component memoization where needed