Repository Layout
Core Directories
cmd/ - Command Line Interface
Handles argument parsing, configuration loading, and application initialization.
- Parse
--dband--yelp-keyflags - Load environment variables from
.envfiles - Manage
~/.toni/configuration directory - Run onboarding flow for new users
- Load and save Yelp API credentials securely
root.go- Flag parsing, config resolution (119 lines)onboarding.go- Interactive setup wizard
internal/db/ - Database Layer
Provides typed database operations using raw SQL and the standard database/sql package.
restaurants- Restaurant entities with location and metadatavisits- Visit records linked to restaurantswant_to_visit- Wishlist entries with priority- Indexes on
visited_on,restaurant_id,priority
db.go- Database initialization and schema (68 lines)restaurants.go- Restaurant CRUD and aggregation queriesvisits.go- Visit tracking with joined querieswant_to_visit.go- Wishlist managementundo_helpers.go- State capture for undo/redo
All functions accept
*sql.DB as the first parameter and return domain types from internal/model. No database-specific types leak to upper layers.- List views use
JOINto fetch denormalized rows - Detail views use separate queries to avoid N+1
- All mutations return affected IDs for undo tracking
internal/model/ - Domain Types
Defines the core data model and Bubble Tea messages. This layer is pure data with no business logic.
types.go (149 lines):
msg.go (117 lines):
- Data-loaded messages:
VisitsLoadedMsg,RestaurantDetailLoadedMsg - Mutation messages:
VisitSavedMsg,DeleteVisitMsg - Navigation messages:
FormCancelledMsg,ConvertToVisitMsg
internal/ui/ - User Interface
Implements all screens, forms, tables, and visual components using Bubble Tea.
Core files:
app.go (1159 lines)
Root Bubble Tea model with:
Init()- Load initial dataUpdate()- Route messages and handle input (internal/ui/app.go:81)View()- Render current screen (internal/ui/app.go:277)- Mode handlers:
handleNavMode(),handleInsertMode() - Screen navigation:
switchTopLevel(), screen-specific nav handlers
Table-based screens
visits.go- Visits list with sortable/filterable columnsrestaurants.go- Restaurants list with aggregated statswant_to_visit.go- Wishlist with priority sorting
Detail screens
visit_detail.go- Visit details with edit/delete actionsrestaurant_detail.go- Restaurant info + visit history
table_controls.go- Reusable table component with column management, sorting, filteringstyles.go- Lip Gloss style definitions (colors, borders, spacing)keys.go- Keybinding maps for navigation and formshelp.go- Context-aware help overlaygraphics.go- ASCII art, terminal capability detectionprefs.go- UI preferences (column visibility, sort order) persisted to~/.toni/prefs.json
Update() and View() methods, called by the root model.
internal/search/ - External Integrations
Yelp Fusion API client for restaurant autocomplete.
yelp.go (230 lines):
- Business search with partial name matching
- Returns restaurant name, address, city, cuisine, price range
- 5-second timeout for network requests
- Graceful degradation if API unavailable
internal/util/ - Utilities
Shared formatting and validation functions.
format.go (181 lines):
- ISO 8601:
2026-03-04 - Full month:
January 4, 2026 - Short month:
Jan 4, 2026 - Numeric:
1/4/2026,01/04/2026
Application Entrypoint
main.go (54 lines)
Orchestrates initialization and launches the TUI:
CI/CD
.github/workflows/release.yml
Automated release builds for multiple platforms:
Build matrix:
- Linux: amd64, arm64
- macOS: amd64, arm64
- Windows: amd64, arm64
- Build with version from git tag:
-ldflags="-X main.version=${VERSION}" - Package as
.tar.gz(Unix) or.zip(Windows) - Upload to GitHub release
- Generate SHA256 checksums
- Go 1.23
CGO_ENABLED=0for static binaries
Configuration Files
go.mod
Module definition with minimal dependencies:
Runtime files (in ~/.toni/)
toni.db- SQLite database with all user dataprefs.json- UI preferences (column visibility, sort state)settings.json- Onboarding completion statusyelp_key- Encrypted Yelp API key (if configured)
Code Statistics
Total Go files: ~25 files Lines of code by layer:internal/ui/: ~3000 lines (largest layer - all screens and components)internal/db/: ~800 lines (database operations)internal/model/: ~270 lines (types and messages)internal/search/: ~230 lines (Yelp API client)internal/util/: ~180 lines (formatting)cmd/: ~300 lines (CLI and onboarding)main.go: ~54 lines
The codebase prioritizes clarity over cleverness. Each layer has a single responsibility, and dependencies flow downward (UI → Model → DB).