Skip to content

andreis/diet

Repository files navigation

diet.simi.pw – Personal Diet & Meal Planner

A personalized diet management tool for tracking elimination diets, IgG food intolerance test results, and meal planning.

Project Overview

A personalized diet management platform that helps users create, customize, and manage meal plans based on their dietary needs, food allergies, and preferences.

Core Concepts

Meal Plans:

  • Can be builtin (system-owned templates), published by users, or user-owned (personal plans that appear in their dashboard)
  • Mixable and matchable containers of per-day/week food options
  • Examples: Celiac, Gluten-Free, Paleo, Vegetarian, Vegan, Atkins, Intermittent Fasting

Food Preferences:

  • Metadata that tracks user-specific dietary requirements
  • Includes allergies, intolerances, dietary restrictions, and lifestyle choices
  • Used to filter meal plans and ensure safe food options (e.g., "user is allergic to nuts, so no meal plans should include nuts")

Food Options:

  • Individual meals with configurable variables
  • Example: A ham and cheese omelet can have variables for:
    • Number of eggs (e.g., 2)
    • Quantity of ham (e.g., 100g)
    • Quantity of cheese (e.g., 1 slice)
  • Variables have specified values in meal plans, but users can easily update them

Support Documents:

  • Users can upload PDFs, text files, or markdown files with food preferences/allergies
  • Documents are stored as base64 in the database (no object storage needed for small projects)

Features

  • Personalized Meal Plans: Create custom plans or choose from premade templates
  • Food Preference Management: Upload documents or enter freeform text about allergies and dietary restrictions
  • IgG Test Tracking: Track food intolerance test results (High, Borderline, Normal reactivity)
  • Meal Planning: Plan meals with safe options, add custom options dynamically
  • Reintroduction Challenges: Track food challenge testing during reintroduction phases
  • Week View Calendar: Monday-first week view with meal planning interface
  • Meal Plan Expansion: View detailed phase information, meal days, and options when expanding meal plans
  • Smart Meal Option Selection: Add meal options from active meal plans filtered by day of week and phase, with fuzzy search
  • Meal Memory: Remembers recently added food items, ordered by recency and usage count
  • Custom Meal Options: Add custom meal options for specific days with support for variables
  • Meal Copy Shortcuts: Copy meals from yesterday or last week (for same meal type or entire day)
  • User Avatar Caching: Profile images cached in localStorage with TTL to handle rate limiting
  • Theme Support: Light/dark/system theme with persistence
  • Meal Plan Import/Export: JSON format for sharing and backing up meal plans. Imported meal plans are automatically published to the public library.
  • Public Meal Plan Library: Browse all available meal plans with tabbed interface (Your meal plans / All meal plans)
  • Template Management: Delete unused meal plan templates from the public library (owners and admins only)
  • Real-time Updates: Meal plan changes (add/enable/disable/remove) update the UI without page reload

Tech Stack

  • Framework: Astro (SSR mode)
  • Auth: Auth.js (@auth/core) with Google OAuth
  • Database: SQLite (better-sqlite3)
  • ORM: Drizzle ORM
  • UI: Tailwind CSS + shadcn/ui (React components)
  • Deploy: Coolify-ready

Usage

Prerequisites

  • Node.js 18+ installed
  • npm or yarn package manager

Initial Setup

  1. Install dependencies:
   npm install
  1. Set up environment variables:

    Create a .env file in the project root with the following variables:

    AUTH_SECRET=your-secret-key-here-change-in-production
    AUTH_URL=https://your-domain.com  # Required in production (e.g., https://diet.simi.pw)
    GOOGLE_CLIENT_ID=your-google-client-id
    GOOGLE_CLIENT_SECRET=your-google-client-secret
    ADMIN_EMAILS=admin1@example.com,admin2@example.com
    DAILY_SIGNUP_LIMIT=15

    AUTH_SECRET:

    • This is a secret key used by Auth.js to encrypt session tokens and cookies
    • Generate a secure random string (at least 32 characters)
    • You can generate one using:
      openssl rand -base64 32
      Or use an online generator: https://generate-secret.vercel.app/32
    • Important: Use a different secret for production!

    AUTH_URL:

    • IMPORTANT: If deploying on Coolify, DO NOT set AUTH_URL in environment variables
    • Coolify may URL-encode this variable, which causes Auth.js to fail
    • The app automatically uses COOLIFY_URL (Coolify's predefined variable) instead
    • For other platforms: Set to the full URL of your application (e.g., https://diet.simi.pw)
    • Used by Auth.js to generate callback URLs for OAuth providers
    • Can be omitted in development (localhost)
    • Example (non-Coolify): AUTH_URL=https://diet.simi.pw

    ADMIN_EMAILS:

    • Comma-separated list of email addresses that have admin access
    • Admins can approve/reject user signups via the Admin panel
    • Admins are automatically approved on signup
    • Example: ADMIN_EMAILS=admin@example.com,another@example.com

    DAILY_SIGNUP_LIMIT:

    • Maximum number of unique email addresses that can sign up per day
    • Default: 15 if not specified
    • Helps prevent spam/DDoS attacks
    • Example: DAILY_SIGNUP_LIMIT=15

    Google OAuth Setup:

    To get GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET:

    1. Go to Google Cloud Console
    2. Create a new project or select an existing one
    3. Enable the Google+ API:
      • Navigate to "APIs & Services" > "Library"
      • Search for "Google+ API" and enable it
    4. Create OAuth 2.0 credentials:
      • Go to "APIs & Services" > "Credentials"
      • Click "Create Credentials" > "OAuth client ID"
      • If prompted, configure the OAuth consent screen first:
        • Choose "External" user type
        • Fill in app name, user support email, developer contact
        • Add your email to test users (for development)
      • Select "Web application" as the application type
      • Add authorized redirect URIs:
        • For local dev: http://localhost:4321/api/auth/callback/google
        • For production: https://yourdomain.com/api/auth/callback/google
      • Click "Create"
    5. Copy the Client ID and Client Secret to your .env file
  2. Start the application:

    The easiest way to start the app is to use the automated startup script:

    npm run start

    This command automatically:

    • Installs dependencies (npm install - idempotent)
    • Syncs database schema (drizzle-kit push - idempotent)
    • Seeds the database (npm run db:seed - idempotent)
    • Starts the Astro dev server with hot-reload

    The app will be available at http://localhost:4321

    Note: If you make schema changes, simply stop the server (Ctrl+C) and restart with npm run start. The schema will be automatically synced on restart.

    Alternative: If you've already run setup and just want to start the dev server:

    npm run dev

    Manual setup (if needed):

    npm run db:setup

    This runs all setup steps manually:

    • npm install
    • npx drizzle-kit push (syncs schema)
    • npm run db:seed (creates initial data)

    The seed script creates:

    • 16 builtin meal plan templates (Low-FODMAP, Mediterranean, Keto, Paleo, Vegetarian, Vegan, etc.)
    • Templates are stored in the global library and can be added to user libraries

    Login:

    • Use Google OAuth with your Google account

    Production build:

npm run build
npm run preview

Available Scripts

Command Action
npm run start Recommended: Full setup + dev server (install, sync schema, seed, dev)
npm run dev Starts Astro dev server only (assumes setup already done)
npm run build Builds production site to ./dist
npm run preview Preview production build locally
npm run db:setup Manual setup: install + sync schema + seed
npm run db:seed Seeds database with initial data (idempotent)
npm run db:push Sync schema changes to database (idempotent)
npx drizzle-kit generate Generate database migrations (usually not needed, push syncs directly)
npx drizzle-kit push Sync schema to database (idempotent)

Project Structure

/
├── src/
│   ├── components/      # React components (shadcn/ui)
│   ├── db/              # Database schema and seed script
│   ├── layouts/         # Astro layouts
│   ├── lib/             # Utility functions
│   ├── middleware.ts    # Auth middleware
│   └── pages/           # Astro pages and API routes
├── auth.config.ts       # Auth.js configuration
├── drizzle.config.ts    # Drizzle ORM configuration
└── .env                 # Environment variables (not in git)

Database

The application uses SQLite (local.db) for local development. The database schema includes:

Core Tables

  • Users & Auth: User accounts, sessions (Auth.js)
  • IgG Profiles: Food intolerance test results
  • Diet Plans: User's diet plans with phases
  • Meal Planning: Days, meals, and meal options
  • Reintroduction Challenges: Food challenge tracking

Extended Tables

  • Food Preferences: User allergies, intolerances, dietary restrictions
  • Support Documents: Uploaded PDFs/txt/md files stored as base64
  • Meal Option Variables: Configurable parameters for meal options (e.g., number of eggs, quantity of ham)
  • Meal Plan Templates: Builtin/premade plans that users can select (Celiac, Gluten-Free, Paleo, etc.)

Architecture

Meal Plan System

  1. Templates: Builtin or user-created meal plan templates
  2. User Plans: Personalized meal plans created from templates or from scratch
  3. Phases: Elimination, Reintroduction, or Personalization phases within a plan
  4. Meal Days: Days of the week or numbered days
  5. Meals: Breakfast, Lunch, Dinner, Snacks
  6. Meal Options: Individual food options with optional variables

Food Preferences Flow

  1. User uploads documents or enters freeform text
  2. Documents stored as base64 in database
  3. Preferences used to filter meal plans and ensure safe options

Creating Meal Plans with LLM

To create a custom meal plan using an LLM (ChatGPT, Gemini, etc.):

  1. (Optional) Add text files or freeform text to your food preferences
  2. Click the "Copy LLM Prompt" button to copy a prompt with your preferences and the meal plan JSON schema
  3. Go to your favourite LLM chat: Gemini, ChatGPT, etc.
  4. Paste the prompt
  5. Add your instructions for what kind of meal plan you're trying to create
  6. Copy the JSON response from the LLM
  7. Click "Import meal plan JSON" and paste the JSON to add it to your library

Note: Imported meal plans are automatically published to the public library, making them available to all users. You can delete your own unused templates from the "All meal plans" tab.

API Endpoints

Meal Plans:

  • GET /api/meal-plans/templates - List available meal plan templates (includes usage info and delete permissions)
  • GET /api/meal-plans/list - List user's meal plans
  • POST /api/meal-plans/create - Create a new personalized meal plan
  • POST /api/meal-plans/create-from-template - Create plan from template
  • POST /api/meal-plans/toggle - Enable/disable a meal plan
  • POST /api/meal-plans/delete - Remove a meal plan from user's library
  • DELETE /api/meal-plans/delete-template?templateId=... - Delete a template from the public library (owners and admins only, unused templates only)
  • GET /api/meal-plans/export?planId=... - Export meal plan as JSON
  • POST /api/meal-plans/import - Import meal plan from JSON (automatically publishes to public library)
  • GET /api/meal-plans/schema - Get JSON schema for meal plans

Preferences:

  • GET /api/preferences/get - Get user preferences (theme, week start day)
  • POST /api/preferences/update - Update user preferences
  • POST /api/preferences/documents - Upload food preferences document
  • POST /api/preferences/text - Save food preferences as text
  • GET /api/preferences/llm-prompt - Get LLM prompt with JSON schema and user preferences for meal plan generation

Meals:

  • GET /api/meals/selections?weekStart=... - Get meal selections for a week
  • POST /api/meals/add-option - Add meal option (existing or custom) for a specific date/meal type
  • POST /api/meals/remove - Remove a meal selection
  • GET /api/meals/memory?mealType=... - Get meal memory (recently added items) for a meal type
  • POST /api/meals/select - Save meal selections for a specific date (legacy)
  • POST /api/meals/options - Add custom meal option (legacy, use /api/meals/add-option)

Development Notes

  • Starting the app: Use npm run start for automatic setup. It handles all prerequisites idempotently.
  • Schema changes: After modifying src/db/schema.ts, restart with npm run start to automatically sync the schema.
  • Idempotent operations: All setup steps are idempotent:
    • npm install - Only installs missing packages
    • drizzle-kit push - Only syncs schema changes
    • db:seed - Checks for existing data and skips if found (non-destructive)
  • Database migrations are managed with Drizzle Kit (using push mode, not migrations)
  • The seed script creates 16 builtin meal plan templates (not user-specific data)
  • Meal Option Selection: The AddMealOptionDialog component:
    • Filters options from active meal plans based on day of week (0=Sunday, 1=Monday, ..., 6=Saturday, null=all days)
    • Calculates current phase from plan start date and current date
    • Respects applicable weeks (if specified in meal plan)
    • Shows meal memory (recently added items) when search is empty
    • Deduplicates items between memory and meal plan options
    • Hides already-selected items for the current day/meal type
  • Meal Memory: Tracks recently added food items, ordered by recency (70%) and usage count (30%)
  • Real-time Updates: Meal plan changes trigger custom events that update WeekView without page reload
  • User Avatar: Profile images are cached in localStorage with a 24-hour TTL to handle rate limiting. Falls back to user initials if image fails to load.
  • Theme: Theme preference (light/dark/system) is persisted in user preferences and localStorage
  • Confirmation Dialogs: Uses shadcn/ui AlertDialog for destructive actions (e.g., removing meal plans)

License

ISC

About

Personal meal planner

Resources

Stars

Watchers

Forks

Packages

No packages published

Languages