# Build brief — a focused alternative to Cal AI

> **Verdict:** Partly, if you narrow it · **Buildability:** 46/100 · **Category:** Wellness
> **Source:** https://www.canitbevibecoded.com/cal-ai
> Independent editorial assessment from Can It Be Vibe Coded? Not affiliated with, endorsed by, or derived from Cal AI. Verify current pricing and capabilities before acting.

## Context

**Cal AI** — Point your phone at a plate of food and get a calorie and macro estimate logged to a daily total. It currently costs $9.99/mo.

The core trick, send a food photo to a multimodal model and ask for calories and macros as JSON, is a one-evening build and works surprisingly well. Where it stops being easy is everything around it: a native app that opens fast, a camera flow you actually use three times a day, barcode lookups against a real food database, HealthKit or Google Fit sync, and streaks that keep you logging past day four. Accuracy is also less about your prompt and more about calibration, portion-size guessing is where these apps live or die and you have no correction data. A local PWA is a genuinely useful personal replacement if you are the kind of person who will tolerate a browser bookmark instead of an app icon. You are also renting the vision model, so this is not fully self-contained.

This brief describes a focused, single-operator replacement for the part of Cal AI that is genuinely reproducible. It is deliberately narrower than the product it replaces, and it says so in writing. Build the useful core; do not pretend to have rebuilt the rest.

## What you are building

Snap or upload a food photo, a vision model returns dish name, portion guess and macros as structured JSON, and it gets appended to a local daily log with running totals.

- Log workouts and nutrition, track trends, and keep personal health data exportable.
- A responsive interface with real empty, loading, success, and error states.

## Requirements

### Functional

- Node 20 and a machine or cheap VPS to run it.
- A phone browser, added to home screen, for the camera flow.
- Acceptance that portion estimates will be wrong by 20 percent sometimes.

### Data and integrations

- An API key for a multimodal model that accepts images.

Each of these needs a real account, credential, or quota. Set them up before writing feature code.

### Non-functional

- Accessibility: semantic markup, labelled controls, visible focus, and reduced-motion support.
- Security: server-side secrets, validated input, and no credentials in the client bundle.
- Reliability: retries with backoff on external calls, and a clear failure state when a provider is down.
- Portability: the operator can export their data and leave without losing it.

## Implementation brief

Build a self-hosted photo calorie logger as a mobile-first PWA. No accounts, no cloud, no telemetry, single user.

Stack, no substitutions:
- Next.js 15 App Router, TypeScript, Tailwind. Server actions and route handlers only, no separate API service.
- SQLite via better-sqlite3, file at ./data/food.db, schema created on boot if missing.
- OpenAI-compatible chat completions with image input for the estimate. Read OPENAI_API_KEY and MODEL from .env. Commit a .env.example, never a real key.

Core loop:
1. Home screen shows today: total kcal, protein, carbs, fat, plus a list of logged entries with thumbnails and a delete button on each.
2. A big camera button uses an input type="file" with accept="image/*" and capture="environment". Resize client side to max 1024px on the long edge, JPEG quality 0.8, before upload.
3. Server action stores the image under ./data/uploads, then sends it to the model with a strict instruction: identify each distinct food item, estimate portion in grams, return JSON only matching { items: [{ name, grams, kcal, protein_g, carbs_g, fat_g, confidence }], notes }. Use JSON response format and validate with zod. On parse failure, retry once, then surface an error, do not fake numbers.
4. Show a confirmation screen listing detected items with editable grams. Editing grams rescales that item's macros linearly. Save writes one row per item plus a parent meal row.
5. Manual entry form as a fallback: name, grams, kcal, macros. No barcode scanning, no external food database.

Also include:
- A daily kcal and protein target stored in a settings table, shown as progress bars.
- A /history page: last 30 days, one row per day with totals, and a tiny inline bar chart drawn with divs, no chart library.
- Export button that dumps all entries as CSV.
- PWA manifest and an icon so it can be added to a phone home screen. Offline is out of scope, say so in the README.

Explicitly out of scope: auth, multi-user, HealthKit or Google Fit sync, push notifications, streaks, recipes, native apps.

Deliver a README with setup, .env vars, how to run on a LAN so the phone can reach it, and one blunt paragraph noting that portion estimates from a photo are rough and the edit-grams step is not optional if you care about the numbers.

## Delivery standard

- Inspect the repository first, then write a short implementation plan before writing code.
- Deliver the smallest complete end-to-end workflow first; every primary control must work against persisted data.
- Use real validation and storage; never substitute fake dashboards, decorative controls, hard-coded success states, or mock integrations.
- Include responsive layouts plus genuine empty, loading, success, validation, and failure states.
- Keep secrets server-side in environment variables, provide .env.example, and never commit credentials or user data.
- Add structured logs around every external call and return actionable errors without leaking sensitive details.
- Write unit tests for the core logic and one automated test of the main user journey.
- Finish with a README covering setup, architecture, data location, backups, tests, deployment, and known limitations.

## Acceptance criteria

- [ ] A clean install starts the app using only the README and .env.example.
- [ ] The primary journey works from first visit through saved result, reload, edit, export, and deletion where applicable.
- [ ] Invalid input, missing configuration, provider failure, and an empty database each have a usable state.
- [ ] The interface works at 390px and 1440px, is keyboard navigable, and shows visible focus on every control.
- [ ] Tests, type checking, linting, and a production build all pass with no ignored failures.
- [ ] No part of the interface implies a live integration, security guarantee, or scale capability that was not actually built and verified.

## Non-goals

Do not build these, and do not claim to have replaced them:

- A native app with widgets, notifications and instant cold start.
- Barcode scanning against a maintained packaged-food database.
- HealthKit / Google Fit / Apple Watch sync.
- Streaks, coaching copy and the habit scaffolding that makes tracking stick.
- Whatever portion-size calibration they have learned from millions of corrected logs.

## What you still own after launch

- Secure credentials, rotate secrets, and handle provider rate limits.
- Run migrations, backups, restores, and dependency updates.
- Test the critical journey after every model, API, or hosting change.
- Monitor failures and fix the edge cases a first prompt will miss.

## Risk

**Operational risk.** The code is achievable; dependable data, integrations, and ongoing operations are the real cost.

Editorial confidence in this assessment: medium. No reviewed project implementation is linked yet.

---

Generated by [Can It Be Vibe Coded?](https://www.canitbevibecoded.com) · Full report: https://www.canitbevibecoded.com/cal-ai
