Build & Deployment
Audience: End users, system administrators, technical stakeholders Last Updated: 2026-04-06 Version: 2.0.0
Table of Contents
- Overview
- Supported Platforms
- How Builds Work
- Version Management
- Web & PWA Build
- Mobile Builds
- Desktop Builds
- Offline & Caching (PWA)
- Build Optimizations
- Browser Support
- Technical Specifications
- Security Considerations
- Known Limitations
- Related Documentation
Overview
Llamafin is built as a single codebase that compiles to four different platforms: Web (as a Progressive Web App), Android, iOS, and Desktop (Windows, macOS, Linux). The build system uses Angular 16 as the core framework, Capacitor 5 for mobile bridging, and Electron 25 for desktop applications.
Why It Matters
A unified build system means:
- Consistent Features: Every platform gets the same features and bug fixes
- Faster Updates: A single code change propagates to all platforms
- Shared Testing: Unit tests validate the core logic across all platforms
- Simplified Development: Developers maintain one codebase, not four
Build Tools
| Tool | Purpose |
|---|---|
| Angular CLI 16 | Core application bundling, compilation, optimisation |
| esbuild | Bundles background workers (downloads, audio analysis, colour processing) |
| Capacitor 5 | Bridges web code to native mobile APIs (iOS/Android) |
| Electron 25 | Wraps the web app as a standalone desktop application |
| electron-builder | Creates installers (NSIS for Windows, DMG for Mac, .deb/AppImage for Linux) |
Supported Platforms
Platform Matrix
| Platform | Minimum Version | Build Type | Distribution Method |
|---|---|---|---|
| Chrome (Desktop) | 79+ (Dec 2019) | Web/PWA | Direct URL, self-hosted |
| Firefox (Desktop) | 70+ (Oct 2019) | Web/PWA | Direct URL, self-hosted |
| Edge (Desktop) | 79+ (Jan 2020) | Web/PWA | Direct URL, self-hosted |
| Safari (Desktop) | 14+ (Sep 2020) | Web/PWA | Direct URL, self-hosted |
| Chrome (Android) | 79+ | Android App | APK (side-load), Play Store |
| iOS | 14+ (Sep 2020) | iOS App | TestFlight, App Store |
| Windows | 10+ | Desktop App | NSIS installer |
| macOS | 10.15+ | Desktop App | DMG disk image |
| Linux | Modern distros | Desktop App | .deb package, AppImage |
Architecture Support
| Platform | Architectures |
|---|---|
| Android | ARM64, ARMv7, x86_64 |
| iOS | ARM64 (devices), ARM64e (Apple Silicon Macs via Catalyst) |
| Windows | x64, ia32 |
| macOS | x64 (Intel), ARM64 (Apple Silicon) |
| Linux | x64 |
How Builds Work
The Build Process
Every platform shares the same first step: building the web application.
┌─────────────────────────────────────┐
│ Source Code │
│ TypeScript, HTML, SCSS, Assets │
└──────────────┬──────────────────────┘
│
▼
┌─────────────────────────────────────┐
│ Worker Bundling (esbuild) │
│ Background tasks bundled to JS │
└──────────────┬──────────────────────┘
│
▼
┌─────────────────────────────────────┐
│ Angular Production Build │
│ - Compiles TypeScript │
│ - Optimises and minifies │
│ - Generates service worker │
│ - Copies assets │
└──────────────┬──────────────────────┘
│
▼
┌─────────────────────────────────────┐
│ Web Output (www/ folder) │
│ Ready for web server or packaging │
└──────────────┬──────────────────────┘
│
┌──────────┼──────────┬──────────────┐
▼ ▼ ▼ ▼
┌───────┐ ┌────────┐ ┌────────┐ ┌──────────┐
│ Web │ │Android │ │ iOS │ │ Desktop │
│Server │ │ App │ │ App │ │ App │
└───────┘ └────────┘ └────────┘ └──────────┘
Platform-Specific Packaging
After the web app is built, each platform packages it differently:
| Platform | Packaging Tool | What It Does |
|---|---|---|
| Web/PWA | Angular CLI | Serves the www/ folder as a static website with service worker for offline support |
| Android | Gradle + Android Gradle Plugin | Wraps the web app in a WebView, adds native plugins, compiles to APK |
| iOS | Xcode | Wraps the web app in a WebView, adds native plugins, compiles to IPA |
| Desktop | Electron + electron-builder | Wraps the web app in a Chromium window, adds Node.js runtime, creates native installer |
Version Management
Version Numbers
The app uses semantic versioning (MAJOR.MINOR.PATCH):
| Component | Current Version | Notes |
|---|---|---|
| Web App | 2.0.0 | Primary version |
| Desktop App | 1.8.4 | Separate version tracking |
| Android | 2.0.0-beta (versionCode: 8) | Separate version tracking |
| iOS | Managed by Xcode | Set in Xcode project |
Version Bumping
Developers use three commands to increment versions:
| Command | Effect | Example |
|---|---|---|
| Patch bump | Bug fixes only | 2.0.0 → 2.0.1 |
| Minor bump | New features, backward-compatible | 2.0.0 → 2.1.0 |
| Major bump | Breaking changes | 2.0.0 → 3.0.0 |
The -dev suffix is automatically added to the version during development builds (e.g., 2.0.0-dev), and removed for production builds.
Database Version
A separate "database version" (dbVersion: 49) tracks the IndexedDB schema version. This is incremented when the app's local storage structure changes, triggering cache invalidation and data migration on the next app launch.
Web & PWA Build
What You Get
The web build produces a standard Progressive Web App (PWA) that can be:
- Hosted on any web server (Nginx, Apache, static hosting)
- Installed on your device like a native app (Chrome, Edge, Safari)
- Used offline with cached data and downloads
Output Structure
The build output (www/ folder) contains:
| File/Directory | Purpose |
|---|---|
index.html | Entry point |
main.[hash].js | Application code (content-hashed for caching) |
polyfills.[hash].js | Browser compatibility code |
styles.[hash].css | Compiled CSS styles |
ngsw-worker.js | Angular Service Worker (handles offline caching) |
ngsw.json | Service worker configuration (auto-generated) |
manifest.webmanifest | PWA manifest (name, icons, theme colours) |
assets/ | Images, translations, workers |
app/workers/ | Bundled background task workers |
Content Hashing
Every JavaScript and CSS file gets a content hash in its filename (e.g., main.a1b2c3d4.js). This ensures:
- Browser caches are invalidated when files change
- Old versions don't accidentally serve stale code
- Service worker updates only when content actually changes
Mobile Builds
Android
Build Command: npm run build-android
Minimum Requirements:
- Android 6.0 (API level 23) or later
- Target: Android 15 (API level 35)
Build Process:
- Web app is built to
www/folder - Capacitor syncs web assets to the Android project
- Android Studio opens for final build, signing, and testing
Key Settings:
- ProGuard (code shrinking/obfuscation): Disabled
- File sharing: Enabled
- Keyboard handling: Resizes the app body when keyboard appears
Output: APK file for sideloading, or AAB for Play Store submission.
iOS
Build Command: npm run build-ios
Minimum Requirements:
- iOS 14 or later
Build Process:
- Web app is built to
www/folder - Capacitor syncs web assets to the iOS project
- Xcode opens for final build, signing, and testing
Key Settings:
- All screen orientations supported (portrait, landscape)
- File sharing enabled
- Documents can be opened in place
- Minimum device capability: ARMv7
Output: IPA file for TestFlight or App Store submission.
Desktop Builds
Electron Architecture
The desktop app wraps the web app inside a Chromium browser window with a Node.js backend. This provides:
- Native window management (frameless, always-on-top, custom sizing)
- Node.js access (file system, system tray, native menus)
- Audio device management (switch audio outputs natively)
Window Management
The desktop app features two player sizes:
| Mode | Dimensions | Purpose |
|---|---|---|
| Small (default) | 268 × 513 px | Compact music player (Plexamp-style) |
| Expanded | 412 × 660 px | Full player with Visualisations |
Window Properties:
- Frameless (no title bar)
- Always on top
- Resizable via player controls, but not manually
- Not maximizable (designed for compact size)
Installer Types
| Platform | Installer | User Experience |
|---|---|---|
| Windows | NSIS | Custom installer with directory selection, creates Start Menu shortcut |
| macOS | DMG | Disk image — drag app to Applications folder |
| Linux (.deb) | Debian package | Installs via apt or Software Centre |
| Linux (AppImage) | AppImage | Single file, runs without installation |
Desktop-Specific Features
| Feature | Description |
|---|---|
| Audio Output Selection | Choose which audio device to play through (speakers, headphones, DAC) |
| Global Keyboard Shortcuts | Media keys (play/pause, next, previous) work from any app |
| System Tray | App runs in background with tray icon and controls |
| File System Access | Direct access to local files for downloads and library management |
Auto-Update
Status: Not configured. The desktop app does NOT currently have automatic updates. Users must manually download and install new versions.
Offline & Caching (PWA)
How Offline Works
The web app uses Angular's Service Worker to cache files and API responses for offline use.
Caching Strategies
| What's Cached | Strategy | How It Works |
|---|---|---|
| App Code (JS, CSS, HTML) | Cache-first | Always served from cache; updated in background when new version available |
| Assets (images, fonts, icons) | Lazy + update prefetch | Cached when first requested; updated in background |
Album Art & Images (/Items/**/Images) | Cache-first (3 days, 100 entries) | Served from cache if available; falls back to network. Cached for 3 days, up to 100 images. |
Library Data (/Users/**/Items) | Network-first (3 days, 100 entries) | Tries network first (10 second timeout); falls back to cache if network fails. Fresh data preferred. |
Why Two Strategies?
- Cache-first is used for images because they rarely change and look fine when slightly stale. This saves bandwidth and speeds up loading.
- Network-first is used for library data because you want to see the latest albums, playlists, etc. If the network fails, the cached data keeps the app usable.
What Works Offline
| Feature | Offline Support |
|---|---|
| Browse cached library | ✅ Yes |
| Play downloaded music | ✅ Yes |
| View cached album art | ✅ Yes |
| Search cached library | ✅ Yes |
| Play streaming music | ❌ No (requires network) |
| Browse uncached library | ❌ No (requires network) |
| Settings changes | ✅ Yes (stored locally) |
Build Optimizations
What Happens in Production Builds
| optimisation | What It Does | User Benefit |
|---|---|---|
| AOT Compilation | Compiles templates ahead of time | Faster app startup |
| Tree-Shaking | Removes unused code | Smaller download size |
| Minification | Compresses code | Smaller download size |
| Output Hashing | Adds content hash to filenames | Better browser caching |
| Build Optimizer | Removes Angular decorators and metadata | Smaller bundle |
Size Budgets
The build enforces size limits:
| What | Warning | Error |
|---|---|---|
| Initial load | 4 MB | 5 MB |
| Any CSS file | 16 KB | 18 KB |
If the build exceeds these limits, it will warn (or fail) to alert developers that the app is getting too large.
Development vs Production
| Feature | Development Build | Production Build |
|---|---|---|
| Optimised | No | Yes |
| Source Maps | Yes (for debugging) | No |
| Readable Names | Yes | No (minified) |
| Build Speed | Fast | Slow |
| File Size | Large | Small |
Browser Support
Supported Browsers
| Browser | Minimum Version | Release Date |
|---|---|---|
| Chrome (Desktop) | 79 | December 2019 |
| Chrome (Android) | 79 | December 2019 |
| Firefox | 70 | October 2019 |
| Edge (Chromium) | 79 | January 2020 |
| Safari (Desktop) | 14 | September 2020 |
| Safari (iOS) | 14 | September 2020 |
What This Means
- Modern JavaScript: The app uses ES2022 features (optional chaining, nullish coalescing, top-level await)
- Modern CSS: Uses CSS custom properties, grid, flexbox
- Web APIs: Uses Web Audio API, IndexedDB, Service Workers
- No IE11 Support: Internet Explorer is NOT supported
Technical Specifications
Build Configuration
| Property | Value |
|---|---|
| Framework | Angular 16 |
| TypeScript Target | ES2022 |
| Module System | ES2020 |
| Strict Mode | Enabled (full strict, plus additional checks) |
| AOT Compilation | Always enabled |
Dependency Counts
| Category | Count |
|---|---|
| Production Dependencies | ~80 packages |
| Development Dependencies | ~60 packages |
| Local/Custom Dependencies | 8 packages (from sibling directories or private registry) |
Worker Files
| Worker | Purpose | Bundler |
|---|---|---|
| Transcode Download | Transcodes downloaded music | esbuild |
| Concurrent Chunks | Downloads chunks in parallel | esbuild |
| Colour Thief | Extracts dominant colours from images | esbuild |
| Alpha/Beta Test | Feature testing workers | esbuild |
| Sonic Analysis | Audio fingerprinting | Manual concatenation |
Service Worker Caching
| Resource | Max Entries | Max Age | Strategy |
|---|---|---|---|
| Images | 100 | 3 days | Cache-first |
| Library API | 100 | 3 days | Network-first (10s timeout) |
Security Considerations
Content Security Policy (Desktop)
The Electron desktop app uses a very permissive Content Security Policy:
script-src * 'unsafe-inline' 'unsafe-eval';
default-src * blob: data:;
Implications: This allows scripts from any source, inline scripts, and eval() execution. While functional, this is less secure than a locked-down CSP.
Recommendations for Users
- Download from trusted sources only: Only install Llamafin from official channels
- Keep the app updated: Manual updates mean you should check for new versions regularly
- Use HTTPS for web access: When accessing the web version, ensure the server uses HTTPS
Known Limitations
| Limitation | Impact | Workaround |
|---|---|---|
| No automatic desktop updates | Users must manually download new versions | Check for updates periodically |
| Separate version tracking | Web, desktop, and Android have different version numbers | Check the About page in the app for the actual running version |
| ProGuard disabled on Android | Larger APK size, no code obfuscation | None currently |
| No E2E testing | Complex user flows are not automatically tested | Manual testing before releases |
| No CI/CD pipeline | Builds are run manually, not automatically | Follow the build scripts in package.json |
| Hardcoded credentials in config | GitLab token for private packages is in .npmrc | Repository access should be restricted |
Related Documentation
- Platform Support - Detailed platform-specific features and limitations
- Offline Support - How offline mode works with the service worker
- Security Implementation - Security architecture and CSP analysis
- Internationalization - Translation pipeline and language support
Last Updated: 2026-04-06 Version: 2.0.0