Files
tuxmate/CONTRIBUTING.md

18 KiB
Raw Blame History

Contributing to TuxMate

Thank you for your interest in contributing! This guide ensures high-quality, error-free contributions.


⚠️ Before You Start

Your PR will be rejected if you:

  • Submit unverified package names
  • Use wrong package name casing (e.g., firefox vs MozillaFirefox)
  • Put pacman packages in arch when they're AUR-only
  • Use partial Flatpak IDs instead of full App IDs
  • Forget --classic for Snap packages that require it
  • Include PPAs or unofficial repos for apt packages
  • Incorrect Homebrew format (GUI apps require '--cask name' with a space separator)

📦 Adding Applications

All applications are defined in src/lib/data.ts.

Mandatory Research Protocol

You MUST verify every package on these official sources before submitting:

Source What to Check URL
Repology Global package index (check first!) https://repology.org/project/[app-name]/versions
Arch Linux Official repos (core, extra) archlinux.org/packages
AUR User repos (only if not in official!) aur.archlinux.org
Ubuntu/Debian Main/Universe repos only, NO PPAs packages.ubuntu.com / packages.debian.org
Fedora Official packages packages.fedoraproject.org
OpenSUSE Official packages software.opensuse.org
NixOS Nix packages search.nixos.org
Flathub Flatpak apps (get the App ID!) flathub.org
Snapcraft Snap packages snapcraft.io
Homebrew Formulae CLI tools (works on macOS + Linux) formulae.brew.sh
Homebrew Casks GUI apps (macOS only) formulae.brew.sh/cask

Entry Structure

{
  id: 'app-id',                        // Unique, lowercase, kebab-case
  name: 'App Name',                    // Official display name  
  description: 'Short description',    // Max ~25 characters
  category: 'Category',                // Must match valid categories
  iconUrl: si('icon-slug', '#color'),  // See Icon System section
  targets: {
    ubuntu: 'exact-package-name',      // apt package (official repos ONLY)
    debian: 'exact-package-name',      // apt package (official repos ONLY)
    arch: 'exact-package-name',        // pacman OR AUR package name
    fedora: 'exact-package-name',      // dnf package
    opensuse: 'exact-package-name',    // zypper package (CASE SENSITIVE!)
    nix: 'exact-package-name',         // nix package
    flatpak: 'com.vendor.AppId',       // FULL Flatpak App ID (reverse DNS)
    snap: 'snap-name',                 // Add --classic if needed
    homebrew: 'formula-name',          // Formula (CLI) or '--cask cask-name' (GUI)
  },
  unavailableReason?: 'Markdown install instructions'
}

Strict Rules (Read Carefully!)

Package Name Rules

Rule Correct Wrong
Case sensitivity MozillaFirefox (openSUSE) firefox
Exact package name firefox-esr (Debian) firefox
OpenJDK versions openjdk-21-jdk (Ubuntu) openjdk
Arch package firefox firefox-bin (when official exists)

Arch Linux: arch vs AUR

Situation Field to Use Example
Package in official repos (core/extra) arch: 'package' arch: 'firefox'
Package NOT in official repos arch: 'package-bin' arch: 'brave-bin'
NEVER mix both Use only ONE

How to check:

  1. Search archlinux.org/packages
  2. If found → use arch field
  3. If NOT found → search aur.archlinux.org → use arch field with AUR package name
  4. Prefer -bin suffix packages in AUR (pre-built, faster install)
  5. IMPORTANT: If your AUR package name does NOT end in -bin, -git, or -appimage, you MUST add it to KNOWN_AUR_PACKAGES in src/lib/aur.ts so the app knows it's from AUR.

Ubuntu/Debian: Official Repos Only

Allowed NOT Allowed
Main repository packages PPAs
Universe repository packages Third-party repos
Packages on packages.ubuntu.com Manual .deb downloads

If a package requires a PPA: Leave the field empty and add install instructions to unavailableReason.

Flatpak: Full App ID Required

Correct Wrong
com.spotify.Client spotify
org.mozilla.firefox firefox
app.zen_browser.zen zen-browser

How to find: Go to flathub.org, search the app, copy the full App ID from the app page.

Snap: Classic Confinement

Some snaps require --classic flag. Check snapcraft.io for the app and look for "classic" confinement.

App Type Format
Regular snap 'snap-name'
Classic confinement 'snap-name --classic'

Homebrew: Formulae vs Casks

Homebrew has two types of packages:

Type What It Is Platform Format in targets
Formula CLI tools, libraries macOS + Linux 'package-name'
Cask GUI applications (.app) macOS only '--cask package-name'

Examples:

App Type Correct Format
Git Formula (CLI) homebrew: 'git'
Node.js Formula (CLI) homebrew: 'node'
Python Formula (versioned) homebrew: 'python@3.12'
Firefox Cask (GUI) homebrew: '--cask firefox'
VS Code Cask (GUI) homebrew: '--cask visual-studio-code'
Discord Cask (GUI) homebrew: '--cask discord'
VLC Cask (GUI) homebrew: '--cask vlc'

