Skip to content

jesshas/shef

Repository files navigation

Shef 🌿

AI-powered weekly meal planning that feels like a beautiful recipe journal β€” not a clinical SaaS dashboard.

Plan your week, get a smart consolidated grocery list, and see your nutrition at a glance. No sign-up required to start.


Features

  • No sign-up wall β€” start planning immediately as a guest; results are fully usable without an account
  • AI generation β€” one click produces a full week of meals, a nutrition breakdown, and a consolidated grocery list (via Claude or GPT-4o)
  • Duplicate meals & quick-add β€” copy any meal to another slot; add Leftovers in one hover click
  • Guest β†’ account import β€” sign up after planning and your week is automatically saved
  • Dietary preferences β€” set vegetarian, vegan, gluten-free, dairy-free, low-carb, or high-protein; passed to the AI on every generation
  • Saved recipes β€” bookmark meals with tag filtering (4 free, Pro unlimited)
  • Subscriptions β€” embedded Stripe checkout (no redirect); monthly ($4.99) and annual ($49) Pro plans
  • Mobile-friendly β€” responsive grid; iOS & Android install-to-home-screen prompt

Tech stack

Layer Choice
Framework Next.js 16 (App Router, Server Actions, Turbopack)
Styling Tailwind CSS v4 with custom design tokens
Auth Clerk (optional β€” only required to persist data)
Database Neon (PostgreSQL) + Drizzle ORM
AI Anthropic Claude (claude-sonnet-4-6) or OpenAI (gpt-4o)
Payments Stripe (embedded Elements β€” no hosted redirect)
Toasts Sonner
Icons Lucide React
Validation Zod

Getting started

Prerequisites

  • Node.js 20.9+ (recommend 22 via nvm use 22)
  • A Neon database
  • An Anthropic or OpenAI API key
  • A Clerk app (or use keyless dev mode β€” Clerk starts automatically without keys in local dev)
  • A Stripe account (test mode is fine for local dev)

1. Clone & install

git clone https://github.com/jesshas/shef.git
cd shef
npm install

2. Environment variables

cp .env.local.example .env.local

Edit .env.local:

