mirror of
https://github.com/abusoww/tuxmate.git
synced 2026-04-17 15:53:24 +02:00
refactor: minor changes to umami events logic
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -41,4 +41,4 @@ yarn-error.log*
|
||||
next-env.d.ts
|
||||
|
||||
# local notes
|
||||
AGENT.md
|
||||
# AGENT.md
|
||||
|
||||
123
AGENT.md
Normal file
123
AGENT.md
Normal file
@@ -0,0 +1,123 @@
|
||||
# TuxMate - Agent Guidelines
|
||||
|
||||
This document helps AI assistants understand how to work with this codebase.
|
||||
|
||||
## Project Overview
|
||||
|
||||
TuxMate is a Linux bulk app installer web app. Users select apps, pick their distro, and get a ready-to-run terminal command.
|
||||
|
||||
**Stack**: Next.js 14, TypeScript, Tailwind CSS, GSAP animations
|
||||
|
||||
## Code Style
|
||||
|
||||
### Comments
|
||||
|
||||
Single-line `//` comments only. No JSDoc blocks.
|
||||
|
||||
**Good:**
|
||||
```ts
|
||||
// Everything the app needs to work
|
||||
export function useLinuxInit() { ... }
|
||||
|
||||
// Quick one-liner for copy-paste warriors
|
||||
export function generateSimpleCommand() { ... }
|
||||
|
||||
// Vim-style keyboard navigation. Because real devs don't use mice.
|
||||
export function useKeyboardNavigation() { ... }
|
||||
```
|
||||
|
||||
**Never do this:**
|
||||
```ts
|
||||
/**
|
||||
* This is a multi-line JSDoc block.
|
||||
* We don't use these here.
|
||||
*/
|
||||
```
|
||||
|
||||
### Tone
|
||||
|
||||
Comments should sound like a senior dev wrote them. Brief, practical, occasionally witty.
|
||||
|
||||
- ✅ "Arch with AUR packages - this is where it gets fun"
|
||||
- ✅ "Memoized because React was having a moment"
|
||||
- ❌ "This function handles the complex orchestration of..."
|
||||
- ❌ "Leveraging advanced patterns to optimize..."
|
||||
|
||||
### Formatting
|
||||
|
||||
- `'use client';` at top of client components
|
||||
- CSS variables for theming: `var(--bg-primary)`, `var(--text-muted)`, etc.
|
||||
- Tailwind for utilities, CSS variables for colors
|
||||
- GSAP for entrance animations
|
||||
|
||||
## Key Patterns
|
||||
|
||||
### State Management
|
||||
- All state lives in hooks (`useLinuxInit`, `useTheme`, etc.)
|
||||
- localStorage persistence with hydration handling
|
||||
- No external state libraries
|
||||
|
||||
### Distro Handling
|
||||
- Configs in `src/lib/data.ts`
|
||||
- Each distro: id, name, color, icon, installPrefix
|
||||
- Package names: `app.targets[distroId]`
|
||||
|
||||
### AUR Detection
|
||||
- `src/lib/aur.ts` handles Arch AUR package detection
|
||||
- Patterns: `-bin`, `-git`, `-appimage` suffixes
|
||||
- Known AUR list for edge cases
|
||||
|
||||
### Nix Handling
|
||||
- `src/lib/nixUnfree.ts` detects unfree packages (Discord, Slack, Spotify, Steam, etc.)
|
||||
- Nix outputs declarative config, not shell scripts
|
||||
- Preview: clean config snippet
|
||||
- Download: includes unfree warning comment if needed
|
||||
- Set `KNOWN_UNFREE_PACKAGES` contains lowercase package names
|
||||
- **Verify Licenses**: Always check `nixpkgs` for license status. If `free = false`, add to `KNOWN_UNFREE_PACKAGES`.
|
||||
- Example: `heroic` is GPLv3 (free), `discord` is unfree. Don't guess.
|
||||
|
||||
### Command Generation
|
||||
- `useLinuxInit` generates clipboard one-liner (preview)
|
||||
- `generateInstallScript` creates downloadable files
|
||||
- Nix: downloads `configuration.nix`, others download `.sh`
|
||||
- Each distro has its own generator in `src/lib/scripts/`
|
||||
|
||||
## File Structure
|
||||
|
||||
```
|
||||
src/
|
||||
├── app/ # Next.js pages
|
||||
├── components/ # UI by domain
|
||||
│ ├── app/ # App grid (CategorySection, AppItem)
|
||||
│ ├── command/ # Footer, drawer, shortcuts
|
||||
│ ├── common/ # Tooltip, GlobalStyles
|
||||
│ ├── distro/ # Distro selector
|
||||
│ ├── header/ # Help modal, links
|
||||
│ └── ui/ # Theme toggle
|
||||
├── hooks/ # Custom hooks
|
||||
└── lib/ # Data, utilities, scripts
|
||||
├── aur.ts # Arch AUR package detection
|
||||
├── nixUnfree.ts # Nix unfree package detection
|
||||
├── data.ts # All apps and distro configs
|
||||
└── scripts/ # Per-distro generators
|
||||
```
|
||||
|
||||
## Don't
|
||||
|
||||
- No JSDoc blocks
|
||||
- No "educational" comments explaining obvious things
|
||||
- No buzzwords (leveraging, orchestrating, paradigm)
|
||||
- No unnecessary abstractions
|
||||
- Don't ignore existing patterns
|
||||
- Don't add unused exports (dead code)
|
||||
- Don't duplicate logic across files - centralize
|
||||
|
||||
## Do
|
||||
|
||||
- Keep comments concise
|
||||
- Match existing code style
|
||||
- Test on mobile (drawer = bottom sheet)
|
||||
- Use distro brand color for accents
|
||||
- Persist preferences to localStorage
|
||||
- One file per distro in `scripts/` (e.g., `nix.ts`, `arch.ts`)
|
||||
- Follow AUR pattern when adding distro-specific detection
|
||||
@@ -5,6 +5,7 @@ import { Check } from 'lucide-react';
|
||||
import { distros, type DistroId, type AppData } from '@/lib/data';
|
||||
import { isAurPackage } from '@/lib/aur';
|
||||
import { AppIcon } from './AppIcon';
|
||||
// import { analytics } from '@/lib/analytics'; // Uncomment to enable app selection tracking
|
||||
|
||||
/**
|
||||
* Individual app row in the category list.
|
||||
@@ -93,6 +94,12 @@ export const AppItem = memo(function AppItem({
|
||||
onFocus?.();
|
||||
if (isAvailable) {
|
||||
onToggle();
|
||||
// Umami tracking disabled to save quota
|
||||
// if (isSelected) {
|
||||
// analytics.appDeselected(app.name, app.category || '', selectedDistro);
|
||||
// } else {
|
||||
// analytics.appSelected(app.name, app.category || '', selectedDistro);
|
||||
// }
|
||||
}
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -4,6 +4,7 @@ import { useState, useEffect, useRef } from 'react';
|
||||
import { createPortal } from 'react-dom';
|
||||
import { Check, ChevronDown } from 'lucide-react';
|
||||
import { distros, type DistroId } from '@/lib/data';
|
||||
import { analytics } from '@/lib/analytics';
|
||||
import { DistroIcon } from './DistroIcon';
|
||||
|
||||
/**
|
||||
@@ -78,7 +79,7 @@ export function DistroSelector({
|
||||
{distros.map((distro, i) => (
|
||||
<button
|
||||
key={distro.id}
|
||||
onClick={() => { onSelect(distro.id); setIsOpen(false); }}
|
||||
onClick={() => { onSelect(distro.id); setIsOpen(false); analytics.distroSelected(distro.name); }}
|
||||
className={`group w-full flex items-center gap-3 py-3 px-4 cursor-pointer text-left transition-colors duration-100 ${selectedDistro === distro.id
|
||||
? 'border-l-2 -ml-[2px] pl-[18px]'
|
||||
: 'hover:bg-[var(--bg-hover)]'
|
||||
|
||||
Reference in New Issue
Block a user