- Project Overview
- Development Workflow
- Adding Applications
- Adding Distributions
- Pull Request Checklist
- Templates
src/lib/apps/*.json: Main registry for applications (split by category).src/lib/data.ts: Main registry for distributions, categories, and Typescript types.src/lib/aur-packages.json: Whitelist for AUR packages that lack standard suffixes.src/lib/nix-unfree.json: Registry for unfree Nix packages.src/lib/verified-flatpaks.json: Auto-generated list of verified Flathub apps. Do not edit.src/lib/verified-snaps.json: Manual whitelist of verified Snap publishers.
git clone https://github.com/abusoww/tuxmate.git
cd tuxmate
npm install
npm run devThe app will be available at http://localhost:3000.
Running with Docker
You can run the full application using the official Docker image:
docker run -p 3000:80 ghcr.io/abusoww/tuxmate:latestQuality Assurance
Always run these before pushing:
npm run lint: Check for code style issues.npm run test: Run unit test suite.npm run build: Verify production build.
Verifying Install Scripts
To verify that the scripts generated by TuxMate work correctly, run them in a clean container environment. This prevents messing up your local system.
- Generate a script in the TuxMate UI (Dev mode).
- Copy the script.
- Run the corresponding distro container commands below and paste the script.
# Arch Linux
docker run -it --rm archlinux:latest bash -c "pacman -Sy && bash"
# Ubuntu
docker run -it --rm ubuntu:latest bash -c "apt update && bash"
# Fedora
docker run -it --rm fedora:latest bash -c "dnf check-update; bash"All applications are defined in category-specific JSON files within src/lib/apps/.
You MUST verify every package on these official sources before submitting:
| Source | Scope | URL |
|---|---|---|
| Repology | Global Index | repology.org |
| Arch Linux | Official Repos | archlinux.org/packages |
| AUR | User Repo | aur.archlinux.org |
| Debian | Official Repos | packages.debian.org |
| Ubuntu | Official Repos | packages.ubuntu.com |
| Fedora | Official Repos | packages.fedoraproject.org |
| OpenSUSE | Official Repos | software.opensuse.org |
| Nix | Nixpkgs | search.nixos.org |
| Flathub | Flatpaks | flathub.org |
| Snapcraft | Snaps | snapcraft.io |
| Homebrew | CLI & Casks | formulae.brew.sh |
{
"id": "app-id", // Unique, lowercase, kebab-case
"name": "App Name", // Official display name
"description": "Short description", // Max ~60 characters
"category": "Category", // Must match valid categories
"icon": { // See Icon System section
"type": "iconify",
"set": "simple-icons",
"name": "python",
"color": "#3776AB"
},
"targets": {
"ubuntu": "exact-package-name", // apt package (official repos ONLY)
"arch": "exact-package-name", // pacman OR AUR package name
"flatpak": "com.vendor.AppId", // FULL Flatpak App ID (reverse DNS)
"snap": "snap-name", // Add --classic if needed
"homebrew": "formula-name" // Formula (CLI) or '--cask name' (GUI)
},
"unavailableReason": "Markdown install instructions"
}This field renders Markdown when a target is missing. It serves as the manual fallback instruction.
Requirements:
- Actionable: Avoid "Not available". State the alternative (e.g., "Install via Flatpak").
- Linked: Hard-link the solution (Flathub page, upstream .deb URL, or Wiki guide).
- Format: Use standard Markdown for links
[text](url)and code`cmd`.
Examples:
| Status | Message | Why? |
|---|---|---|
| ❌ Bad | 'Not available.' |
Dead end. No solution provided. |
| ❌ Bad | 'Download from website.' |
Dead end. No solution provided. |
| ✅ Good | 'Not in official repos. Use the [Flatpak version](https://flathub.org/apps/com.spotify.Client) instead.' |
Directs to the preferred supported alternative. |
| ✅ Good | 'Arch requires [multilib](https://wiki.archlinux.org/title/Official_repositories#multilib) enabled: uncomment `[multilib]` in `/etc/pacman.conf`, run `sudo pacman -Syu`, then `sudo pacman -S steam`.' |
Exact steps to enable the required repo. |
- Official Packages: Use the package name directly if found in
coreorextra(e.g.,firefox). - Automatic AUR Detection:
src/lib/aur.tsautomatically detects suffixes-bin,-git, or-appimage. Use the name directly (e.g.,brave-bin). - Manual AUR Detection: For AUR packages without suffixes (e.g.,
google-chrome), you must add the name tosrc/lib/aur-packages.json. - Prefer
-binsuffix packages in AUR (pre-built, faster install)
Nixpkgs requires explicit user consent for unfree software.
- Check the license on search.nixos.org.
- If the license is unfree, add it to
src/lib/nix-unfree.jsonif missing. - Add the package to the appropriate JSON file in
src/lib/apps/normally.
Strict Repository Policy: The generation scripts do not enable extra repositories (like PPAs or non-free by default). Packages must be available in the standard enabled repositories.
- Allowed:
- Ubuntu: Main, Restricted
- Debian: Main
- Prohibited:
- PPAs (Personal Package Archives).
- External
.debURLs. - Packages requiring manual
sources.listmodification (unless detailed inunavailableReason).
- ID Format: Always use the full Application ID (reverse-DNS style).
- ✅ Correct:
org.mozilla.firefox - ❌ Wrong:
firefox
- ✅ Correct:
- Verification: Find the exact ID at the bottom of the app's Flathub page.
- Note:
verified-flatpaks.jsonis auto-generated; do not edit it manually.
- Classic Confinement: If the snap requires classic confinement (access to host system files), append
--classic.- Example:
code --classic - Check the install command on snapcraft.io to confirm.
- Example:
- Verification: If the publisher has a "Verified" badge on Snapcraft:
- Add the publisher name to
src/lib/verified-snaps.json. - This enables the "Verified" badge in the TuxMate UI.
- Add the publisher name to
Homebrew (macOS/Linux) has two package types. Check formulae.brew.sh to find the correct one.
- Formula: Standard CLI tools and libraries.
- Usage: Use the package name directly.
- Example:
'wget','node','python@3.12'
- Cask: GUI applications and large binaries (macOS only).
- Usage: Prefix with
--cask(note the space). - Example:
'--cask firefox','--cask visual-studio-code'
- Usage: Prefix with
- Validation:
- Run
brew search <name>locally to confirm type. - We skip
--casktargets on Linux installs automatically.
- Run
Every app needs an icon! Our JSON format makes it super simple to add icons using Iconify.
We store icons as structured objects in the JSON. You just need to provide the set, name, and color:
"icon": {
"type": "iconify",
"set": "simple-icons",
"name": "python",
"color": "#3776AB"
}- Simple Icons (
"set": "simple-icons")- Used for major brands and single-color logos (like Discord or Python).
- You must provide a hex
"color"for these.
- Logos (
"set": "logos")- Used when an app has a multi-colored, official logo.
- You don't need a
"color"for these.
- Material Design (
"set": "mdi")- Used for generic utilities (like a terminal or a magnifying glass).
- You must provide a hex
"color"for these.
If an app's icon isn't on Iconify, you can use a direct link to an image (SVG preferred, or a high-res PNG).
Just change the "type" to "url":
"icon": {
"type": "url",
"url": "https://raw.githubusercontent.com/..."
}- ✅ DO: Use a stable link (like the app's official GitHub repo raw image, or Wikimedia).
- ❌ DON'T: Use temporary image hosts (like Imgur) or hotlink-protected websites.
Use exactly one of these:
- Web Browsers • Communication • Media • Creative • Gaming • Office
- Dev: Languages • Dev: Editors • Dev: Tools
- Terminal • CLI Tools • VPN & Network • Security • File Sharing • System
Adding a new distribution involves three main steps:
Edit src/lib/data.ts:
- Add the new ID to the
DistroIdtype definition. - Add a new object to the
distrosarray with:id: unique identifier.name: Display name.iconUrl: Icon for the distro selector.color: Brand color.installPrefix: The default command prefix (e.g.,sudo dnf install -y).
Create a new file src/lib/scripts/<distroId>.ts. This file must export a function (e.g., generateFedoraScript) that takes PackageInfo[] and returns the generated shell script string.
- Use helpers from
shared.tslikegenerateAsciiHeaderandPackageInfo. - Implement logic to check if a package is already installed.
- Implement the installation command loop using
with_retryfor robustness. - See
src/lib/scripts/fedora.tsorubuntu.tsfor clean examples.
- Export your new function in
src/lib/scripts/index.ts. - Import it in
src/lib/generateInstallScript.ts. - Add a case for your
distroIdin theswitchstatement insidegenerateInstallScript. - Also add the simple one-liner command logic in
generateSimpleCommandwithin the same file.
Important
Your PR will be rejected if you violate these rules:
- Verify Everything: Submit only verified package names. Guessing is prohibited.
- Official First: Use official repository packages over third-party options.
- No Unofficial Repos: Do not include PPAs, COPRs, or unofficial repositories.
- Full IDs: Use full IDs for Flatpaks (e.g.,
org.mozilla.firefox). - Strict Casing: Package names are case-sensitive.
- Link Integrity: Ensure all links in
unavailableReasonare direct and working.
Verify before submitting:
- Package names verified on official search pages (Repology, Arch, etc).
- Case sensitivity checked (especially openSUSE).
- Arch packages verified (Official vs AUR).
- No PPAs used for Debian/Ubuntu; Main/Universe only.
- Flatpak IDs are full reverse-DNS style.
- Snap
--classicflag verification. - Nix unfree packages added to JSON.
- Homebrew Casks prefixed correctly.
-
npm run lint&npm run testpassed.
## Summary
Brief description of changes.
## Changes
| App Name | Category | Sources |
|----------|----------|---------|
| Example | Dev: Tool| apt, pacman |
## Verification
> Package names verified against official sources.
| Source | Link |
|--------|------|
| Repology | [Link](...) |
| Arch | [Link](...) |
| ... | ... |
## Testing
- [ ] `npm run dev` working
- [ ] `npm run build` passed
## Screenshots (if applicable)
<!-- Add screenshots for UI changes -->
## 🐛 Bug Report
**Environment**:
- OS: [e.g. Arch Linux]
- Browser: [e.g. Firefox 120]
**Steps to Reproduce**:
1. ...
2. ...
**Details**:
**Logs/Screenshots**:
[Paste console logs or attach screenshots]