This file provides guidance for AI coding agents working on the Alby Hub repository.
Alby Hub is a self-custodial Nostr Wallet Connect (NWC) service that bridges Lightning Network wallets with applications supporting the NIP-47 protocol. It supports multiple Lightning backends (LDK, LND, Phoenixd, Cashu) and runs as either a web server or a desktop app (via Wails).
hub/
├── api/ # HTTP API handlers and request/response models
├── alby/ # Alby account integration (OAuth, backups)
├── apps/ # App connection management
├── cmd/http/main.go # HTTP server entry point
├── config/ # Configuration management
├── db/ # Database layer, migrations, queries
├── events/ # Event pub/sub system
├── frontend/ # React frontend (see below)
├── http/ # HTTP service router
├── lnclient/ # LN abstraction interface + implementations
│ ├── ldk/ # Embedded LDK node
│ ├── lnd/ # LND gRPC client
│ ├── phoenixd/ # Phoenixd client
│ └── cashu/ # Cashu client
├── nip47/ # NIP-47 protocol implementation
│ ├── controllers/ # Per-method request handlers
│ ├── permissions/ # Permission validation
│ └── cipher/ # NIP-04 encryption
├── service/ # Core service orchestration
├── swaps/ # Boltz atomic swap integration
├── transactions/ # Transaction tracking and metadata
├── tests/ # Test helpers and utilities
└── wails/ # Wails desktop-specific handlers
frontend/src/
├── components/ # Reusable UI components
├── screens/ # Page-level route components
├── contexts/ # React context providers
├── hooks/ # Custom React hooks
├── state/ # Zustand client state stores
├── lib/ # Auth, backend type helpers
├── utils/ # Shared utilities (request.ts, swr.ts, formatting, etc.)
├── types.ts # Shared TypeScript types
└── routes.tsx # Route definitions
frontend/platform_specific/
├── http/ # Web-specific utilities (copied at build time)
└── wails/ # Desktop-specific utilities (copied at build time)
# Terminal 1 – Frontend (port 5173)
cd frontend
yarn install
yarn dev:http
# Terminal 2 – Backend (port 8080)
cp .env.example .env # configure as needed
go run cmd/http/main.go
wails dev -tags "wails"
Wails versions must stay in sync: the github.com/wailsapp/wails/v2 version in go.mod and the Wails CLI version installed in .github/workflows/wails.yml (go install ...cmd/wails@vX.Y.Z) must match. When bumping one, always update the other — this is a common source of drift (e.g. via Dependabot updates to go.mod only).
# Run all tests
go test ./...
# Run specific test by name
go test ./... -run TestHandleGetInfoEvent
# Run with PostgreSQL (optional)
export TEST_DATABASE_URI="postgresql://user:password@localhost:5432/postgres"
go test ./...
Mocks are generated with mockery (config in .mockery.yaml); run it after changing any interface.
cd frontend
yarn lint # ESLint + TypeScript type check + Prettier
yarn tsc:compile # TypeScript only
yarn format # Prettier only
No Jest/Vitest tests exist; frontend quality is enforced via linting.
# HTTP production build
cd frontend && yarn build:http
go build -o main cmd/http/main.go
# Docker
docker build . -t albyhub:latest
HTTP Request / NIP-47 Nostr Event
→ HTTP Handler / NIP-47 Event Handler
→ api/ package (business logic)
→ LNClient interface
→ Backend implementation (LDK/LND/Phoenixd/Cashu)
Services communicate via events/ pub/sub. Prefer publishing events over direct inter-service calls. Key events use the nwc_* prefix (e.g., nwc_payment_sent, nwc_payment_received).
Code under frontend/platform_specific/http/ and frontend/platform_specific/wails/ is swapped at build time. Any platform-specific frontend logic must have both variants.
lnclient/models.go defines the interface all backends must implement. Changes to this interface require updates to all four implementations (LDK, LND, Phoenixd, Cashu) and their mocks.
db/migrations/ — always add new migrations here; never modify existing ones.go-gormigrate. Use GORM conventions for new models.gofmt formatting expected.logrus with contextual fields — no fmt.Print.fmt.Errorf("context: %w", err) for debugging.api/api.go with corresponding HTTP routes in http/http_service.go.px definitions or inline styles. Use Tailwind's spacing, sizing, and layout utilities instead of hardcoded pixel values.!px-12, !text-sm). If a component's default styles need overriding, use a proper variant, compose with a wrapper, or extend the component — don't force specificity with !.bg-primary, rounded-lg, shadow-sm) rather than hardcoding hex values or arbitrary values. See frontend/src/index.css for available theme variables.ZapIcon, BitcoinIcon, ArrowDownIcon) — both forms are valid lucide exports, but this codebase consistently uses the suffixed alias. Don't mix styles.any types.frontend/src/state/).request() helper in frontend/src/utils/request.ts.frontend/src/routes.tsx.Use a type prefix followed by a short, dash-separated summary: feat/, chore/, or fix/. For example:
feat/add-cashu-backend
fix/payment-timeout-crash
chore/bump-go-1.25
Follow Conventional Commits format (feat:, fix:, chore:, etc.) — enforced by commitlint.
| File | Purpose |
|---|---|
cmd/http/main.go | HTTP server entry point |
main_wails.go | Desktop entry point |
api/api.go | Primary API endpoint handlers |
service/service.go | Core service initialization |
service/start.go | Service startup sequence |
lnclient/models.go | LNClient interface definition |
nip47/event_handler.go | NIP-47 request dispatch |
db/migrations/ | Database schema history |
frontend/src/types.ts | Shared TypeScript types |
frontend/src/routes.tsx | Frontend routing |
CI runs Go tests (including PostgreSQL), frontend lint/type checks, and binary builds for Linux and macOS. All checks must pass before merging to master.