Imported from cbrunnkvist/alsamixer-web (
AGENTS.md). Install upstream withnpx skills add cbrunnkvist/alsamixer-web. Copyright stays with the author.
AGENT Guidelines for alsamixer-web Repository
This document outlines the build process, testing procedures, and coding style guidelines for contributing to the alsamixer-web project. Adhering to these guidelines ensures consistency, maintainability, and high quality across the codebase.
1. Build and Test Commands
All primary build and test operations are managed via the Makefile.
Core Commands
-
Build Project Locally:
make buildThis compiles the main
alsamixer-webexecutable for the current operating system and architecture, placing it in the project root. -
Run Project Locally:
make runExecutes the
alsamixer-webserver locally. -
Run All Tests Locally:
make testExecutes all Go tests within the project.
-
Clean Build Artifacts:
make cleanRemoves generated binaries (
alsamixer-web) and thedist/directory.
Cross-Compilation & Deployment
-
Build for Linux AMD64:
make build-linux-amd64Cross-compiles the
alsamixer-webbinary forlinux/amd64architecture, placing it indist/. -
Build for Linux ARM64:
make build-linux-arm64Cross-compiles the
alsamixer-webbinary forlinux/arm64architecture, placing it indist/. -
Deploy to Remote Server:
make deploy DEPLOY_TARGET=user@host DEPLOY_PATH=/path/to/destThis target builds the
linux/amd64binary and then usesscpto transfer it to the specified destination, also setting execute permissions. Replaceuser@hostwith your target server and/path/to/destwith the directory where you want to install the binary.Example usage:
make deploy DEPLOY_TARGET=root@lemox.lan DEPLOY_PATH=/root/work/alsamixer-web -
Run Specific Go Test:
go test ./internal/server -run TestMyHandlerNameReplace
./internal/serverwith the path to the package andTestMyHandlerNamewith the exact test function name.
E2E Tests with Playwright
The project includes E2E tests using Playwright to verify UI functionality. Tests require configuration via environment variables.
Prerequisites:
- Playwright is installed via
npm install(dev dependency) - Brave browser must be available at
/Applications/Brave Browser.app/Contents/MacOS/Brave Browser
Environment Variables:
E2E_BASE_URL: Required - URL of the running alsamixer-web server (e.g.,http://localhost:8888orhttp://lemox.lan:8888)E2E_SERVER_CMD_PREFIX: Optional - Command prefix to run ALSA commands (e.g.,ssh lemox.lanfor remote server orsudofor local with privileges)
Run All E2E Tests:
E2E_BASE_URL=http://localhost:8888 node e2e.test.js
Run Specific E2E Test File:
# Basic UI tests
E2E_BASE_URL=http://localhost:8888 node e2e.test.js
# ALSA→UI synchronization tests
E2E_BASE_URL=http://lemox.lan:8888 E2E_SERVER_CMD_PREFIX="ssh lemox.lan" node e2e-alsa-to-ui.test.js
# Mute toggle tests
E2E_BASE_URL=http://lemox.lan:8888 E2E_SERVER_CMD_PREFIX="ssh lemox.lan" node e2e-mute.test.js
Test Files:
e2e.test.js- Basic UI load and interaction testse2e-alsa-to-ui.test.js- Tests external ALSA changes reflected in UI via SSEe2e-mute.test.js- Tests mute toggle UI↔ALSA synchronization
Note: Tests use Brave browser in non-headless mode for debugging. Modify the test files to use headless: true for CI/automated runs.
Go Toolchain Commands
-
Format Go Code:
go fmt ./...Ensures all Go files adhere to standard formatting.
-
Run Static Analysis:
go vet ./...Performs basic static analysis to detect suspicious constructs.
2. Code Style Guidelines
Go (.go files)
- Formatting: Strictly adhere to
gofmtoutput. - Imports:
- Group imports: standard library first, then external, then internal project packages.
- Use blank lines to separate import groups.
- Example:
import ( "context" "fmt" "log" "github.com/external/library" "github.com/user/alsamixer-web/internal/alsa" )
- Naming Conventions:
- Packages:
lowercase(e.g.,server,alsa). - Variables/Functions:
camelCasefor unexported,PascalCasefor exported. - Constants:
PascalCasefor exported (e.g.,ThemeTerminal),camelCasefor unexported.ALL_CAPSfor environment variables/flags. - Struct Fields:
PascalCasefor exported,camelCasefor unexported. - Interfaces: Often end with
er(e.g.,VolumeController,Hub).
- Packages:
- Error Handling:
- Always explicitly check errors (
if err != nil). - Wrap errors using
fmt.Errorf("descriptive message: %w", err)for context. - Return
nil, fmt.Errorf(...)for functions that encounter errors. - Use
log.Printffor non-fatal errors and informational messages. - Use
log.Fatalffor unrecoverable errors during application startup. - HTTP handlers should use
http.Error()with appropriatehttp.Status...codes.
- Always explicitly check errors (
- Concurrency:
- Protect shared state with
sync.Mutexor other synchronization primitives. - Use
gogoroutines for concurrent operations (e.g., SSE broadcasting, ALSA monitoring). - Employ
sync.WaitGroupfor graceful shutdown of goroutines.
- Protect shared state with
- Build Tags: Use
//go:build <tag>for platform-specific code (e.g.,//go:build linuxfor ALSA integrations). - Documentation: Provide clear, concise comments for all exported functions, structs, interfaces, and complex logic blocks.
HTML Templates (.html files)
- Structure: Adhere to HTML5 standards with semantic tags.
- Accessibility (A11y):
- Prioritize ARIA attributes (
role,aria-label,aria-valuenow,aria-checked,aria-live, etc.) for rich interactive elements. - Include a skip link (
.skip-link) for keyboard navigation.
- Prioritize ARIA attributes (
- HTMX Integration:
- Utilize
hx-post,hx-trigger,hx-swap,hx-valsfor dynamic interactions. hx-onfor client-side JavaScript to handle post-request logic (e.g., updatingaria-checked).- Use
sse-connectandsse-swapfor Server-Sent Events.
- Utilize
- Go Template Syntax:
- Use
{{define "name"}}...{{end}}and{{block "name" .}}...{{end}}for template composition. - Access data with
{{.FieldName}}. - Control flow with
{{if .Condition}}...{{end}}and{{range .Slice}}...{{end}}. - Include partials with
{{template "name" .}}.
- Use
CSS (.css files)
- Methodology: Prefer BEM-like (
.block__element--modifier) naming for clarity and modularity. - CSS Custom Properties (Variables):
- Define global variables in
web/static/css/base.css. - Theme-specific variables (
--term-bg,--mobile-accent) should override or extend base variables in their respective theme files (web/static/themes/*.css).
- Define global variables in
- Responsive Design: Implement
@mediaqueries for different screen sizes (max-width,min-width) and user preferences (prefers-reduced-motion,forced-colors,prefers-color-scheme). Aim for a mobile-first approach. - Accessibility: Explicitly include styles for
:focus-visiblestates, high contrast mode, and reduced motion. - Clarity: Start each CSS file with a clear, descriptive comment.
JavaScript (.js files)
- Vanilla JS: Prefer vanilla JavaScript over frameworks to keep the project lightweight.
- Encapsulation: Use Immediately Invoked Function Expressions (IIFEs) for scope management.
- DOM Manipulation: Direct DOM API usage (
querySelector,querySelectorAll,addEventListener,setAttribute,closest). - HTMX Interaction: Listen for HTMX events (e.g.,
htmx:afterSwap) to re-initialize JavaScript logic on dynamically loaded content. - Accessibility: Directly update ARIA attributes in response to user interaction.
- Debug Logging: Client-side debug logging is available via
window.app.debugLogging. Set totruein the browser console to enable debug output (e.g., for E2E testing via Playwright:page.evaluate(() => { window.app.debugLogging = true })). - Clarity: Comment complex logic blocks and functions.
3. Tool-Specific Rules
No specific .cursor/rules/ or .github/copilot-instructions.md files were found. Agents should infer best practices from the existing codebase and general industry standards.
Playwright Browser Rule (Critical)
-
NEVER run
browser_installin this environment. -
Always use the existing Brave browser installation as the Chromium executable.
-
Brave path (macOS):
/Applications/Brave Browser.app/Contents/MacOS/Brave Browser -
Any Playwright session must explicitly use Brave instead of attempting to download or install Chrome/Chromium.
Failure to follow this rule will cause unnecessary timeouts and environment instability.
4. ALSA Reference
When working with ALSA mixer functionality, refer to ALSA-NOTES.md for:
- Core ALSA terminology (Cards, Controls, PCM devices, Channels)
- Control naming patterns and volume/switch derivation
- Channel configurations (Mono, Stereo Joined, Stereo Independent)
- Code patterns for GetMute/SetMute
- Common ALSA plugins (softvol, dmix, route, dsnoop)
- Debugging commands and lemox-specific setup
Key points:
- Switch values: ALSA 0 = muted, 1 = unmuted
- Derive switch name from volume:
strings.Replace(name, " Volume", " Switch", 1) - Always check channel configuration before assuming stereo/mono behavior