Skip to content

Latest commit

 

History

479 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Food Scanner

AI-powered food logging for Google Health. Take a photo of your meal, let Claude analyze the nutrition, and log it directly to Google Health.

What It Does

  1. Photo capture — Take a photo of your food with your phone camera
  2. AI analysis — Claude analyzes the image and estimates nutritional information
  3. Review & edit — Confirm or adjust the nutrition data
  4. Log to Google Health — Post directly to your Google Health food log

Single-user application with email allowlist.


Tech Stack

  • Next.js 16+ (App Router, TypeScript)
  • Tailwind CSS + shadcn/ui for styling
  • iron-session for encrypted cookie-based sessions
  • Google OAuth 2.0 for authentication and Google Health API access
  • Google Health REST API for food logging (single shared OAuth client)
  • Anthropic Claude API for nutrition analysis (tool_use)
  • PostgreSQL via Railway (Drizzle ORM)
  • Railway for deployment

Environments

Environment Branch URL Health API
Production release food.lucaswall.me Live
Staging main food-test.lucaswall.me Dry-run (HEALTH_DRY_RUN=true)

Branch strategy:

  • main — development branch, auto-deploys to staging
  • release — stable branch, auto-deploys to production
  • Feature branches → PR to main → merge to staging → merge main to release

Each environment has its own Railway Postgres, environment variables, and domain.

Promotion flow: Merge mainrelease to deploy to production.


Deployment (Railway)

Prerequisites

  • Railway account
  • Railway CLI installed and authenticated (railway login)
  • GitHub repository pushed to origin

Step 1: Create Railway Project

  1. Go to railway.com/new
  2. Choose "Deploy from GitHub Repo"
  3. Select the food-scanner repository
  4. Railway creates the project and auto-deploys

Do not use railway init — that's for manual deploys, not GitHub-linked projects.

Step 2: Link CLI to Project

From the project directory:

railway link

Select the food-scanner project and environment when prompted. This stores the link in ~/.railway/config.json (global, not in the repo).

Step 3: Obtain OAuth Credentials

Follow the OAuth Setup section below to create Google OAuth credentials before setting environment variables.

Step 4: Set Environment Variables

railway variable set \
  SESSION_SECRET="$(openssl rand -base64 32)" \
  HEALTH_TOKEN_ENCRYPTION_KEY="$(openssl rand -base64 32)" \
  ALLOWED_EMAILS=wall.lucas@gmail.com \
  APP_URL=https://food.lucaswall.me \
  GOOGLE_CLIENT_ID=your-google-client-id \
  GOOGLE_CLIENT_SECRET=your-google-client-secret \
  ANTHROPIC_API_KEY=your-anthropic-api-key \
  LOG_LEVEL=info

For staging, also set:

railway variable set HEALTH_DRY_RUN=true

Note: HEALTH_TOKEN_ENCRYPTION_KEY is a dedicated 32-byte random key for encrypting Google Health tokens at rest. Rotating this key invalidates all stored tokens — users must re-link Google Health after rotation.

Set real values for all credentials.

Do not set NODE_ENV — Railway handles this automatically. Setting NODE_ENV=development breaks the Next.js production build.

Step 5: Generate Public Domain

railway domain

This creates a public URL like https://food-scanner-production-XXXX.up.railway.app.

Step 6: Update OAuth Redirect URIs

Once you have your Railway domain, go back to the Google Cloud Console and add the production redirect URI:

  • Google: https://<your-railway-domain>/api/auth/google/callback

Step 7: Verify

curl https://food-scanner-production-XXXX.up.railway.app/api/health

Should return { "success": true, "data": { "status": "ok" }, "timestamp": ... }.

Step 8: Add PostgreSQL Database

  1. Open your project in the Railway dashboard
  2. Click "+ New" on the Project Canvas
  3. Select "Database""PostgreSQL"
  4. Railway creates a Postgres service with auto-generated credentials

Connect the database to your app service

  1. Click on the food-scanner service in the canvas
  2. Go to the Variables tab
  3. Click "+ New Variable"
  4. Add DATABASE_URL with value ${{Postgres.DATABASE_URL}} — This uses Railway's reference variable syntax to dynamically resolve the Postgres connection string
  5. Railway will redeploy automatically after saving

