- Twig updater: multiple partitions could prove VERY difficult. idk how to address this.
- The info could be centered vertically in the space below the button instead of straddling it?
- Checkboxes for various additional packages:
- all themes
- all A30 ports
- all free games
- PortMaster (are we making this a separate archive?)
- Backup and restore (update current installation instead of just fresh ones?)
- Scrape boxart for roms
- ✅ Asset Selection - Installer now intelligently handles multiple downloads from a single release
- ✅ Repository Info - Each repository can display custom information text in the UI
- ✅ Bug Fixes - Fixed modal dialog freeze issue and cancellation state handling
SpruceOS Installer is an all-in-one downloader, extractor, formatter, and installer made for SpruceOS.
It can be easily edited and adapted to work with any custom firmware (CFW) that requires files to be copied onto a FAT32 SD card, with little to no hassle.
GitHub Actions are set up to automatically build and create releases per branch.
If you’d like to use this program for your own project, let us know—we can create a branch for you or add you directly to the repository.
Please do not remove the Spruce or NextUI teams from the authors section.
Instead, add your name alongside the existing credits.
The installer is distributed as a .zip containing a self-contained .app bundle. No system installation is required.
Steps to run:
-
Download the ZIP file from the GitHub release.
-
Extract the ZIP — you will get the following bundle and files:
SpruceOS Installer.app/ ├── Contents/ │ ├── MacOS/ │ │ └── spruceos-installer │ ├── Info.plist │ └── Resources/ │ └── AppIcon.icns
SpruceOS Installer is an all-in-one Rust installer for flashing SD cards with SpruceOS (or other custom firmware).
This guide is intended for developers who want to rebrand or customize the installer for their own OS project.
Note: All builds are handled automatically via GitHub Actions.
Developers only need to create their own branch with the desired customizations — no local build setup is required.
To adapt this installer for your project, update the following in your branch:
Edit these constants:
| Field | Purpose | Example |
|---|---|---|
APP_NAME |
Display name of your OS (window title, UI) | "SpruceOS" |
VOLUME_LABEL |
FAT32 SD card label (max 11 chars, uppercase) | "SPRUCEOS" |
REPO_OPTIONS |
Array of repository configurations (see below) | See example below |
DEFAULT_REPO_INDEX |
Index of the default repo selection (0 = first) | 0 |
WINDOW_SIZE |
Default window size (width, height) | (679.5, 420.0) |
WINDOW_MIN_SIZE |
Minimum window size (width, height) | (679.5, 420.0) |
Repository Configuration (REPO_OPTIONS):
Each repository is defined using a RepoOption struct with three fields:
name: Display name shown in the UI button (e.g., "Stable", "Nightlies")url: GitHub repository in "owner/repo" format (e.g., "spruceUI/spruceOS")info: Description text shown below the Install button when selected. Use\nfor line breaks.
Example:
pub const REPO_OPTIONS: &[RepoOption] = &[
RepoOption {
name: "Stable",
url: "spruceUI/spruceOS",
info: "Stable releases of spruceOS.\nSupported devices: Device X, Device Y",
},
RepoOption {
name: "Nightlies",
url: "spruceUI/spruceOSNightlies",
info: "Nightly development builds.\n⚠️ Warning: May be unstable!",
},
];Asset Detection:
The installer automatically detects and downloads compatible files from GitHub releases:
- Archive mode:
.7z,.zip(formats SD card, extracts, and copies files) - Image mode:
.img.gz,.img.xz,.img(burns raw image directly to device) - Source code archives (
Source code.zip,Source code.tar.gz) are automatically filtered out - If multiple assets exist, the installer will prompt the user to select one, or auto-select based on file type priority
Notes:
WINDOW_TITLE,USER_AGENT, andTEMP_PREFIXare auto-generated fromAPP_NAME. You usually do not need to change these.- The
setup_theme()function inconfig.rsuses the Gruvbox Dark preset. This is a fallback; the actual theme is customized inapp.rs.ASSET_EXTENSIONconstant still exists for backward compatibility but is deprecated and no longer used.
The installer's visual theme is defined in the get_theme_config() method (around line 136 in app.rs). This method returns a ThemeConfig with color overrides in RGBA format [R, G, B, A] (values 0-255).
Key color fields to customize:
| Field | Purpose | SpruceOS Default (RGBA) |
|---|---|---|
override_text_color |
Primary text color | [251, 241, 199, 255] (cream) |
override_weak_text_color |
Secondary/dimmed text | [124, 111, 100, 255] (gray) |
override_hyperlink_color |
Clickable links | [131, 165, 152, 255] (teal) |
override_faint_bg_color |
Input fields, panels | [48, 48, 48, 255] (dark gray) |
override_extreme_bg_color |
Window background | [29, 32, 33, 255] (near black) |
override_warn_fg_color |
Warning messages | [214, 93, 14, 255] (orange) |
override_error_fg_color |
Error messages | [204, 36, 29, 255] (red) |
override_selection_bg |
Text selection, highlights | [215, 180, 95, 255] (gold) |
override_widget_inactive_bg_fill |
Inactive buttons | [215, 180, 95, 255] (gold) |
override_widget_inactive_fg_stroke_color |
Inactive button border | [104, 157, 106, 255] (green) |
override_widget_hovered_bg_stroke_color |
Hovered button border | [215, 180, 95, 255] (gold) |
override_widget_active_bg_stroke_color |
Active button border | [215, 180, 95, 255] (gold) |
Note: Set a field to
Noneto use the default egui value. The theme config has many more fields for fine-grained control — see the full list in theThemeConfigstruct.
Hardcoded UI colors (also in app.rs):
- Line ~1036, 1097: Success message color
Color32::from_rgb(104, 157, 106)(green) - Line ~1397: Install button fill
Color32::from_rgb(104, 157, 106)(green) - Line ~1417: Cancel button fill
Color32::from_rgb(251, 73, 52)(red)
To change these, search for Color32::from_rgb in app.rs and update the RGB values.
Customize the application icon:
| Icon | Path | Usage |
|---|---|---|
| PNG | assets/Icons/icon.png |
Window, title bar (all platforms) |
| ICO | assets/Icons/icon.ico |
Windows Explorer, taskbar |
Notes:
- PNG: Recommended 64x64 or 128x128 with transparency
- ICO: Multi-resolution preferred (16x16, 32x32, 48x48, 256x256)
- The icon is loaded via
APP_ICON_PNGinconfig.rs(requires theiconfeature enabled)
The installer uses a custom font for all UI text. To use your own font:
Replace the font file:
# Replace the existing font with your own TTF/OTF file
cp /path/to/your/font.ttf assets/Fonts/nunwen.ttfUpdate the font configuration in src/config.rs:
| Constant | Purpose | Default |
|---|---|---|
CUSTOM_FONT |
Path to the embedded font file | "../assets/Fonts/nunwen.ttf" |
CUSTOM_FONT_NAME |
Display name for the font (optional, cosmetic) | "Nunwen" |
Example:
// If you want to use a different filename:
pub const CUSTOM_FONT: &[u8] = include_bytes!("../assets/Fonts/YourFont.ttf");
pub const CUSTOM_FONT_NAME: &str = "YourFont";Notes:
- Supports TTF and OTF font formats
- The font is embedded in the binary, so no external font files are needed at runtime
- The custom font applies to all UI text (buttons, labels, dropdowns, etc.)
- To also use the font for monospace text (logs), uncomment the Monospace section in
load_custom_fonts()
To fully rebrand the installer, also update:
Cargo.toml—name,description,authorsassets/Mac/Info.plist—CFBundleName,CFBundleDisplayName,CFBundleIdentifier.github/workflows/*.yml— Artifact names (optional cosmetic change)
- Internal Identifiers (
WINDOW_TITLE,USER_AGENT,TEMP_PREFIX) are auto-generated fromAPP_NAME; modifying them is optional. setup_theme(ctx)inconfig.rsis a fallback that applies the Gruvbox Dark preset. The actual theme used by the installer is defined inapp.rsviaget_theme_config().REPO_OPTIONScan include multiple repos (e.g., stable, nightlies, forks). The user can select between them via button tabs in the UI. Each repo'sinfotext is displayed below the Install button.- The installer uses
eguiandegui_thematicfor the UI. The theme can be edited live using the built-in theme editor (press Ctrl+T in the app). - All color values in
ThemeConfiguse RGBA format[R, G, B, A]where each value is 0-255. - Asset Selection: When a release contains multiple downloadable files, the installer intelligently handles them:
- Single asset → Auto-proceeds to installation
- Multiple files with same base name (different extensions) → Auto-selects by priority (.7z > .zip > .img.gz > .img.xz > .img)
- Multiple different files → Shows selection modal for user to choose
- Source code archives are automatically filtered out
- Fork or clone the repository.
- Create a new branch for your customizations (or use an existing branch).
- Update
src/config.rs:- Set
APP_NAMEto your OS name (e.g.,"MyOS") - Set
VOLUME_LABELto your SD card label (max 11 chars, e.g.,"MYOS") - Update
REPO_OPTIONSwith your GitHub repositories:pub const REPO_OPTIONS: &[RepoOption] = &[ RepoOption { name: "Stable", url: "yourorg/yourrepo", info: "Description shown in UI.\nSupported devices: X, Y, Z", }, ];
- Set
- Replace
assets/Icons/icon.pngandicon.icowith your branding - (Optional) Replace
assets/Fonts/nunwen.ttfwith your custom font - Update
Cargo.tomlandassets/Mac/Info.plistwith your project info - Push your branch to GitHub.
GitHub Actions will automatically build Windows, Linux (x64 + ARM64), and macOS (ARM64 + x64) binaries — no local build setup required.
The installer includes a built-in theme editor that lets you customize colors visually and export the theme config directly. This is much faster than manually editing RGBA values in code.
First, build the installer locally so you can use the theme editor:
# Install Rust if you haven't already
# https://rustup.rs/
# Clone and build
git clone https://github.com/spruceUI/spruceOS-Installer.git
cd spruceOS-Installer
cargo runWith the installer running, press Ctrl+T to open the theme editor panel. This will open on the right side of the window.
The theme editor provides:
- Color pickers for all theme elements (text, backgrounds, borders, buttons, etc.)
- Live preview — changes apply immediately to the UI
- RGBA sliders for precise color control
- Preset themes you can use as starting points
Adjust the colors until you're happy with how the installer looks with your branding.
At the bottom of the theme editor panel, there's a "Copy Theme Config" button (or similar export option). Click it to copy the complete ThemeConfig struct to your clipboard.
The copied output will look like this:
ThemeConfig {
name: "YourTheme".to_string(),
dark_mode: true,
override_text_color: Some([251, 241, 199, 255]),
override_weak_text_color: Some([124, 111, 100, 255]),
// ... all other color overrides
}- Open
src/app.rsand find theget_theme_config()method (around line 136) - Replace the entire
ThemeConfig { ... }block with your copied config - Update the
namefield to match your project name - Save the file
Some UI elements use hardcoded colors outside the theme system. Search for Color32::from_rgb in app.rs to find and update:
- Line ~1036, 1097: Success message green
(104, 157, 106) - Line ~1397: Install button green
(104, 157, 106) - Line ~1417: Cancel button red
(251, 73, 52)
Replace the RGB values to match your brand colors.
# Test your changes
cargo run
# Commit and push to your branch
git add src/app.rs
git commit -m "Update theme colors for [YourProject]"
git pushGitHub Actions will automatically build your customized installer for all platforms.
- Start with a preset: The theme editor includes several presets (Gruvbox, Solarized, etc.). Pick one close to your brand and adjust from there.
- Test readability: Make sure text is readable against backgrounds, especially for secondary text colors.
- Match your brand: Use your project's official brand colors for accents, buttons, and highlights.
- Check all states: Interact with buttons, dropdowns, and inputs to see hover/active/inactive states.
- Dark mode only: The installer currently only supports dark themes. Light theme support is not implemented.
PLEASE: Keep the original spruceOS authors in
Cargo.tomlandInfo.plistfor credit. Add your name alongside ours.