Variable Required Description
DATABASE_URL Yes Neon connection string (postgres://...)
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY No* Clerk publishable key
CLERK_SECRET_KEY No* Clerk secret key
CLERK_WEBHOOK_SECRET No* Clerk webhook signing secret
AI_PROVIDER No anthropic (default) or openai
ANTHROPIC_API_KEY No** Required if AI_PROVIDER=anthropic
OPENAI_API_KEY No** Required if AI_PROVIDER=openai
OPENAI_MODEL No Override OpenAI model (default: gpt-4o)
ANTHROPIC_MODEL No Override Claude model (default: claude-sonnet-4-6)
NEXT_PUBLIC_APP_URL Yes Full origin URL e.g. http://localhost:3000
STRIPE_SECRET_KEY Yes*** Stripe secret key (sk_test_... or sk_live_...)
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY Yes*** Stripe publishable key (pk_test_...)
STRIPE_WEBHOOK_SECRET Yes*** Stripe webhook signing secret (whsec_...)
STRIPE_MONTHLY_PRICE_ID Yes*** Stripe Price ID for the $4.99/month plan
STRIPE_ANNUAL_PRICE_ID Yes*** Stripe Price ID for the $49/year plan

* Clerk runs in keyless dev mode locally if omitted β€” auth is fully functional without API keys in development.
** AI generation returns a friendly error toast if no key is configured.
*** Required for subscriptions to work. Payments are disabled if omitted.

3. Push database schema

npx drizzle-kit push

4. Run

nvm use 22    # ensure Node 20.9+
npm run dev

Open http://localhost:3000.


AI provider

Switch between Anthropic and OpenAI with one env var:

# Default β€” Anthropic Claude
AI_PROVIDER=anthropic
ANTHROPIC_API_KEY=sk-ant-...

# OpenAI
AI_PROVIDER=openai
OPENAI_API_KEY=sk-...
OPENAI_MODEL=gpt-4o-mini   # optional, defaults to gpt-4o

Both providers run nutrition and grocery list generation in parallel for speed.


Database commands

npx drizzle-kit push       # Push schema directly (dev)
npx drizzle-kit generate   # Generate migration files
npx drizzle-kit migrate    # Run pending migrations
npx drizzle-kit studio     # Open Drizzle Studio UI

Routes

Route Access Description
/ Public Landing page
/plan/new Public Weekly meal planner (guests welcome)
/plan/[weekId] Auth Saved week view
/dashboard Auth User home β€” stats and past weeks
/recipes Auth Saved recipe bookmarks
/settings Auth Account profile + dietary preferences + billing
/pricing Public Plan comparison β€” Free vs Pro
/upgrade Auth Embedded Stripe checkout (?plan=monthly or ?plan=annual)

Clerk webhook (production)

In your Clerk dashboard, create a webhook pointing to:

https://your-domain.com/api/webhooks/clerk

Subscribe to: user.created, user.updated, user.deleted

Copy the signing secret into CLERK_WEBHOOK_SECRET in your production environment.


Stripe setup

1. Create products & prices

In the Stripe Dashboard, create one product called "Shef Pro" with two recurring prices:

Price Amount Interval
Monthly $4.99 Monthly
Annual $49.00 Yearly

Copy each Price ID (price_...) into STRIPE_MONTHLY_PRICE_ID and STRIPE_ANNUAL_PRICE_ID.

2. Configure the webhook

In production, add a webhook endpoint in your Stripe dashboard pointing to:

https://your-domain.com/api/webhooks/stripe

Subscribe to:

  • invoice.paid β€” grants Pro access after successful payment
  • customer.subscription.deleted β€” revokes Pro access on cancellation
  • invoice.payment_failed β€” logged for observability; Stripe retries automatically

Copy the signing secret into STRIPE_WEBHOOK_SECRET.

3. Testing locally

Install the Stripe CLI and forward events to your local server:

stripe listen --forward-to localhost:3000/api/webhooks/stripe

The CLI prints a webhook signing secret β€” use that as STRIPE_WEBHOOK_SECRET in .env.local while developing.

Use Stripe's test card 4242 4242 4242 4242 (any future expiry, any CVC) to complete a test payment.

4. Billing portal

Enable the Customer Portal in your Stripe dashboard so users can manage and cancel their subscriptions from the Settings page.


Project structure

app/
  page.tsx                     # Landing page
  plan/new/page.tsx            # Planner (guests + signed-in)
  plan/[weekId]/page.tsx       # Saved week view
  (auth)/dashboard/            # Dashboard
  (auth)/recipes/              # Saved recipes
  (auth)/settings/             # Settings + billing
  pricing/page.tsx             # Pricing page
  upgrade/page.tsx             # Embedded Stripe checkout
  api/webhooks/clerk/route.ts  # Clerk β†’ Neon user sync
  api/webhooks/stripe/route.ts # Stripe β†’ plan upgrade/downgrade
  api/stripe/create-subscription/route.ts  # Creates subscription + returns clientSecret

components/
  ui/                          # Button, Card, SlideOver, Badge, Input, Accordion
  meal-grid/                   # WeekGrid, MealCell, MealSlideOver
  results/                     # NutritionSummary, GroceryList, DayByDayBreakdown
  recipes/                     # RecipeCard, SaveRecipePanel, UpgradePrompt
  layout/                      # Navbar, Footer, MobileInstallBanner

lib/
  db/                          # Drizzle schema + Neon client
  ai/                          # AI generation (Anthropic + OpenAI)
  actions/                     # Server actions (billing portal)
  stripe/                      # Stripe client singleton
  guest/                       # localStorage helpers
  utils/                       # Macros, week helpers, limit checks
  validations/                 # Zod schemas

hooks/
  useWeekPlan.ts               # Meal state (guest + signed-in)
  useMealSlideOver.ts          # Slide-over open/close
  useGuestPlan.ts              # Auto-import guest plan on sign-in

Deployment

Vercel (recommended)

vercel deploy

Set all environment variables in Vercel β†’ Project Settings β†’ Environment Variables.

Make sure DATABASE_URL ends with ?sslmode=require for Neon.


Security notes

  • .env.local and .clerk/ are gitignored and will never be committed
  • No API keys or secrets are hardcoded anywhere in the source
  • See .env.local.example for a full list of required variables with placeholder values only

License

MIT

About

plan your meals & grocery runs

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages