Part I — User manual
How to use MAMA
Available pages
Homepage (click the logo, top left)
An overview of current projects and a computer resource overview, plus other quality-of-life widgets as needed.
Setup menu
Run the setup wizard again. It auto-scans your system to determine prerequisites.
Settings
Change several settings about the app. It can also be edited directly in the app files at user/settings.json — it was intentionally designed to be flexible, portable, and easy to access.
Several settings are optional and not needed for core functions, but they are used in several of the app's tests. For example, several installers require the OS field to be filled out, as they determine the system OS via the settings JSON file, and not through other means.
Multimodel design
An easy GUI for designing multi-model systems.
Database explorer
A quality-of-life feature that lets you browse a web database (such as Hugging Face) to easily transfer information from outside sources.
Export model
A page that walks you through exporting a model for any use case. Future aspirations include instant app/website generation (from template, not LLM), Ollama (or other client) exports, and more.
Baby's first project
- Make a directory
- Open the directory with MAMA
- Design a multimodel interface, and save it to the directory
- Click begin training
- Export the model
Themes
The app uses a file-based theme system. Themes are JSON files placed in user/themes/. Each file adds an option to the appearance dropdown in settings.
Built-in themes
The app ships with no built-in theme visible in the dropdown. The only hardcoded palette is a dark fallback that activates automatically when user/themes/ is empty. If the folder has any valid JSON themes, the fallback is replaced.
Adding a theme
Create a new .json file in user/themes/ with this structure:
{
"name": "my-theme",
"title": "My Theme",
"variables": {
"--page-bg": "#ffffff",
"--page-text": "#000000"
}
}
- name — a short identifier (no spaces recommended). Used internally and stored in settings.
- title — what appears in the dropdown menu.
- variables — CSS custom properties that change the app colours.
Once saved, open Settings → Appearance and your theme will appear in the dropdown. No restart needed — just navigate to settings or reload the page.
Example themes
The repo includes three example themes in user/themes/:
light.json— light modedark.json— dark modedark-green.json— dark mode with green accents
You can enable or disable any theme by adding or removing its .json file.
Fallback
If you remove all .json files from user/themes/, the dropdown will show only System and Fallback. The fallback is a default dark palette built into the app.
Part II — Power user guide
The power user's manual
A supplement to the regular user manual, aimed at those past the beginner stage. For in-depth explanations of each component, refer to the developer's guide.
The user folder
The user folder, located at mama/user, holds most of everything the user will need. Most files live here, including those for custom editing.
Framework installation & verification
Installation (install_fw.py)
Handles the installation of PyTorch and TensorFlow via pip.
- Variants: Supports
cuda(NVIDIA),rocm(AMD), andcpu(standard). - Logic: Dynamically builds the installation command based on the requested framework and hardware variant.
- Execution: Uses
subprocess.runto execute the installation, streaming output for real-time monitoring.
Verification (import_test.py)
Verifies the installation and hardware acceleration.
- PyTorch: Checks for CUDA/ROCm availability and prints GPU details (model, VRAM, version).
- TensorFlow: Checks for available physical GPU devices.
- Error handling: Returns exit code
0on success or1onImportError, allowing the pipeline to detect installation failures.
| Feature | PyTorch | TensorFlow |
|---|---|---|
| Install | pip install torch | pip install tensorflow |
| Verification | import torch | import tensorflow |
| Hardware check | CUDA / ROCm / CPU | Physical GPU devices |
| Diagnostics | GPU model & VRAM | Device list |
Setup wizard — modular architecture
The setup wizard (components/setup/setup.js) has been refactored from a single monolithic script into a modular system. Each step of the wizard lives in its own file under components/setup/modules/, and the order is controlled by components/setup/setup.json.
How it works
setup.jsondefines two things:steps— an array of step definitions, each with anid,title, andscriptpath; andsetup_order— an ordered array of step IDs that determines the wizard's navigation sequence.setup.js(the parent loader) fetchessetup.json, loads_shared.js, then loads each step module. After all modules are loaded, it reorderswindow.__setupStepsto matchsetup_order.modules/_shared.jsprovides shared state (window.__setupState), utilities (window.__setupUtils), settings management (window.__setupSettings), and rendering/navigation (window.__setupRender).- Each step module (e.g.,
step-welcome.js,step-framework.js) is an IIFE that pushes a step object with{ id, title, render, afterRender?, collect? }towindow.__setupSteps.
Reordering steps
To change the wizard's step order, edit the setup_order array in setup.json. No JavaScript changes are needed. For example, to move "Language" after "Appearance":
"setup_order": [ "welcome", "appearance", "language", ... ]
Adding a new step
- Create a new file in
components/setup/modules/step-your-step.js. - Add its definition to the
stepsarray insetup.json. - Add its ID to
setup_orderat the desired position.
Custom theming
Themes are set as CSS variables. Each theme is represented as a .json file in user/themes. Each JSON should automatically be added as an entry; duplicates will be ignored.
The values of said themes can be any CSS-accepted color value, in quotations.
Part III — Developer's guide
The developer's guide
The complete guide on every working part of this application, including intended usage.
Framework installation & verification — deep dive
Overview
This module provides the logic for automatically installing deep learning frameworks (PyTorch and TensorFlow) and verifying their installation and hardware acceleration. It is designed to be called by a parent process and provides streamed output for real-time monitoring.
1. Installation phase (install_fw.py)
The installation script handles the mapping between user requirements and the specific pip commands needed.
- Input parsing: Accepts
framework(torch/tf),gpu_variant(cuda/rocm/cpu), and an optionalaccel_version. - Command construction: The
build_command()function determines the correct installation string:- PyTorch: Maps requirements to
torchinstallation strings, including specific wheels for CUDA or ROCm. - TensorFlow: Maps requirements to
tensorflowortensorflow-gpupackages. - CPU fallback: Installs the CPU-only versions of the frameworks.
- PyTorch: Maps requirements to
- Execution: Executes the command using
subprocess.run(). stdout and stderr are inherited, allowing the calling process to capture installation progress in real-time.
2. Verification phase (import_test.py)
After installation, this script ensures the framework is functional and the system hardware is correctly recognized.
- PyTorch verification: Attempts
import torch; NVIDIA path checkstorch.cuda.is_available()and prints CUDA version, GPU count, and per-GPU properties (model name, VRAM); AMD path checkstorch.version.hipand prints ROCm version; CPU path falls back to "CPU only" status. - TensorFlow verification: Attempts
import tensorflow as tf; GPU detection usestf.config.list_physical_devices("GPU")to list all available hardware. - Exit status:
0success ·1ImportErroror critical failure ·2invalid arguments.
| Feature | PyTorch path | TensorFlow path |
|---|---|---|
| Install command | pip install torch (+ variant) | pip install tensorflow (+ variant) |
| Verification | import torch | import tensorflow as tf |
| Hardware check | torch.cuda / torch.version.hip | tf.config.list_physical_devices |
| Diagnostics | GPU model, VRAM, CUDA/HIP version | List of physical GPU devices |
Theme system
Architecture
Themes are stored as JSON files in user/themes/. Each file represents one theme and must contain three fields:
{
"name": "theme-id",
"title": "Display Name",
"variables": {
"--highlight-color": "#00d4ff",
"--main-color": "#1a1a2e"
}
}
- name — unique identifier used as the internal key and stored in settings.
- title — human-readable label shown in the appearance dropdown.
- variables — a flat map of CSS custom properties to values. Each key must start with
--.
Theme loading flow
- Startup —
components/styling/theme.jscallswindow.electron.themesRead()(IPC) on initialization. - Backend —
components/styling/theme-loader.jsreads all.jsonfiles fromuser/themes/, validates structure (name,title,variables), and returns the array. - Renderer —
theme.jsmerges each theme's variables into apaletteslookup byname. - Settings — both the settings page (
components/setup/settings.js) and setup wizard (components/setup/setup.js) callthemesRead()to populate the appearance dropdown.
Fallback behaviour
When user/themes/ is empty or contains no valid .json files, the app falls back to a hidden built-in dark palette. This fallback is never listed in the dropdown — instead a single "Fallback" option appears. The fallback is hardcoded in theme.js as fallbackPalette.
File locations
| File | Purpose |
|---|---|
user/themes/*.json | User-provided theme files |
components/styling/theme-loader.js | Backend module that reads themes from disk |
components/styling/theme.js | Frontend theme manager — applies CSS variables, manages state |
components/backend/ipc/ipc-handlers.js | Registers themes-read IPC handler |
preload.js | Exposes themesRead() to renderer via contextBridge |
Variables reference
The complete set of CSS custom properties a theme can define — all optional; missing ones simply won't override the previous value:
--highlight-color
--main-color
--shadow-color
--heading-color
--body-color
--page-bg
--page-text
--page-muted
--panel-bg
--panel-border
--widget-bg
--widget-border
--topbar-bg
--topbar-border
--topbar-text
--topbar-muted
--topbar-active
--input-bg
--input-text
--input-border
--button-secondary-bg
--button-secondary-text
Theme manager API
The window.ThemeManager object exposed by theme.js provides:
| Method | Purpose |
|---|---|
applyTheme(themeName, broadcast?) | Apply a theme by name |
getCustomThemeList() | Returns [{name, title}] of loaded themes |
isUsingFallback() | Returns true if no user themes exist |
getActiveTheme() | Returns the currently active theme name |
initializeTheme() | Re-initialize (loads themes from IPC, applies stored preference) |
getResolvedTheme(themeName) | Returns the resolved palette key |
Setup wizard — deep dive
File layout
components/setup/
├── setup.js # Parent loader — fetches setup.json, loads modules, bootstraps
├── setup.json # Step definitions + setup_order array
└── modules/
├── _shared.js # Shared state, utilities, settings, rendering
├── step-welcome.js
├── step-language.js
├── step-appearance.js
├── step-os-detect.js
├── step-python-detect.js
├── step-python-dependency.js
├── step-gpu-detect.js
├── step-compat-check.js
├── step-framework.js
├── step-fw-install.js
├── step-fw-verify.js
├── step-resources.js
├── step-project-folder.js
├── step-qol.js
├── step-security.js
└── step-finish.js
Bootstrap flow
setup.jslistens forDOMContentLoaded, then:- Fetches
setup.jsonto getsteps(definitions) andsetup_order(ordering). - Loads
_shared.jsvia dynamic<script>injection. - Loads each step module in the order listed in
steps. - Reorders
window.__setupStepsto matchsetup_order. - Builds the wizard DOM (
#setup-wizardwith header, content, progress dots, and action buttons). - Calls
window.__setupSettings.loadSettings()to hydrate the settings cache. - Wires up navigation event listeners (next, back, skip, finish).
- Renders the first step.
- Fetches
Shared module (_shared.js)
Exposes four global namespaces:
| Namespace | Purpose |
|---|---|
window.__setupState | All mutable state — selectedFramework, selectedMode, installSucceeded, detected (OS, Python, GPU, compat), pythonDetectCache, selectedProjectFolder, currentStep, settingsCache |
window.__setupUtils | Pure utility functions — escapeHtml, parseKV, boolVal, okIcon, warnIcon, gpuVariant, torchIndexURL, gpuVariantLabel, buildInstallCommand, getPythonDetectResult |
window.__setupSettings | Settings persistence — loadSettings, defaultSettings, applyStepData, collectAndSave |
window.__setupRender | Rendering and navigation — renderStep, nextStep, prevStep |
Step module contract
Each step module is an IIFE that pushes an object to window.__setupSteps:
{
id: 'unique-step-id', // matches the id in setup.json
title: 'Display Title', // shown in progress dots
render(settingsCache) { ... }, // returns HTML string (synchronous)
afterRender() { ... }, // async — runs after DOM is injected
collect() { ... } // returns data to persist into settings
}
render()— must be synchronous. Returns the HTML for the step. Receives the currentsettingsCacheas argument.afterRender()— optional async hook. Runs after the HTML is in the DOM. Used for event binding, async detection, and dynamic UI updates.collect()— optional. Called when the user navigates away from the step. Returns data thatapplyStepData()maps into the settings cache.
Step ordering
The setup_order array in setup.json is the single source of truth for navigation order. After all modules load, setup.js builds a lookup map by step ID and reassembles window.__setupSteps to follow setup_order. Steps not listed in setup_order are dropped. Steps listed but not found are silently skipped.
Adding / removing / skipping a step
- Add: create
components/setup/modules/step-your-step.jsfollowing the contract above, add an entry tostepsinsetup.json, then insert the step ID intosetup_orderat the desired position. - Remove: delete its entry from
stepsand remove its ID fromsetup_order. - Skip without deleting: just remove its ID from
setup_order— the module still loads but won't appear in the wizard.
Documentation system
The documentation system is quite simple. Add the relative path of any MD file to docs/register.json (it assumes the file is in the docs folder, but you can change the path).
{
"display name" : "filename.md",
"file outside of docs folder" : "../path/to/file.md"
}
Auto-updater
MAMA can update itself from GitHub releases. The whole system lives in updater.py; the UI is components/elements/updater.js (banner on every page) plus an "Updates" panel on the settings page.
How it works
- Check —
updater.check_for_update()listsapi.github.com/repos/CrankyTitanO7/mama/releasesand picks the release with the highest version tag (stable over prerelease —/releases/latestcan't be used because it returns the most recently published release, so a later-published lower tag would hide a higher one). It compares the tag against the bundledcomponents/version.jsonand matches an asset: macOS →mama-macos.dmg(ormama-macos-<arch>.dmg/.zip), Windows →mama-windows.zip, Linux →mama-linux.AppImage. One plain archive not targeting another platform is used as a fallback. - Download —
updater.download_update()streams the asset into~/Library/Application Support/mama/updates(per-OS equivalent elsewhere) and verifies its sha256 against the GitHub-provided asset digest. - Stage —
updater.stage_update()unpacks the artifact (dmg →hdiutil attach+dittoout the.app; zip → extract + locate the app folder, handling the Windowsmama/wrapper; AppImage → used as-is, made executable) intoupdates/mama-<tag>/and writes anapply.jsonmarker. Staging is refused when running from source (unpackaged). - Apply — on quit,
bridge.py'son_quitspawns a detachedmama --apply-update <marker>process. It waits for the old process to exit, swaps the old install for the staged one (whole bundle/folder, or single-file replacement for AppImages), copies user data (user/,components/recents.json) from the old install — locating the data dir in the new build even if the PyInstaller layout changed (Contents/Resourcesvs_internal) — deletes the backup, and relaunches the new build (openon macOS, direct exec elsewhere). Anapplying.lockprevents two processes swapping at once, and a marker left by a crashed session is applied on the next startup (updater.recover_pending()inmain.py).
Frontend API (via the shim)
| Method | Purpose |
|---|---|
electron.updateCheck() | Returns {available, current_version, latest_version, notes, asset, error} |
electron.updateDownload() | Starts a background download; progress via _updateProgressCallback |
electron.updateInstall() | Stages the download; emits ready |
electron.appQuit() | Closes the window (triggers the quit hand-off) |
Releasing a new version
The GitHub workflow .github/workflows/build.yml handles the whole release: push a tag and it builds on all three platforms, writes the version into components/version.json from the tag name, packages the artifacts (mama-macos.dmg, mama-windows.zip, mama-linux.AppImage) and uploads them to a GitHub release:
git tag v0.2.0 && git push origin v0.2.0
The build environment MUST have certifi installed (the workflow installs it, and build_release.py warns if it is missing): without it the packaged app contains no CA certificates and every HTTPS request fails from inside the app — the updater can't reach GitHub and reports a TLS error.
The workflow uses the same artifact names the updater expects — a release created any other way must use those names, or the updater won't offer it. To build locally instead, python build_release.py --version 0.2.0 bumps components/version.json, runs PyInstaller, zips the build into dist/mama-<os>-<arch>.zip and prints the sha256; then create a GitHub release and attach the zip.