saltybytes-api

module
v0.0.0-...-b32e876 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 13, 2026 License: AGPL-3.0

README

SaltyBytes API

Backend for SaltyBytes — a recipe app for iOS and Android. Search the web for recipes without the ads and life stories, import from any source, generate with AI, and cook hands-free with voice-guided cooking mode.

Built with Go, Gin, PostgreSQL + pgvector, and Claude AI.

See also: saltybytes-app — the Flutter iOS client | saltybytes-dashboard — the operational metrics dashboard.

Features

Recipe Search & Discovery — Search the web for recipes and get clean results — no ads, no SEO spam, no scrolling past someone's vacation story. Multi-tier pipeline: exact-match cache, pgvector semantic similarity, and Brave web search. Import any result directly into your collection.

Multi-Source Import — Import recipes from URLs (with JSON-LD extraction and Firecrawl fallback), photos (vision-based), freeform text, or manual entry. A canonical recipe cache deduplicates URL imports with automatic background refresh.

AI Recipe Generation — Create recipes through conversation with Claude when you can't find what you're looking for. Fork existing recipes into new variants, regenerate with feedback, and explore branching version history through a recipe tree.

Family Allergen Analysis — AI-powered ingredient analysis detects common allergens (dairy, nuts, shellfish, wheat, soy, sesame, etc.) with confidence scoring. Cross-reference results against family members' dietary profiles.

Real-Time Cooking Mode — WebSocket-based hands-free cooking. Voice commands are transcribed (Whisper), classified by intent (Claude), and answered contextually. Supports ephemeral recipe edits during cooking.

AI Dietary Interviews — Conversational dietary profiling for family members, covering allergies, intolerances, and preferences.

Architecture

Handlers → Services → Repositories → PostgreSQL (GORM)
Layer Purpose
internal/handlers/ HTTP request handling and validation
internal/service/ Business logic, AI orchestration
internal/repository/ Database access via interfaces (DI-friendly)
internal/models/ Data models and GORM schema
internal/ai/ Anthropic, OpenAI, and Brave Search providers
internal/ws/ WebSocket server for cooking mode
internal/middleware/ JWT auth, rate limiting, request context
configs/ AI prompt templates (YAML)
External Services
Service Used For
Anthropic Claude Recipe generation, allergen analysis, dietary interviews, voice intent classification, cooking Q&A
OpenAI DALL-E 3 (recipe images), Whisper (voice transcription), text-embedding-3-small (vector search)
Brave Search Web recipe discovery
AWS S3 Recipe image storage
PostgreSQL + pgvector Data persistence and semantic similarity search

Getting Started

Prerequisites
Setup
  1. Clone the repository
git clone https://github.com/windoze95/saltybytes-api.git
cd saltybytes-api
  1. Configure environment variables
cp .env.example .env

See docs/env-setup.md for a detailed walkthrough of every variable, including how to create API keys and configure AWS.

  1. Run with Docker Compose (recommended)
docker compose up

This starts the API and a PostgreSQL instance. The database schema is auto-migrated on startup.

  1. Or run directly
go run ./cmd/api
Environment Variables
Variable Required Purpose
DATABASE_URL Yes PostgreSQL connection string
JWT_SECRET_KEY Yes Token signing secret
ANTHROPIC_API_KEY Yes Claude — recipe gen, allergens, voice, dietary
OPENAI_API_KEY Yes DALL-E, Whisper, embeddings
AWS_REGION Yes AWS region for S3
S3_BUCKET Yes Image storage bucket
ID_HEADER Yes Request validation header
BRAVE_SEARCH_KEY No Web recipe search (gracefully disabled if absent)
AWS_ACCESS_KEY_ID No S3 auth (falls back to IAM role)
AWS_SECRET_ACCESS_KEY No S3 auth (falls back to IAM role)
PORT No Server port (default: 8080)
GIN_MODE No Set to release for production

API Overview

Authentication
  • POST /v1/users — Create account
  • POST /v1/auth/login — Login
  • POST /v1/auth/refresh — Refresh token
Recipes
  • POST /v1/recipes/chat — Generate recipe via conversation
  • PUT /v1/recipes/:id/chat — Regenerate with feedback
  • POST /v1/recipes/:id/fork — Fork into a new variant
  • GET /v1/recipes/:id/tree — Version history tree
  • GET /v1/recipes — List user's recipes
  • DELETE /v1/recipes/:id — Delete recipe
Import
  • POST /v1/recipes/import/url — Import from URL
  • POST /v1/recipes/import/photo — Import from photo
  • POST /v1/recipes/import/text — Import from text
  • POST /v1/recipes/import/manual — Manual entry
  • POST /v1/recipes/preview/url — Quick URL preview
  • GET /v1/recipes/search — Search recipes (semantic + web)
  • GET /v1/recipes/similar/:id — Find similar recipes
