AGENTS.md
Rama main · réplica de lectura del repositorio original.
# SubTrackr - Agent Documentation
## Project Overview
SubTrackr is a self-hosted subscription management application built with Go and HTMX. It helps users track subscriptions, visualize spending, and get renewal reminders.
## Architecture
### Tech Stack
- **Backend**: Go 1.21+ with Gin web framework
- **Database**: SQLite (GORM)
- **Frontend**: HTMX + Tailwind CSS
- **Deployment**: Docker & Docker Compose
### Project Structure
```
subtrackr-xyz/
├── cmd/
│ ├── server/ # Main server entry point
│ └── migrate-dates/ # Date migration utility
├── internal/
│ ├── config/ # Configuration management
│ ├── database/ # Database initialization and migrations
│ ├── handlers/ # HTTP request handlers (Gin handlers)
│ ├── middleware/ # HTTP middleware (auth, etc.)
│ ├── models/ # Data models (GORM models)
│ ├── repository/ # Data access layer
│ ├── service/ # Business logic layer
│ └── version/ # Version information
├── templates/ # HTML templates (HTMX)
├── web/static/ # Static assets (JS, CSS, images)
├── tests/ # Playwright E2E tests
└── data/ # SQLite database (gitignored)
```
### Key Components
#### 1. Server Entry Point (`cmd/server/main.go`)
- Initializes database, repositories, services, and handlers
- Sets up Gin router with templates
- Configures routes (web and API)
- Starts HTTP server
#### 2. Handlers (`internal/handlers/`)
- **subscription.go**: CRUD operations for subscriptions
- **settings.go**: SMTP config, Pushover config, notifications, API keys, currency, dark mode
- **category.go**: Category management
#### 3. Services (`internal/service/`)
- Business logic layer
- **subscription.go**: Subscription operations
- **settings.go**: Settings management
- **category.go**: Category operations
- **currency.go**: Currency conversion (Fixer.io integration)
- **email.go**: Email notification service (SMTP)
- **pushover.go**: Pushover notification service
- **ntfy.go**, **gotify.go**: ntfy and Gotify channels, sharing the retry and redirect-free transport in **push_http.go**
- **notification_dispatcher.go**: Sends a notification to every configured channel and reports what was delivered
- **reminder_runner.go**: Scheduled reminder passes; a reminder is marked sent only when a configured channel delivered it
#### 4. Models (`internal/models/`)
- GORM models:
- `Subscription`: Main subscription entity
- `Category`: Subscription categories
- `Settings`: Application settings (key-value store)
- `SMTPConfig`: Email configuration
- `PushoverConfig`: Pushover notification configuration
- `NtfyConfig`, `GotifyConfig`: ntfy and Gotify notification configuration
- `APIKey`: API authentication keys
- `ExchangeRate`: Currency exchange rates
#### 5. Repository (`internal/repository/`)
- Data access layer using GORM
- Abstracts database operations
### Routing Structure
#### Web Routes (HTMX)
- `/` - Dashboard
- `/dashboard` - Dashboard
- `/subscriptions` - Subscription list
- `/analytics` - Analytics view
- `/settings` - Settings page
- `/form/subscription` - Subscription form modal
#### API Routes (HTMX)
- `/api/subscriptions` - Subscription CRUD
- `/api/stats` - Statistics
- `/api/export/*` - Data export
- `/api/settings/*` - Settings management
- `/api/categories` - Category management
#### Public API Routes (Require API Key)
- `/api/v1/subscriptions` - Subscription CRUD
- `/api/v1/stats` - Statistics
- `/api/v1/export/*` - Data export
### Database Schema
#### Subscriptions
- ID, Name, Cost, OriginalCurrency
- Schedule: Monthly, Annual, Weekly, Daily
- Status: Active, Cancelled, Paused, Trial
- CategoryID (foreign key)
- Dates: StartDate, RenewalDate, CancellationDate
- Additional: PaymentMethod, Account, URL, Notes, Usage
#### Categories
- ID, Name
- CreatedAt, UpdatedAt
#### Settings
- Key-value store for application settings
- Keys: `smtp_config`, `renewal_reminders`, `currency`, etc.
### Key Features
1. **Subscription Management**
- CRUD operations
- Multiple schedules (Monthly, Annual, Weekly, Daily)
- Categories
- Multi-currency support
2. **Email Notifications**
- SMTP configuration with TLS/SSL support
- STARTTLS for ports 2525, 8025, 587, 25, 80
- Implicit TLS for ports 465, 8465, 443
- Renewal reminders
- High cost alerts
3. **Pushover Notifications**
- Pushover API integration for mobile push notifications
- User Key and Application Token configuration
- Renewal reminders (same settings as email)
- High cost alerts (same threshold as email)
- Works alongside email notifications
4. **Currency Support**
- USD, EUR, GBP, JPY, RUB, SEK, PLN, INR, CHF, BRL, COP, BDT
- Optional Fixer.io integration for real-time rates
- Automatic conversion display
- BDT (Bangladeshi Taka) with ৳ symbol
5. **API Access**
- API key authentication
- RESTful endpoints
- JSON responses
5. **Data Management**
- CSV/JSON export
- Backup functionality
- Clear all data option
### Development Guidelines
#### Code Style
- Follow Go standard formatting (`go fmt`)
- Use meaningful variable and function names
- Add comments for exported functions
- Keep functions focused and small
#### Error Handling
- Return errors from functions, don't panic
- Log errors appropriately
- Provide user-friendly error messages in handlers
#### Testing
- Unit tests in `*_test.go` files
- E2E tests in `tests/` using Playwright
- Test API endpoints with `test-api.sh`
#### Database Migrations
- Migrations in `internal/database/migrations.go`
- Use GORM AutoMigrate for schema changes
- Test migrations on sample data
#### Frontend
- Use HTMX for dynamic updates
- Tailwind CSS for styling
- Dark mode support via class-based switching
- Mobile-responsive design
### Recent Changes
#### v0.5.3 - Sort Persistence and PWA Support
- Remember sorting preference (#85) - localStorage persistence
- Fix Tab and PWA icon missing (#84) - favicon, apple-touch-icon, manifest.json
- Input validation for sort parameters
- PWA meta tags on all HTML templates
#### v0.5.2 - Currency Improvements
- Enhanced currency support and conversion display
#### v0.5.1 - Dark Classic Theme and Calendar Fixes
- Dark classic theme option
- Calendar view improvements
#### v0.5.0 - Optional Login Support
- Optional authentication system
- Beautiful theme options
### Release Workflow
This project uses versioned branches for releases. See `CLAUDE.md` for the complete workflow.
**Quick Reference:**
1. Create versioned branch: `git checkout -b vX.Y.Z`
2. Track work with beads: `bd create`, `bd update`, `bd close`
3. Create draft release: `gh release create vX.Y.Z --draft`
4. Run code review agent before committing
5. Commit, push, create PR: `gh pr create`
6. Comment on GitHub issues: `gh issue comment`
7. Monitor PR CI: `gh run watch`
8. Merge PR and pin the updated `main` SHA as `RELEASE_SHA`
9. Verify the main Docker build for `--commit "$RELEASE_SHA"`
10. Publish at the verified commit: `gh release edit vX.Y.Z --target "$RELEASE_SHA" --draft=false`
### Common Tasks
#### Adding a New Feature
1. Create/update model in `internal/models/`
2. Add repository methods in `internal/repository/`
3. Add service logic in `internal/service/`
4. Create handler in `internal/handlers/`
5. Add routes in `cmd/server/main.go`
6. Update templates if needed
7. Add tests
#### Adding a New Schedule Type
1. Update `Subscription.Schedule` validation in `internal/models/subscription.go`
2. Update `AnnualCost()` and `MonthlyCost()` methods
3. Update frontend templates to include new option
4. Update date calculation logic if needed
#### Adding a New Currency
1. Add currency code to `SupportedCurrencies` in `internal/service/currency.go`
2. Add currency symbol mapping in `GetCurrencySymbol()` in `internal/service/settings.go`
3. Add currency option to currency selection in `templates/settings.html`
4. Update exchange rate handling if using Fixer.io
#### Adding a New Notification Method
1. Create notification config model in `internal/models/settings.go`
2. Create notification service in `internal/service/` (e.g., `ntfy.go`) implementing `NotificationChannel` and `ToCancelReminderChannel`; a channel without the latter silently receives no to-cancel reminders, so add it to the compile-time list in `notification_dispatcher.go`
3. Add config save/get methods to `SettingsService`
4. Add handlers in `internal/handlers/` (e.g., `settings_push.go`) that test with the submitted values rather than saving them
5. Add UI in `templates/settings.html` and strings in all of `web/locales/`
6. Register the channel with `NewNotificationDispatcher` in `cmd/server/main.go`; the subscription handler and reminder schedulers send through the dispatcher
### Environment Variables
- `PORT` - Server port (default: 8080)
- `DATABASE_PATH` - SQLite database path (default: ./data/subtrackr.db)
- `GIN_MODE` - Gin mode: debug/release (default: debug)
- `FIXER_API_KEY` - Fixer.io API key for currency conversion (optional)
### Building and Running
```bash
# Development
go run cmd/server/main.go
# Build
go build -o subtrackr cmd/server/main.go
# Docker
docker-compose up -d --build
```
### Testing
```bash
# Run Go tests
go test ./...
# Run E2E tests
npm test
# Test API
./test-api.sh
```
## Landing the Plane (Session Completion)
**When ending a work session**, you MUST complete ALL steps below. Work is NOT complete until `git push` succeeds.
**MANDATORY WORKFLOW:**
1. **File issues for remaining work** - Create issues for anything that needs follow-up
2. **Run quality gates** (if code changed) - Tests, linters, builds
3. **Update issue status** - Close finished work, update in-progress items
4. **PUSH TO REMOTE** - This is MANDATORY:
```bash
git pull --rebase
bd sync
git push
git status # MUST show "up to date with origin"
```
5. **Clean up** - Clear stashes, prune remote branches
6. **Verify** - All changes committed AND pushed
7. **Hand off** - Provide context for next session
**CRITICAL RULES:**
- Work is NOT complete until `git push` succeeds
- NEVER stop before pushing - that leaves work stranded locally
- NEVER say "ready to push when you are" - YOU must push
- If push fails, resolve and retry until it succeeds
<!-- BEGIN BEADS INTEGRATION -->
## Issue Tracking with bd (beads)
**IMPORTANT**: This project uses **bd (beads)** for ALL issue tracking. Do NOT use markdown TODOs, task lists, or other tracking methods.
### Why bd?
- Dependency-aware: Track blockers and relationships between issues
- Git-friendly: Auto-syncs to JSONL for version control
- Agent-optimized: JSON output, ready work detection, discovered-from links
- Prevents duplicate tracking systems and confusion
### Quick Start
**Check for ready work:**
```bash
bd ready --json
```
**Create new issues:**
```bash
bd create "Issue title" --description="Detailed context" -t bug|feature|task -p 0-4 --json
bd create "Issue title" --description="What this issue is about" -p 1 --deps discovered-from:bd-123 --json
```
**Claim and update:**
```bash
bd update bd-42 --status in_progress --json
bd update bd-42 --priority 1 --json
```
**Complete work:**
```bash
bd close bd-42 --reason "Completed" --json
```
### Issue Types
- `bug` - Something broken
- `feature` - New functionality
- `task` - Work item (tests, docs, refactoring)
- `epic` - Large feature with subtasks
- `chore` - Maintenance (dependencies, tooling)
### Priorities
- `0` - Critical (security, data loss, broken builds)
- `1` - High (major features, important bugs)
- `2` - Medium (default, nice-to-have)
- `3` - Low (polish, optimization)
- `4` - Backlog (future ideas)
### Workflow for AI Agents
1. **Check ready work**: `bd ready` shows unblocked issues
2. **Claim your task**: `bd update <id> --status in_progress`
3. **Work on it**: Implement, test, document
4. **Discover new work?** Create linked issue:
- `bd create "Found bug" --description="Details about what was found" -p 1 --deps discovered-from:<parent-id>`
5. **Complete**: `bd close <id> --reason "Done"`
### Auto-Sync
bd automatically syncs with git:
- Exports to `.beads/issues.jsonl` after changes (5s debounce)
- Imports from JSONL when newer (e.g., after `git pull`)
- No manual export/import needed!
### Important Rules
- ✅ Use bd for ALL task tracking
- ✅ Always use `--json` flag for programmatic use
- ✅ Link discovered work with `discovered-from` dependencies
- ✅ Check `bd ready` before asking "what should I work on?"
- ❌ Do NOT create markdown TODO lists
- ❌ Do NOT use external issue trackers
- ❌ Do NOT duplicate tracking systems
For more details, see README.md and docs/QUICKSTART.md.
<!-- END BEADS INTEGRATION -->