How to verify package names:

  1. Formulae: Search formulae.brew.sh or run brew search <name>
  2. Casks: Search formulae.brew.sh/cask or run brew search --cask <name>
  3. Check the exact name on the package page (e.g., visual-studio-code not vscode)

Important notes:

  • Casks are macOS-only — the generated script will skip them on Linux
  • Always prefix GUI apps with --cask (note the space after)
  • Some apps exist as both formula AND cask (e.g., emacs formula vs emacs-app cask) — choose based on user expectation
  • For versioned packages, use the explicit version: python@3.12, node@20

Empty Fields

If a package doesn't exist in a source, leave the field empty (omit it entirely):

// ✅ Correct - Discord not in apt repos
targets: {
  arch: 'discord',
  flatpak: 'com.discordapp.Discord',
  snap: 'discord'
}

// ❌ Wrong - Empty strings clutter the code
targets: {
  ubuntu: '',
  debian: '',
  arch: 'discord',
  fedora: '',
  opensuse: '',
  nix: '',
  flatpak: 'com.discordapp.Discord',
  snap: 'discord'
}

The unavailableReason Field

Use this to provide helpful installation alternatives when an app isn't available in most package managers.

Format: Markdown with clickable links

// ✅ Good example
unavailableReason: 'Not in official repos. Use [Flatpak](https://flathub.org/apps/com.example.App) or download from [example.com](https://example.com/download).'

// ❌ Bad examples
unavailableReason: 'Not available'           // No helpful info
unavailableReason: 'Download from website'   // No link provided

Valid Categories

Use exactly one of these:

Web Browsers • Communication • Dev: Languages • Dev: Editors • Dev: Tools
Terminal • CLI Tools • Media • Creative • Gaming • Office
VPN & Network • Security • File Sharing • System

🎨 Icon System

TuxMate uses the Iconify API for icons. Icon helpers are defined in src/lib/data.ts.

Helper Functions

Function Use Case Example
si('slug', '#color') Simple Icons (brands) si('firefox', '#FF7139')
lo('slug') Logos (already colorful) lo('chrome')
vs('slug') VS Code file icons vs('file-type-shell')
mdi('slug', '#color') Material Design icons mdi('console', '#57F287')

Finding Icon Slugs

Source URL Notes
Simple Icons simpleicons.org Use lowercase slug, add hex color
Material Design pictogrammers.com/library/mdi Use icon name
Iconify Search icon-sets.iconify.design Search all sets
Fallback Use mdi('application', '#color')

Icon Requirements

  • Must be recognizable at 24×24px
  • Use official brand colors - click icon to copy hex
  • Monochrome icons (si, mdi) require a color parameter
  • Colorful icons (lo, sk, vs) don't need color
  • Don't use blurry or low-quality external URLs

🔀 Pull Request Checklist

Before submitting, verify ALL of these:

Package Verification

  • Checked Repology for global package availability
  • Verified exact package names on each distro's official package search
  • Confirmed case sensitivity (especially openSUSE: MozillaFirefox, MozillaThunderbird)
  • Arch packages confirmed in official repos OR AUR
  • Ubuntu/Debian packages are in Main/Universe only (no PPAs)
  • Flatpak uses full App ID from Flathub
  • Snap packages checked for --classic requirement
  • Homebrew uses correct format: 'formula' for CLI, '--cask name' for GUI apps

Code Quality

  • Tested locally with npm run dev
  • Production build passes: npm run build
  • Lint passes: npm run lint
  • Unit tests pass: npm run test
  • Apps added in alphabetical order within their category
  • Icons display correctly at small sizes

📝 Pull Request Template

Use the following template when submitting a pull request:

## Summary

Brief description of changes made.

## Changes

### Apps Added
| App Name | Category | Package Sources |
|----------|----------|-----------------|
| Example App | Dev: Tools | apt, pacman, flatpak, homebrew |

### Apps Modified
- `app-id`: Description of change

## Verification

> All package names have been verified against official sources.