Allergens
  • POST /v1/recipes/:id/allergens/analyze — Run allergen analysis
  • GET /v1/recipes/:id/allergens — Get analysis results
  • POST /v1/recipes/:id/allergens/check-family — Cross-reference family dietary profiles
Family & Dietary
  • POST /v1/family — Create family
  • POST /v1/family/members — Add member
  • PUT /v1/family/members/:id/dietary — Update dietary profile
  • POST /v1/family/members/:id/dietary/interview — AI dietary interview
Cooking Mode
  • GET /v1/ws/cook/:id — WebSocket connection for hands-free cooking

Testing

All tests run offline — no database, network, or external services required. Services accept repository interfaces for dependency injection.

# Run all tests
go test ./... -count=1

# Verbose
go test ./... -v -count=1

# Specific package
go test ./internal/service/ -v

# Lint
go vet ./...

Deployment

The CI/CD pipeline runs automatically via GitHub Actions:

  • On PR to main — vet, test, build validation
  • On merge to main — vet, test, Docker build, push to ECR, deploy to ECS (Fargate)
Manual deployment
docker build --platform linux/amd64 -t saltybytes-api .

The Dockerfile uses a multi-stage build (Go 1.24 builder → distroless runtime) for a minimal production image.

Tech Stack

  • Language: Go 1.24
  • Framework: Gin
  • ORM: GORM
  • Database: PostgreSQL 17 + pgvector
  • AI: Anthropic Claude, OpenAI (DALL-E, Whisper, Embeddings)
  • Search: Brave Search API
  • Storage: AWS S3
  • Auth: JWT (golang-jwt)
  • WebSocket: gorilla/websocket
  • Logging: zap
  • Container: Docker (distroless base)
  • CI/CD: GitHub Actions → ECR → ECS Fargate

License

This project is dual-licensed:

  • Open Source: GNU Affero General Public License v3.0 (AGPL-3.0) — you are free to use, modify, and distribute this software, provided that any derivative work or network service built with it is also released under the AGPL-3.0.
  • Commercial: If you wish to use this software in proprietary/closed-source applications without the AGPL-3.0 obligations, a commercial license is available. Contact the maintainer for details.

Directories

Path Synopsis
cmd
api command
sitepreview command
Command sitepreview serves the public website (internal/web) with canned fixture data on localhost — no database, no network.
Command sitepreview serves the public website (internal/web) with canned fixture data on localhost — no database, no network.
internal
ai
db
email
Package email sends transactional email (signup verification codes) through Amazon SES.
Package email sends transactional email (signup verification codes) through Amazon SES.
iap
Package iap implements store-side purchase verification for the App Store (StoreKit 2 signed JWS, verified locally against Apple's pinned root CA) and Google Play (Android Publisher API), plus the account-token scheme that ties store purchases back to SaltyBytes users.
Package iap implements store-side purchase verification for the App Store (StoreKit 2 signed JWS, verified locally against Apple's pinned root CA) and Google Play (Android Publisher API), plus the account-token scheme that ties store purchases back to SaltyBytes users.
mcpserver
Package mcpserver exposes SaltyBytes as a remote MCP server: OAuth-protected tools over Streamable HTTP at /mcp, with MCP Apps widgets rendered in-chat by hosts like Claude and ChatGPT.
Package mcpserver exposes SaltyBytes as a remote MCP server: OAuth-protected tools over Streamable HTTP at /mcp, with MCP Apps widgets rendered in-chat by hosts like Claude and ChatGPT.
notify
Package notify pushes operational alerts to an ntfy topic so the operator hears about problems (budget trips, provider failures) from their phone, with a tap-through link to the place where the problem gets fixed.
Package notify pushes operational alerts to an ntfy topic so the operator hears about problems (budget trips, provider failures) from their phone, with a tap-through link to the place where the problem gets fixed.
s3
units
Package units is the single source of truth for SaltyBytes' unit handling: canonical unit metadata (dimension, measurement system, factor to a base unit), measure-kind classification, base-quantity normalization, and deterministic display conversion.
Package units is the single source of truth for SaltyBytes' unit handling: canonical unit metadata (dimension, measurement system, factor to a base unit), measure-kind classification, base-quantity normalization, and deterministic display conversion.
video
Package video handles importing recipes from social/video links by acquiring the video's caption, transcript, and downloadable media via the ScrapeCreators API, then (in later layers) sampling frames and extracting the recipe.
Package video handles importing recipes from social/video links by acquiring the video's caption, transcript, and downloadable media via the ScrapeCreators API, then (in later layers) sampling frames and extracting the recipe.
web
Package web serves the public marketing site and shareable recipe pages at the apex domain (saltybytes.ai).
Package web serves the public marketing site and shareable recipe pages at the apex domain (saltybytes.ai).
ws

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL