Files
terminalShop/CLAUDE.md

8.1 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview

Terminal Coffee Shop is a terminal-based e-commerce application for ordering coffee, built with Go and the Bubbletea TUI framework. It's designed to eventually run as an SSH server similar to terminal.shop, with a backend API, PostgreSQL database, and Stripe payment integration.

Current Status: Phase 1 (Enhanced UI & Navigation) - The TUI is functional with shop, cart, and account views. Backend API has not been implemented yet.

Essential Reading

Before making any changes, read these files in order:

  1. README.md - Complete roadmap and current phase status
  2. MODELS.md - Technical specifications, architecture, code standards, error handling patterns
  3. CONTRIBUTING.md - Workflow guidance for AI-assisted development

Architecture

Current Structure (TUI-only)

terminalShop/
├── main.go                    # SSH server entry point (Wish framework)
├── pkg/
│   ├── tui/                   # Bubbletea TUI components
│   │   ├── model.go          # Main model with state management
│   │   ├── views.go          # View rendering and layout
│   │   ├── shop.go           # Shop view (left: coffee list, right: details)
│   │   ├── cart.go           # Cart view with scrolling
│   │   ├── account.go        # Account view (auto-updating right panel)
│   │   ├── header.go         # Tab navigation header
│   │   ├── footer.go         # Keybind hints
│   │   └── breadcrumbs.go    # Checkout flow breadcrumbs (cart only)
│   └── models/
│       └── coffee.go         # Coffee and CartItem models
└── .ssh/                     # SSH host keys

Planned Structure (Backend)

The api/ directory structure from MODELS.md will be created in Phase 2 with:

  • Chi router for HTTP endpoints
  • GORM models for PostgreSQL
  • JWT authentication middleware
  • Stripe payment integration

Key Architectural Patterns

TUI State Management (Bubbletea/Elm Architecture)

The Model struct in pkg/tui/model.go contains all application state:

  • Navigation state: ViewingCart, ViewingAccount, CheckoutStep
  • Cursor positions: Cursor (shop), CartCursor (cart), AccountCursor (account)
  • Data: Coffees (product list), Cart (map[int]*CartItem)
  • Scroll: ScrollOffset for handling overflow

Critical Pattern: All views (shop, cart, account) follow a left-panel + right-panel layout:

  • Left panel: List of items with cursor navigation (j/k)
  • Right panel: Details that auto-update based on cursor position
  • No Enter/ESC navigation - hovering updates the right panel immediately

View Rendering Flow

  1. views.go:View() - Main entry point, handles vertical centering and scrolling
  2. Calls view builders: BuildShopView(), BuildCartView(), BuildAccountView()
  3. Each view uses lipgloss.JoinHorizontal() for left+right layout
  4. Fixed content height calculated dynamically to prevent UI shifting

Cart Management

Important: Cart uses map[int]*models.CartItem where the key is the coffee index in m.Coffees. This enables fast lookups but requires sorting in GetCartItemsSlice() because Go maps have randomized iteration order.

Scrolling System

Implemented for cart view to handle long lists on small terminals:

  • ScrollOffset tracks current scroll position (line-based, not item-based)
  • Each cart item is ~5 lines tall (including borders)
  • Auto-scrolls when navigating with j/k to keep selected item visible
  • Manual scroll with pgup/pgdn

Build and Run Commands

# Build and run SSH server
go build -o terminalshop && ./terminalshop
# Server listens on localhost:23457
# Connect with: ssh localhost -p 23457

# Quick run without building
go run main.go

# Add dependencies
go get <package>
go mod tidy

Development Workflow

Adding a New View Component

  1. Create new file in pkg/tui/ (e.g., shipping.go)
  2. Add build function following the pattern: func (m Model) BuildShippingView() string
  3. Use left-panel + right-panel layout with lipgloss.JoinHorizontal()
  4. Update views.go:View() to conditionally render the new view
  5. Add navigation state to Model struct in model.go
  6. Add keybinds in model.go:Update()
  7. Update footer.go with new keybind hints

Modifying Existing Views

The shop, cart, and account views are split across multiple files but all follow the same pattern:

  • Use lipgloss.NewStyle() for styling
  • Fixed widths for panels (leftWidth typically 18, rightWidth calculated)
  • Cursor-based selection with colored highlights
  • Responsive to WindowWidth and WindowHeight

Working with the Model

When adding state to the Model struct:

  1. Add field to struct definition in model.go
  2. Initialize in NewModel() constructor
  3. Reset appropriately when changing views (see case "s", case "c", case "a")
  4. Update in Update() function based on user input

Important Implementation Details

Styling Conventions

  • Active/selected: White (#FFFFFF), bold
  • Inactive: Gray (#666666)
  • Accent color: Steel blue (#4682B4) - used for cart breadcrumbs and highlights
  • Coffee colors: Use individual coffee's .Color field (hex values like "#8B4513")

Window Size Handling

views.go automatically adjusts content height based on terminal size:

  • Calculates available space after header, breadcrumbs, footer, margins
  • Minimum content height of 3 lines
  • Margins scale down on small windows (< 25 lines height)
  • Truncates content and enables scrolling when needed

Breadcrumbs

Only visible in cart view, showing checkout flow: cart / shipping / payment / confirmation

  • Current step (tracked in CheckoutStep) is white/bold
  • Future steps are gray
  • Will be used when implementing checkout pages in later phases

SSH Server

main.go uses Wish (Charm's SSH framework) to serve the TUI over SSH:

  • Host key in .ssh/term_info_ed25519
  • Port 23457
  • Each SSH session gets its own Bubbletea program instance
  • Username passed to tui.NewModel(username)

Common Gotchas

  1. Map iteration order: Always sort cart items in GetCartItemsSlice() to prevent random reordering
  2. Scroll offset: When adding scrolling to new views, update viewport height calculation (currently hardcoded as -9 for cart with breadcrumbs)
  3. Content height: Fixed height prevents UI shifting between pages but must account for all UI elements (header, breadcrumbs, footer, margins)
  4. Panel widths: Left panel is 18 chars, right panel is WindowWidth - leftWidth - leftMargin - 4
  5. Reset scroll: Always reset ScrollOffset = 0 when switching views

Code Style (from MODELS.md)

  • Imports: stdlib, external deps, internal packages (separated by blank lines)
  • Error messages: lowercase, no punctuation, use %w for wrapping
  • Comments: Start with function/type name, complete sentences
  • Struct tags: Always include json tags with snake_case
  • Context: Always first parameter in functions

Reference Implementation

terminal-shop-source/ contains the full terminal.shop codebase (TypeScript/Go hybrid):

  • packages/go/pkg/tui/*.go - TUI patterns and components
  • packages/go/cmd/ssh/main.go - SSH server setup
  • Study patterns, don't copy verbatim (different tech stack)

Next Steps (from Roadmap)

Current phase is wrapping up. Next major phase:

  • Phase 2: Backend API Foundation with Chi router, PostgreSQL, GORM models
  • See MODELS.md for complete API specification and database schema
  • See README.md Phase 2 tasks for implementation order

Environment Setup

Copy .env.example to .env and configure:

  • DATABASE_URL - PostgreSQL connection (for Phase 2)
  • JWT_SECRET - Auth token secret (for Phase 3)
  • STRIPE_SECRET_KEY / STRIPE_PUBLIC_KEY - Payment integration (for Phase 5)
  • SSH_PORT - Default 2222 (currently using 23457)

Testing

Currently no tests. Testing standards defined in MODELS.md for future API implementation:

  • Unit tests for business logic
  • Integration tests for API endpoints
  • Use testify for assertions
  • Table-driven test pattern