Files
yellowjacket/AGENTS.md
T

7.1 KiB

AGENTS.md - YellowJacket

Guidelines for AI coding agents working in this repository.

Project Overview

YellowJacket is a cross-platform desktop music player built with:

  • Backend: Go 1.24+ with Wails v2 framework
  • Frontend: TypeScript with Lit Web Components
  • Database: SQLite (pure-Go driver via modernc.org/sqlite)
  • Build Tools: Make, Wails CLI, Vite, pnpm

Build Commands

make dev          # Development with hot-reload
make build-dev    # Debug build
make build-prod   # Production build (obfuscated + UPX compressed)
make generate     # Run all code generators (sqlc, templ)
make clean        # Clean frontend build artifacts

Frontend Only

cd frontend
pnpm install    # Install dependencies
pnpm dev        # Vite dev server
pnpm build      # Production build

Testing

go test ./...                                       # Run all tests
go test ./backend/player/                           # Run tests in a specific package
go test -run TestFunctionName ./backend/player/     # Run a single test by name
go test -v -run TestFunctionName ./backend/player/  # Verbose output

Test files are located alongside source files as *_test.go. Test fixtures live in test_data/.

Linting

The project uses golangci-lint (v2 config) with strict rules. Key enabled linters:

  • gocritic, errorlint, err113, godot, revive, sloglint, nlreturn, wsl
  • Formatters: gci, gofmt, gofumpt, goimports, golines
golangci-lint run

Code Generation

go:generate directives live in:

  • backend/app.go — templ: generates *_templ.go from .templ files
  • backend/database/database.go — sqlc: generates type-safe DB code from SQL

After modifying .templ files or SQL in backend/database/sql/, run make generate.

Code Style Guidelines

Go Code Style

Package Documentation

Every package must have a doc comment:

// Package player provides audio playback functionality.
package player

Import Organization

Imports are grouped and ordered by gci/goimports (three groups separated by blank lines):

  1. Standard library 2. Third-party packages 3. Internal packages (yellowjacket/...)
import (
    "context"
    "fmt"
    "log/slog"

    "github.com/wailsapp/wails/v2/pkg/runtime"

    "yellowjacket/backend/events"
    "yellowjacket/backend/metadata"
)

Error Handling

  • Always wrap errors with context: fmt.Errorf("failed to open file: %w", err)
  • Define sentinel errors as package-level vars (enforced by err113):
    var ErrUnsupportedFileType = errors.New("unsupported file type")
    
  • Use errors.Join() for accumulating multiple errors
  • Return early on errors; blank line required after early returns (nlreturn)

Naming Conventions

  • Structs: PascalCase (e.g., Player, AudioFile)
  • Exported methods: PascalCase
  • Unexported methods/fields: camelCase
  • Constants: PascalCase for exported, grouped with const (...)
  • Custom domain types: type PlayerState string, type UserVolume int

Logging

Use log/slog with structured key-value pairs. Logger instances are injected via constructors:

p.logger.Info("File loaded", "file", filePath)
p.logger.Error("Failed to decode", "path", filePath, "err", err)

Logger groups via logger.WithGroup("player") for component-scoped logging.

Constructor Pattern

func NewPlayer(ctx context.Context, logger *slog.Logger, db *database.DB) (*Player, error) {
    player := &Player{ctx: ctx, logger: logger, state: Stopped}
    // initialization...
    return player, nil
}

SetContext Pattern (Two-Phase Initialization)

Backend components that need the Wails runtime use a two-phase pattern because Wails runtime features (events, dialogs) are unavailable until OnStartup:

  1. Constructor (New*) — created before Wails runtime is available
  2. SetContext(ctx context.Context) — called after Wails runtime starts; registers event handlers

Comments

  • Doc comments on all exported functions/types
  • End sentences with periods (enforced by godot)
  • Blank line after early returns (enforced by nlreturn)

Build Tags

Dev/prod detection uses build tags in internal/dev/:

  • //go:build devIsDev = true (used by make dev)
  • //go:build !devIsDev = false (production builds)

TypeScript/Lit Code Style

Import Organization

Use path aliases defined in tsconfig.json:

import { EventsOn, EventsEmit } from '@runtime/runtime';
import type { TrackInfo } from '@store/player-store';

Available aliases: @go/*, @components/*, @store/*, @runtime/*, @utils/*, @assets/*, @pages/*

Lit Component Pattern

@customElement('component-name')
export class ComponentName extends LitElement {
  @state() private someState: Type = initialValue;

  override connectedCallback() { super.connectedCallback(); }
  override render() { return html`...`; }
}

TypeScript Strictness

  • strict: true enabled
  • noUncheckedIndexedAccess: true — check array/object access
  • noImplicitOverride: true — must use override keyword
  • verbatimModuleSyntax: true — use import type for type-only imports
  • experimentalDecorators: true — required for Lit decorators

Frontend-Backend Communication

Event System

Events are the primary communication mechanism. Event names must match exactly in both files:

  • Go: backend/events/events.go
  • TypeScript: frontend/src/events.ts
runtime.EventsEmit(p.ctx, events.TrackChanged, trackInfo)
runtime.EventsOn(p.ctx, events.RequestPlay, func(_ ...any) { p.Play() })
EventsEmit(Events.RequestPlay);
EventsOn(Events.TrackChanged, (trackInfo: TrackInfo) => { ... });

State Management

  • Singleton stores in frontend/src/store/ — backend is source of truth
  • ReactiveController pattern (PlayerController) connects Lit components to stores

HTMX

The config page uses HTMX for HTML fragment loading. Backend serves HTML fragments via templ templates (backend/config/config-form.templ, backend/library/config.templ). Config is a separate entry point (src/pages/config/).

Database

SQLite with sqlc for type-safe queries. Schemas in backend/database/sql/schemas/, queries in backend/database/sql/queries/, generated code in backend/database/sql/sqlcgen/. After modifying SQL files, run make generate.

Directory Structure

  • backend/ — Go backend: config/, database/, events/, library/, metadata/, player/, system/
  • frontend/src/ — TypeScript/Lit: components/, pages/, store/, utils/
  • frontend/wailsjs/ — Generated Wails bindings
  • internal/dev/ — Build-tag-based dev/prod detection
  • pkg/templcomp/ — Shared templ component utilities
  • test_data/ — Audio test fixtures

Key Dependencies

  • Wails v2: Desktop app framework bridging Go and web frontend
  • beep: Audio playback library (custom fork TheCodeOfCaleb/beep)
  • sqlc: Type-safe SQL code generation
  • templ: Go HTML templating
  • Lit: Web component framework
  • Web Awesome: Web component UI library (@awesome.me/webawesome)