Verify the connection

After the redeploy completes:

railway logs

Look for successful startup with no database connection errors. The app runs migrations automatically on startup — no manual migration step is needed.

Build & Start

Railway builds with Railpack, which auto-detects Next.js:

  • Build: npm run build (runs next build)
  • Start: npm start (runs next start)
  • Health check: GET /api/health returns 200

railpack.json replaces Railpack's deprecated NPM_CONFIG_PRODUCTION=false with NPM_CONFIG_INCLUDE=dev, so the build still installs devDependencies without npm's production config warning on every install, build and start.

Watch Paths are set in the Railway service settings (Settings → Build), not in a repo file — Railway's railway.json Config as Code is deprecated. Keep them in sync with the app paths in .github/workflows/ci.yml, plus railpack.json and .node-version.

Monitoring

railway logs            # Stream deploy logs
railway logs --build    # Stream build logs

Or use the Railway MCP from Claude Code to query logs and deployment status.

Custom Domain (Optional)

  1. Add custom domain in Railway dashboard → Settings → Networking
  2. Configure DNS (CNAME record pointing to Railway)
  3. Update OAuth redirect URIs in the Google Cloud Console to use the custom domain

External Services Setup

Anthropic API

Claude powers the AI food analysis. The model id lives in src/lib/claude.ts.

  1. Go to console.anthropic.com
  2. Create an account or sign in
  3. Navigate to API Keys in the sidebar
  4. Click Create Key and copy the API key
  5. Add to Railway: ANTHROPIC_API_KEY=sk-ant-api03-...

Note: The API key is included in Step 4 (Set Environment Variables) above.


OAuth Setup

Google OAuth

Food Scanner uses a single shared Google OAuth client for both login and Google Health API access.

  1. Go to Google Cloud Console
  2. Create a new project (or select existing)
  3. Navigate to APIs & Services → Credentials
  4. Click Create Credentials → OAuth 2.0 Client ID
  5. Select application type: Web application
  6. Under Authorized redirect URIs, add your environment URLs:
    • Production: https://food.lucaswall.me/api/auth/google/callback
    • Staging: https://<staging-railway-domain>/api/auth/google/callback
    • Local: http://localhost:3000/api/auth/google/callback
  7. Copy the Client ID and Client Secret

Google Health Scopes

Configured on the GCP OAuth consent screen, not via environment variables. The four scopes requested (see GOOGLE_HEALTH_SCOPES in src/lib/auth.ts) are all under https://www.googleapis.com/auth/:

  • googlehealth.nutrition.writeonly
  • googlehealth.profile.readonly
  • googlehealth.health_metrics_and_measurements.readonly
  • googlehealth.activity_and_fitness.readonly

IMPORTANT: every googlehealth.* scope is restricted. That requires OAuth verification plus an annual CASA assessment, and the consent screen must be In production — while it is in Testing, Google revokes refresh tokens every 7 days and caps the app at 100 users.

Users connect via the one-click /app/connect-health flow after logging in.


Local Development

See DEVELOPMENT.md for complete local setup instructions.


PWA (Add to Home Screen)

The app supports "Add to Home Screen" on mobile devices for a native-like experience.

Features:

  • Standalone display mode (no browser chrome)
  • Custom app icon on home screen
  • Portrait orientation lock

To install:

  1. Open the app in Safari (iOS) or Chrome (Android)
  2. Tap the Share button → "Add to Home Screen"
  3. The app launches in standalone mode

Customizing icons: Replace the placeholder icons in public/:

  • icon-192.png — 192x192 PNG
  • icon-512.png — 512x512 PNG

No service worker or offline support — the app requires an internet connection.


Documentation

File Description
API.md External API reference (auth, endpoints, schemas)
ROADMAP.md Feature ideas and specifications
CLAUDE.md Technical reference for Claude Code
DEVELOPMENT.md Local development setup
MIGRATIONS.md Pending production data migrations
PLANS.md Current implementation plan (managed by skills)
CHANGELOG.md Version history
README.md This file — deployment and operations

About

AI-powered food logging for Google Health — photograph a meal, Claude estimates the nutrition, log it

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages