Gander Labs logo
All projects

SoFat Personal AI Nutrition Coach

SoFat Personal AI Nutrition Coach
2024
SoFat.app

SoFat is a full-stack health and nutrition application that gives users a single place to track food intake, plan meals, manage weight, build recipes, and stay consistent through tasks and reminders —

SoFat.app — Case Study

AI-powered nutrition tracking and weight management for the modern web


Overview

SoFat is a full-stack health and nutrition application that gives users a single place to track food intake, plan meals, manage weight, build recipes, and stay consistent through tasks and reminders — all synchronized in real time across every device they own. The product sits at the intersection of personalized nutrition, AI-assisted food logging, and social accountability, wrapped in a clean, mobile-friendly UI.


The Problem

Nutrition tracking apps fall into two failure modes: they are either too rigid (requiring exact barcode scans for every food) or too loose (offering no guidance on whether a user is hitting targets). Existing tools rarely combine meal planning with meal logging, forcing users to juggle multiple apps. And almost none offer the kind of real-time cross-device sync that modern users expect — enter a meal on your phone and see it reflected on the tablet dashboard instantly.

SoFat was built to solve all three of these: flexible food logging backed by AI estimation, an integrated meal planner tied directly to the food log, and live multi-device sync powered by WebSockets.


Target Audience

  • Individuals tracking calories and macros for weight loss, muscle gain, or maintenance
  • Users following intermittent fasting protocols who need timer and reminder support
  • People who want AI-generated recipes and meal suggestions tailored to their remaining daily macros
  • Health-conscious users who want their data on their infrastructure rather than a third-party cloud

Core Features

Intelligent Food Logging

Three input paths are available so users can always log quickly:

  1. Barcode scan — the camera scans a product barcode and pulls nutrition data automatically.
  2. Text description — a user types "a bowl of oatmeal with banana" and OpenAI estimates the nutrition in structured JSON, removing friction entirely.
  3. Manual entry — full numeric control for known or custom foods.

Water intake is tracked as a first-class log type alongside food, with real-time broadcast to all open sessions.

AI Recipe Generation

Users provide constraints — diet type, cuisine, maximum prep time, target calorie range, number of servings — and the app calls GPT-3.5 Turbo to generate a complete recipe: ingredient list with amounts and units, step-by-step instructions, and a full macro breakdown. Generated recipes are saved to the user's library and can be cooked directly from the app, which walks through the instructions step by step.

AI Meal Recommendations

At any point during the day, users can request meal suggestions sized to fit their remaining macros. The app calculates how many calories, protein, carbs, and fat the user still has available, passes those targets along with their dietary preferences to the AI, and surfaces three to five concrete meal ideas they can log immediately or add to their meal plan.

Meal Planning

A weekly meal planner lets users slot meals into a structured schedule. Each meal in the plan tracks its own nutrition and completion status. Marking a meal complete automatically logs it to the food diary for that day — and unchecking it removes the entry — keeping the plan and the log always in agreement.

Intermittent Fasting Timer

Users configure a fasting window (e.g., 16:8), enable fasting from the dashboard, and a countdown timer tracks elapsed and remaining fasting time. Scheduled email reminders via Resend notify users when fasts begin and end. A celebration animation plays on successful completion.

Task & Reminder System

Todos can be linked directly to meals: completing a task (e.g., "eat pre-workout snack") automatically logs the associated meal's nutrition. Tasks support priority levels, categories, due dates, and email reminders. A recurring task pattern handles daily or weekly habits.

Weight Check-ins

Users log weight entries over time. The app surfaces a weekly check-in prompt (Monday through Wednesday) for users with active weight-loss or gain goals. Historical weight data feeds into a stats dashboard showing trends alongside calorie averages.

Real-Time Cross-Device Sync

Every data mutation — adding food, completing a meal, toggling a fast, checking off a task — broadcasts a typed sync event to all of the user's connected sessions via Socket.IO. A subtle toast notification informs the user when data arrives from another device. No manual refresh required.

Comprehensive Stats Dashboard

A dedicated analytics view aggregates today's nutrition, weekly trends, fasting history, macro compliance, and weight trajectory. All time calculations are user-timezone-aware so daily summaries always correspond to the user's local day.

Onboarding Wizard

New users are guided through a multi-step profile setup covering personal measurements (height, weight, age, gender), activity level, goals (lose / maintain / gain), target weekly rate, meal timing preferences, fasting configuration, measurement system, and timezone. The onboarding data drives personalized daily calorie and macro targets.

Admin Panel

Administrators have access to a protected panel covering:

  • User management — search, paginate, promote to admin, or delete any account with safeguards against self-deletion.
  • System health — live status of the database connection, OpenAI API availability, and Socket.IO uptime.
  • Analytics — user growth, activity, and data volume summaries.
  • Database status — record counts and last-activity timestamps.

Technical Architecture

Stack

| Layer | Technology | |---|---| | Framework | Next.js 15 (App Router) | | Language | TypeScript 5 | | Database | PostgreSQL via Prisma 5 | | Auth | NextAuth v4 (Credentials + Google OAuth) | | AI | OpenAI SDK (GPT-3.5 Turbo) | | Real-time | Socket.IO 4 | | Email | Resend | | Styling | Tailwind CSS 3 + Radix UI primitives | | Data fetching | TanStack Query v5 | | Validation | Zod | | Deployment | Docker + Coolify (self-hosted) |

Custom Node Server

