Gabriel Kaszewski 792c9bf9ec
All checks were successful
CI / Check / Test (push) Successful in 11m29s
style: rustfmt
2026-07-11 22:58:00 +02:00
2026-07-11 22:58:00 +02:00
2026-07-11 21:02:28 +02:00

PocketChords

A rip-off of Ultimate Guitar with a focus on mobile users, without any ads or subscription. Self-hosted, open source and free to use.

Features

  • Import chord sheets from Ultimate Guitar URLs or HTML files (bulk import supported)
  • Transpose chords up/down with one tap
  • Piano keyboard and guitar fretboard chord diagrams
  • Capo support with sounding-key display
  • Adjustable font size (S/M/L) for readability while playing
  • Search and sort your library
  • Dark/light theme
  • PWA — add to home screen for native feel
  • JWT auth with registration/login
  • OpenAPI docs at /docs

Architecture

Hexagonal / ports-and-adapters with CQRS in the application layer. See architecture.mmd for the full diagram.

crates/
  domain/           # entities, value objects, ports, domain services
  application/      # use cases: songs/, tabs/, auth/ (commands, queries, deps)
  presentation/     # axum HTTP server, routes, extractors, OpenAPI
  api-types/        # request/response DTOs
  infra-wiring/     # shared config (AppConfig)
  adapters/
    sqlite/          # SQLite persistence (songs, users, refresh sessions)
    ug-parser/       # Ultimate Guitar HTML parser
    auth/            # JWT + Argon2 password hashing
app/                 # React Router SPA (Tailwind, shadcn/ui)

Quick start

# prerequisites: rust, node

# run locally (builds frontend, starts backend on :8000)
make dev

# or backend only (if frontend already built)
make dev-api

# run checks (fmt, clippy, tests)
make check

Deployment

Single Docker image serves both API and SPA:

# build and push to private registry
make deploy

# or with a specific tag
./deploy.sh --tag v1.0.0

Environment variables

Variable Default Description
DATABASE_URL sqlite://./pocket-chords.db SQLite connection string
HOST 0.0.0.0 Bind address
PORT 8000 Bind port
JWT_SECRET (required) Secret for signing JWTs
JWT_TTL_SECONDS 900 Access token TTL (15 min)
REFRESH_TTL_SECONDS 2592000 Refresh token TTL (30 days)
ALLOW_REGISTRATION false Enable user registration
CORS_ALLOWED_ORIGINS * Comma-separated origins or *
SPA_DIR ./app/build/client Path to SPA static files

License

MIT (see LICENSE for details).

Description
Languages
TypeScript 74.8%
Rust 22.9%
CSS 1.3%
Dockerfile 0.4%
Mermaid 0.3%
Other 0.3%