NutriChef is a full-stack nutrition tracking web application engineered to eliminate guesswork in home-cooked meal management. It provides precise calculations of calories, proteins, fats, and carbohydrates based on raw ingredients and cooked portion weights, paired with a daily diary, customizable nutritional goals, and an automated macronutrient calculator.
Live Preview: https://nutrichef-ten.vercel.app/
- Overview
- Interface Preview
- Key Features
- Technology Stack
- Security Architecture
- Project Structure
- Getting Started
- Testing and Code Quality
- API Reference
- License
Traditional calorie-tracking applications frequently fail when handling multi-ingredient home-cooked meals due to moisture evaporation during cooking and non-linear yield factors. NutriChef addresses this by calculating exact macronutrient densities per 100 grams of prepared dish:
This guarantees that any portion logged into the user's daily diary accurately reflects actual dietary intake.
- Calculates nutritional values (Calories, Protein, Fat, Carbohydrates) per 100g and for any served portion.
- Computes caloric distribution percentages (P/F/C ratios).
- Saves recipes directly to a private meal collection.
- Interactive date navigator with day-by-day logging.
- Categorized logs for Breakfast, Lunch, Dinner, and Snacks.
- Real-time visual progress bars tracking consumption against target goals.
- Daily wellness and mindful eating recommendations.
- Search, filter, edit, and delete saved recipes.
- Quick logging of saved meals directly to the active date with portion scaling.
- Custom daily targets for calories, protein, fat, and carbs.
- Scientific macro calculator based on the Mifflin-St Jeor equation:
- Basal Metabolic Rate (BMR) estimation using age, gender, height, and weight.
- Total Daily Energy Expenditure (TDEE) based on activity coefficients.
- Goal adjustments for weight loss, maintenance, or muscle gain.
- Local registration and login with bcrypt password hashing.
- Google OAuth 2.0 authentication integration.
- Secure avatar upload with file signature validation (magic bytes) and automatic disk cleanup.
- Account deletion with cascading data removal.
- Framework: React 19
- Build Tool: Vite 8
- Routing: React Router DOM v7 (with
React.lazycode splitting) - Styling: SCSS (Modular Sass with design tokens and responsive mixins)
- HTTP Client: Axios (with custom auth interceptors and 15s timeout)
- UI Components & Icons: Lucide React, React Toastify
- Resilience: Custom React
ErrorBoundaryfallback
- Runtime: Node.js
- Framework: Express 5
- ORM: Prisma Client v6
- Database: PostgreSQL
- Authentication: JSON Web Tokens (
jsonwebtokenwith HS256 algorithm enforcement) andbcryptjs - Security: Helmet, Express Rate Limit, CORS protection
- File Processing: Multer with magic-byte image validation
- Mailing: Nodemailer (password reset flow)
NutriChef has undergone a comprehensive backend and client-side security audit:
- Rate Limiting: Tiered protection against brute-force and denial-of-service attacks via
express-rate-limit:- 300 requests / 15 min on general API endpoints.
- 10 requests / 15 min on sensitive auth routes (
login,forgot-password,reset-password). - 10 registrations / hour per IP address.
- Enumeration Protection: The
forgotPasswordendpoint returns a uniform200 OKresponse regardless of email existence, preventing account harvesting. - JWT Hardening: Explicit
HS256algorithm specification on token generation and verification, preventing algorithm-confusion attacks. - Upload Hardening: Avatar uploads enforce file extension whitelists (
.jpg,.jpeg,.png,.webp,.gif), MIME checks, and strict magic-byte signature inspection (FF D8 FF,89 50 4E 47,RIFF/WEBP,GIF8). - Database Indexing: Targeted compound and single-column indexes on
Meal(userId) andDailyLog(userId, date,mealId) for high-throughput queries. - Client Resilience: Global
ErrorBoundarypreventing application unmounts, network timeout boundaries, and sanitized error messages hiding stack traces in production.
nutrichef/
|-- client/ # Frontend React Application
| |-- public/ # Static public assets (favicon, logo)
| |-- src/
| | |-- api/ # Axios instance and API service modules
| | |-- assets/ # Processed images and graphics
| | |-- components/ # Reusable UI elements, modals, layout
| | |-- context/ # AuthContext state provider
| | |-- pages/ # Route views (Landing, Dashboard, Settings, etc.)
| | |-- routes/ # Route configuration with code-splitting
| | |-- styles/ # SCSS variables, mixins, reset, global styles
| | `-- utils/ # Date helpers, math formulas, user formatters
| |-- index.html # HTML entry point with SEO metadata
| `-- package.json
|
|-- server/ # Backend Express Application
| |-- prisma/
| | `-- schema.prisma # Prisma database schema and indexes
| |-- src/
| | |-- controllers/ # Request handlers (auth, meals, logs, dashboard)
| | |-- middleware/ # Auth verification, rate limiting, file upload
| | |-- routes/ # Express API routes
| | |-- services/ # Nodemailer email service
| | `-- app.js # Express app configuration
| |-- test/ # Node.js automated test suites (93 tests)
| |-- .env.example # Environment variables reference
| `-- package.json
|
`-- README.md
- Node.js (v18.x, v20.x, or v22.x recommended)
- PostgreSQL database instance
- npm or yarn package manager
-
Clone the repository:
git clone https://github.com/OkayMarta/nutrichef.git cd nutrichef -
Install backend dependencies:
cd server npm install -
Install frontend dependencies:
cd ../client npm install
Create a .env file in server/ using server/.env.example as a template:
# Server Configuration
PORT=5000
NODE_ENV=development
# PostgreSQL Connection
DATABASE_URL="postgresql://username:password@localhost:5432/nutrichef_db?schema=public"
# JWT Authentication
JWT_SECRET="generate_a_secure_random_string_here"
JWT_EXPIRES_IN="7d"
# Google OAuth 2.0 (Optional)
GOOGLE_CLIENT_ID="your-client-id.apps.googleusercontent.com"
# Client URL (for CORS & Reset Links)
FRONTEND_URL="http://localhost:5173"
# SMTP Configuration (Optional, for Password Reset)
SMTP_HOST="smtp.gmail.com"
SMTP_PORT=465
SMTP_SECURE=true
SMTP_USER="your-email@gmail.com"
SMTP_PASS="your-app-password"
EMAIL_FROM="NutriChef <noreply@nutrichef.com>"Create a .env file in client/:
VITE_API_URL="http://localhost:5000"From the server/ directory, apply the Prisma schema to your PostgreSQL database:
cd server
npx prisma db pushTo inspect database tables in a visual interface:
npx prisma studio-
Start the backend development server:
cd server npm run devServer will run on
http://localhost:5000. -
Start the frontend development server:
cd client npm run devClient will run on
http://localhost:5173.
The backend test suite is written using the native Node.js test runner (node:test) and covers authentication, session management, access isolation (IDOR protection), meal calculations, and daily logging.
Run all tests:
cd server
npm testExpected result:
# tests 93
# suites 30
# pass 93
# fail 0
# cancelled 0
# skipped 0
Check code styling and ESLint compliance:
cd client
npm run lintVerify production build and chunk distribution:
cd client
npm run build| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
POST |
/api/auth/register |
Register new user account | No |
POST |
/api/auth/login |
Authenticate with credentials | No |
POST |
/api/auth/google |
Authenticate with Google ID token | No |
GET |
/api/auth/me |
Fetch active user profile | Yes (JWT) |
PUT |
/api/auth/profile |
Update profile information | Yes (JWT) |
PUT |
/api/auth/goals |
Update daily nutritional goals | Yes (JWT) |
POST |
/api/auth/avatar |
Upload profile avatar (multipart) | Yes (JWT) |
POST |
/api/auth/forgot-password |
Request password reset token | No |
POST |
/api/auth/reset-password |
Reset password using valid token | No |
DELETE |
/api/auth/account |
Permanently delete user account | Yes (JWT) |
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
POST |
/api/meals |
Create new calculated meal | Yes (JWT) |
GET |
/api/meals |
List and search user's saved meals | Yes (JWT) |
GET |
/api/meals/:id |
Retrieve single meal by ID | Yes (JWT) |
PUT |
/api/meals/:id |
Update meal macros and details | Yes (JWT) |
DELETE |
/api/meals/:id |
Delete meal from library | Yes (JWT) |
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
GET |
/api/dashboard/:date |
Aggregated statistics, logs, and goals | Yes (JWT) |
POST |
/api/logs |
Log meal consumption for specific date | Yes (JWT) |
PUT |
/api/logs/:id |
Update consumed portion or meal type | Yes (JWT) |
DELETE |
/api/logs/:id |
Remove entry from daily diary | Yes (JWT) |
This project is licensed under the ISC License.