| Source | Verification Link |
|--------|-------------------|
| Repology | [repology.org/project/...](https://repology.org/) |
| Arch Linux | [archlinux.org/packages/...](https://archlinux.org/packages/) |
| AUR | [aur.archlinux.org/packages/...](https://aur.archlinux.org/) |
| Ubuntu | [packages.ubuntu.com/...](https://packages.ubuntu.com/) |
| Fedora | [packages.fedoraproject.org/...](https://packages.fedoraproject.org/) |
| openSUSE | [software.opensuse.org/...](https://software.opensuse.org/) |
| NixOS | [search.nixos.org/packages/...](https://search.nixos.org/packages) |
| Flathub | [flathub.org/apps/...](https://flathub.org/) |
| Snapcraft | [snapcraft.io/...](https://snapcraft.io/) |
| Homebrew | [formulae.brew.sh/...](https://formulae.brew.sh/) |

## Testing

- [ ] `npm run dev` — Local development server works
- [ ] `npm run build` — Production build passes
- [ ] `npm run lint` — No linting errors
- [ ] `npm run test` — All unit tests pass
- [ ] Verified in browser — UI renders correctly

## Screenshots (if applicable)

<!-- Add screenshots for UI changes -->

💻 Development Workflow

Initial Setup

# Clone the repository
git clone https://github.com/abusoww/tuxmate.git
cd tuxmate

# Install dependencies
npm install

# Start development server
npm run dev

The development server will be available at http://localhost:5173.

Quality Assurance

Run these commands before every commit:

Command Purpose
npm run lint Check for code style issues
npm run lint -- --fix Auto-fix linting errors
npm run test Run unit test suite
npm run build Verify production build

Branch Naming Convention

Type Format Example
New feature feature/description feature/add-homebrew-support
Bug fix fix/description fix/arch-aur-detection
Documentation docs/description docs/update-contributing
Refactor refactor/description refactor/script-generation

Commit Message Format

Follow Conventional Commits:

<type>(<scope>): <description>

[optional body]

[optional footer]

Types:

Type Description
feat New feature or functionality
fix Bug fix
docs Documentation changes
style Code style (formatting, no logic change)
refactor Code restructuring (no feature change)
test Adding or updating tests
chore Maintenance tasks

Examples:

feat(data): add Homebrew support for 50+ apps

fix(scripts): correct AUR package detection for -git suffix

docs(contributing): add Homebrew verification guidelines

🐧 Adding Distributions

Distributions are defined in src/lib/data.ts.

Distro Structure

{
  id: 'distro-id',
  name: 'Display Name',
  iconUrl: si('distro-slug', '#color'),
  color: '#HexColor',
  installPrefix: 'sudo pkg install -y'
}

After Adding a Distro

  1. Add the distro ID to the DistroId type in src/lib/data.ts
  2. Create a new script generator file: src/lib/scripts/[distro].ts
  3. Export the generator from src/lib/scripts/index.ts
  4. Add the case in src/lib/generateInstallScript.ts (both functions)
  5. Handle distro-specific logic (repo setup, package detection, etc.)
  6. Add targets.[distro] entries to relevant apps in data.ts

⚙️ Script Generation

Script generation is modular. Each distro has its own generator:

src/lib/
├── generateInstallScript.ts    # Main entry point
├── aur.ts                      # AUR package detection
└── scripts/
    ├── index.ts                # Exports all generators
    ├── shared.ts               # Colors, progress bars, utilities
    ├── arch.ts                 # Arch + AUR (yay)
    ├── debian.ts               # Debian apt
    ├── ubuntu.ts               # Ubuntu apt + PPA handling
    ├── fedora.ts               # Fedora dnf + RPM Fusion
    ├── opensuse.ts             # openSUSE zypper
    ├── nix.ts                  # Nix package manager
    ├── flatpak.ts              # Flatpak (parallel install)
    ├── snap.ts                 # Snap packages
    └── homebrew.ts             # Homebrew (formulae + casks)

Script Generator Features

Each script generator implements these core capabilities:

Feature Description Implementation
Package Detection Skip already-installed packages Distro-specific checks (e.g., dpkg -l, brew list)
AUR Handling Auto-install yay/paru helper for Arch See aur.ts for detection patterns
RPM Fusion Auto-enable repos for Fedora multimedia Enabled when proprietary codecs needed
Parallel Install Concurrent package installation Flatpak uses background jobs for speed
Network Retry Exponential backoff on failures with_retry() in shared.ts
Progress UI Colored output with ETA Progress bars, timing, summary
Shell Escaping Prevent command injection escapeShellString() in shared.ts
Homebrew Casks Platform-aware formula/cask handling Separate commands, skip casks on Linux

Testing Script Changes

Automated Testing

# Run the full test suite
npm run test

# Run tests in watch mode during development
npm run test -- --watch

# Run specific test file
npm run test -- src/__tests__/aur.test.ts

Manual Testing Workflow

Step Action Purpose
1 npm run dev Start development server
2 Select test packages Choose mix of package types
3 Copy generated script Use "Copy" button
4 Test in isolated environment VM or container (see below)
5 Verify installation Check packages installed correctly

Container Testing

Use Docker containers for safe, isolated testing:

# 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"

# Debian
docker run -it --rm debian:latest bash -c "apt update && bash"

Tip

For Homebrew testing, use a macOS environment or Homebrew on Linux.


🐛 Reporting Issues

Bug Reports — Include:

  • Browser & OS (e.g., Firefox 120 on Arch Linux)
  • Steps to reproduce (numbered list)
  • Expected vs actual behavior
  • Console errors (F12 → Console tab)
  • Screenshots if UI-related

Feature Requests — Include:

  • Use case and why it's needed
  • Proposed solution
  • Alternatives considered

Questions?

Open a Discussion or create an Issue.