Skip to content

Latest commit

 

History

History
332 lines (231 loc) · 8.12 KB

File metadata and controls

332 lines (231 loc) · 8.12 KB

Development Workflow

Overview

This document defines the preferred day-to-day development workflow for this repo.

It is intentionally practical: the goal is to reduce ambiguity while the system is still being designed and built.

Related docs:


Core Principle

When a behavior crosses a boundary, we should document and test it at that boundary.

Examples:

  • HTTP behavior should be documented and exercised through HTTP requests
  • Plugin behavior should be documented through plugin contracts and tests
  • DB behavior should be documented through schema and query expectations

This keeps the design honest and helps prevent the docs from drifting away from actual usage.


API Development Workflow

Since this project is building a documented internal HTTP API, we should use httpyac for both:

  1. API documentation-in-use
  2. manual and automated API testing

Reference:

Why httpyac

We want one place where API work can be:

  • readable by humans
  • executable by developers
  • easy to version in git
  • close to the canonical route and payload definitions in docs/api.md

httpyac fits well because it lets us keep request examples as text files in the repo, execute them locally, organize environments, and reuse them during development.

Intended role of docs vs httpyac

  • docs/api.md defines the canonical API contract
  • httpyac request files define the executable examples and test flows

Put differently:

  • if someone asks, “what is the route shape?”, the answer should live in docs/api.md
  • if someone asks, “how do I actually call it and verify it works?”, the answer should live in httpyac files

Proposed Repo Structure

When implementation starts, add an API requests directory like:

http/
  environments/
    local.env.json
    test.env.json
  session.http
  plugins.http
  timeline.http
  insights.http
  share-profile.http

Suggested responsibilities:

  • http/session.http — login/logout/session checks
  • http/plugins.http — connect/import/disconnect/sync plugin flows
  • http/timeline.http — timeline listing and filters
  • http/insights.http — summary and aggregate queries
  • http/share-profile.http — preview and share profile config flows
  • http/environments/*.env.json — base URLs, auth/session helpers, local variables

If the API grows, split further by feature area.


API Route Workflow

For every new API endpoint or route change:

  1. Design the route in docs/api.md first

    • route path
    • method
    • request shape
    • response shape
    • error cases
  2. Add or update a httpyac request

    • happy path example
    • at least one failure/validation example when relevant
  3. Implement the server behavior

    • handler
    • validation
    • core call
    • serialization
  4. Run the httpyac requests against the local server

    • confirm response shape matches docs
    • confirm status codes and error envelopes
  5. Update docs if implementation reveals a better API shape

    • prefer improving the API over preserving a confusing route
    • keep docs/api.md and http/ examples in sync

Definition of done for an API route

A route is not fully done until all of the following are true:

  • documented in docs/api.md
  • exercised in httpyac
  • implemented in server code
  • aligned with auth/permissions expectations
  • returns stable JSON envelopes and status codes

httpyac Conventions

File organization

Each .http file should group related operations and read top-to-bottom as a workflow.

Example for plugins.http:

  • list plugins
  • get one plugin
  • start connect flow
  • import file
  • sync plugin
  • disconnect plugin

Naming

Use section comments that make intent obvious.

Example:

### List plugins
GET {{baseUrl}}/api/v1/plugins

### Sync Spotify
POST {{baseUrl}}/api/v1/plugins/spotify/sync

Environments

Use environment files for values like:

  • baseUrl
  • local test user identifiers if needed
  • CSRF token helpers if needed
  • session/cookie state when supported by the setup

Do not hardcode secrets into committed request files.

Coverage expectations

For important routes, prefer covering:

  • happy path
  • unauthorized request
  • validation error
  • not found
  • rate limited or conflict state when relevant

Example Request Layout

Illustrative example only:

@baseUrl = http://localhost:8080

### Session
GET {{baseUrl}}/api/v1/session

### List plugins
GET {{baseUrl}}/api/v1/plugins

### Get Spotify plugin state
GET {{baseUrl}}/api/v1/plugins/spotify

### Start Spotify connect flow
POST {{baseUrl}}/api/v1/plugins/spotify/connect
Content-Type: application/json

{}

### Sync Spotify
POST {{baseUrl}}/api/v1/plugins/spotify/sync
Content-Type: application/json

{}

### Timeline
GET {{baseUrl}}/api/v1/timeline?limit=20&offset=0

### Share profile preview
GET {{baseUrl}}/api/v1/share-profile/preview

Workflow for Changing Existing API Routes

When changing an existing route:

  1. update docs/api.md
  2. update the matching httpyac request file
  3. update implementation
  4. verify old examples are removed so stale routes do not linger in docs

This matters because route drift creates high cognitive load: developers stop knowing which doc is real, which example is current, and which behavior clients should trust.


Non-API Workflow Guidance

Architecture changes

When a change affects boundaries between client, server, core, plugins, or storage:

  • update docs/architecture.md
  • update docs/api.md if the client/server contract changes
  • update httpyac files if the HTTP surface changes

Plugin changes

When adding or changing a plugin:

  • update docs/plugin-guide.md if the shared contract changes
  • update the plugin-specific doc under docs/plugins/
  • add or update httpyac flows for user-visible plugin operations

Schema changes

When changing persisted fields that affect API responses:

  • update docs/schema.md
  • update docs/api.md response examples if needed
  • update relevant httpyac examples

Tool Management

This project uses mise for all tool and task management.

Installing tools

mise install

This installs Go, templ, sqlc, golang-migrate, air, and httpyac — all pinned in mise.toml.

Common tasks

mise run dev          # Start dev server with live reload (air)
mise run templ        # Generate templ files
mise run db-migrate   # Run database migrations
mise run db-rollback  # Rollback last migration
mise run sqlc         # Generate type-safe SQL from queries
mise run setup        # Full setup (migrate + templ + sqlc)
mise run build        # Build production binary
mise run api-test     # Run httpyac requests against local server

Environment variables

Defined in mise.toml under [env]:

  • DATABASE_URL — PostgreSQL connection string
  • PORT — HTTP server port (default 3000)
  • CSRF_KEY — 32-byte CSRF secret

Override locally with mise.local.toml (gitignored).


httpyac Setup

API request files live in http/ with environment configs in http/environments/:

http/
  environments/
    local.env.json      # baseUrl = http://localhost:3000
  health.http           # Health check
  session.http          # Login/logout/session (future)
  plugins.http          # Plugin operations (future)
  timeline.http         # Timeline queries (future)
  insights.http         # Insight aggregates (future)

Run requests:

# All requests
mise run api-test

# Single file
httpyac send http/health.http -e local

# Single request by name
httpyac send http/health.http --name "Health check" -e local

Practical Rule

If we add a route and cannot easily express it as a clean httpyac request, that is a signal to re-check the API design.

Good routes should be easy to:

  • describe in markdown
  • call from a request file
  • understand without reading server internals