Next.js runs behind a custom Node HTTP server (server.js) that attaches a Socket.IO instance to the same port. This design trades the simplicity of Vercel-style serverless deployment for a persistent process that can maintain WebSocket connections across requests. API routes broadcast events through a global.broadcastToUser function registered at startup, which Socket.IO uses to push sync events to all of a user's connected rooms.

Data Model

The PostgreSQL schema is organized around a central User model that carries both profile data and behavioral state:

  • FoodLog — every food and water entry, macro breakdown, meal type, and timestamp
  • WeightEntry — historical weight measurements
  • MealPlanWeekDayMeal — hierarchical weekly meal plan with per-meal nutrition and completion tracking
  • Recipe + RecipeIngredient — user recipe library with optional public visibility
  • Todo + optional mealId — tasks that can trigger automatic food log entries on completion
  • Reminder — scheduled notifications with send tracking

User preferences (daily targets, macro goals, fasting windows, meal times, measurement system, timezone) all live on the User record for fast, join-free reads on every dashboard load.

Nutrition Pipeline

Food logging follows a prioritized fallback chain designed to maximize ease of use without sacrificing data quality:

Barcode scan → OpenFoodFacts API
       ↓ (no result)
Text description → OpenAI JSON estimation
       ↓ (API unavailable or parse failure)
Manual / zeroed entry

AI Integration Points

| Endpoint | Prompt type | Model | |---|---|---| | POST /api/recipes/generate | Structured JSON recipe from user constraints | GPT-3.5 Turbo | | POST /api/meal-recommendations | 3–5 meals fitting remaining daily macros | GPT-3.5 Turbo | | POST /api/food-log (text path) | Nutrition estimation from food description | GPT-3.5 Turbo |

All three use JSON-only response mode with typed Zod validation. The meal recommendations endpoint includes a deterministic fallback generator that activates when the API is unavailable, so the feature never hard-fails for users.

Authentication

NextAuth is configured with JWT sessions (avoiding a session DB hit on every request) while still using PrismaAdapter for persisting OAuth accounts. A custom signIn callback links Google sign-ins to existing credential accounts by email. Admin access is gated by an isAdmin flag on the User record, checked server-side on both API routes and the admin layout.

Security

  • All API routes verify session before touching the database
  • X-Frame-Options: DENY, X-Content-Type-Options: nosniff, and Referrer-Policy headers set globally
  • Middleware rejects requests with Next-Action headers (server action probes) early, before any body parsing
  • Passwords hashed with bcryptjs; no plaintext credentials stored
  • Admin bootstrap requires a server-side secret (ADMIN_INIT_KEY) separate from user credentials
  • Cron endpoint protected by CRON_SECRET bearer token

Engineering Challenges & Solutions

Challenge: Real-time sync without a serverless model

Problem: Next.js on Vercel cannot maintain persistent WebSocket connections because each request spins up a fresh function invocation.

Solution: A custom Node HTTP server runs Next.js alongside a Socket.IO instance on the same port. This requires self-hosting (via Docker on Coolify) but gives the app true push-based sync without polling. API routes broadcast through a globally registered function, keeping the WebSocket logic entirely in one file.

Challenge: Timezone-aware daily boundaries

Problem: A user in Toronto logging dinner at 11:45 PM should see that entry under "today," not rolled over to the next day on the server's UTC clock.

Solution: Every query that groups by day — dashboard stats, food log fetches, fasting summaries — computes day start and end in the user's stored IANA timezone before constructing Prisma gte/lt filters.

Challenge: Flexible food logging with guaranteed fallback

Problem: Requiring a barcode for every food entry creates too much friction and fails for homemade or restaurant meals.

Solution: A three-tier pipeline (barcode → AI text estimation → manual) ensures users can always log quickly. The AI path uses a tight JSON-only prompt so the response can be parsed directly into the FoodLog schema. If the API is down, manual entry picks up with no error shown.

Challenge: Keeping the meal plan and food log in sync

Problem: A meal plan is forward-looking; a food log is backward-looking. Without integration, completing a planned meal would require a second manual logging step.

Solution: The meal completion API atomically marks the meal as complete and creates a matching FoodLog entry. Unchecking reverses both. The same pattern applies to todo items linked to meals — checking off the task logs the meal, unchecking removes it.


Key Metrics (Design Targets)

| Goal | Approach | |---|---| | Time to log a food entry | < 10 seconds via barcode or text | | Cross-device sync latency | < 500 ms via Socket.IO push | | Recipe generation time | ~ 5–10 seconds (GPT-3.5 Turbo streaming not yet used) | | Zero hard failures on AI unavailability | Deterministic fallbacks at every AI call site |


Deployment

The application is containerized with Docker and self-hosted on Coolify. The custom server architecture means a single container handles both the Next.js HTTP server and the Socket.IO WebSocket server. PostgreSQL runs as a separate service. Environment variables cover database connection, NextAuth secrets, Google OAuth credentials, OpenAI API key, Resend API key, and operational secrets for admin bootstrap and cron authentication.


Outcome

SoFat demonstrates that a small-team product can deliver a feature set that rivals category leaders — AI food recognition, live multi-device sync, integrated meal planning, fasting support, and full recipe management — while remaining entirely self-hosted on affordable infrastructure. The codebase also shows how a Next.js App Router app can step outside serverless constraints through a custom server without sacrificing the developer experience that makes Next.js productive.


Built with Next.js 15, PostgreSQL, Prisma, NextAuth, OpenAI, Socket.IO, Resend, Tailwind CSS, and Radix UI.

Share

Have a similar project in mind?

Talk to us →