smooth-app
전 세계 식품의 성분·영양·정보를 자유롭게 협업하고 공개하는 데이터베이스
README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
A recipe nutrition tracker and workout logger for fitness enthusiasts who meal prep. Track macros per portion, plan weekly meals, and log workouts with biomechanical validation.README 전문 보기 ↗A recipe nutrition tracker and workout logger for fitness enthusiasts who meal prep. Track macros per portion, plan weekly meals, and log workouts with biomechanical validation.
Frontend:
Backend:
src/
├── components/
│ ├── layout/ # RootLayout, Nav (desktop top + mobile bottom tabs + RestTimer)
│ └── ui/ # Button, Card, Input, NumberInput, Select, Switch, Spinner, etc.
├── features/
│ ├── recipes/
│ │ ├── components/ # MacroRing, MacroBar, MacroReadout, PortionPanel, RecipeImportDialog,
│ │ │ # PremadeDialog, SubrecipeExpandedRows, IngredientSearchInput, etc.
│ │ ├── hooks/ # useRecipeCalculations
│ │ ├── utils/ # macros.ts, format.ts
│ │ ├── RecipeListPage.tsx
│ │ └── RecipeEditorPage.tsx
│ ├── ingredients/
│ │ ├── components/ # IngredientForm
│ │ └── IngredientListPage.tsx
│ ├── mealPlans/
│ │ ├── components/ # InventorySidebar, WeekGrid, DayColumn, MealCard, DayTotals,
│ │ │ # WeeklyAverages, SlotPickerPopover, etc.
│ │ ├── MealPlanListPage.tsx
│ │ └── MealPlannerPage.tsx
│ ├── workouts/
│ │ ├── components/ # BodyMap, ExerciseSetForm, SetRow, SupersetForm, SessionReview,
│ │ │ # TimerMode, TimerRing, RestTimer, RestAlertsSection, etc.
│ │ ├── hooks/ # Rest-alert delivery controller and session hooks
│ │ ├── store/ # Persisted workout session/timer state
│ │ ├── utils/ # formulas.ts, sets.ts, export.ts
│ │ ├── RestTimerContext.tsx
│ │ ├── WorkoutListPage.tsx
│ │ ├── WorkoutTemplatePage.tsx
│ │ └── WorkoutSessionPage.tsx
│ └── settings/
│ └── SettingsPage.tsx
├── lib/
│ ├── trpc.ts # tRPC client setup
│ ├── user.tsx # useUser() hook (Clerk)
│ └── cn.ts # clsx + tailwind-merge utility
└── index.css # Design tokens (surfaces, ink, macro colors, etc.)
packages/db/ # Shared package @macromaxxing/db
├── schema.ts # All tables, including pushSubscriptions and restNotificationJobs
├── relations.ts # Drizzle relations
├── types.ts # Inferred types
├── custom-types.ts # TypeID helpers, AiProvider, FatigueTier, MuscleGroup, SetMode, etc.
└── preparation.ts # Preparation descriptor extraction
workers/functions/
├── api/[[route]].ts # Hono entry: Clerk auth middleware → tRPC handler
└── lib/
├── router.ts # tRPC app router (recipe, ingredient, settings, ai, dashboard, mealPlan,
│ # user, workout, analytics, restNotifications)
├── trpc.ts # tRPC context + procedures
├── auth.ts # Clerk cookie verification
├── db.ts # Drizzle D1 setup
├── ai-utils.ts # Multi-provider AI client, model fallback, JSON-LD extraction
├── crypto.ts # AES-GCM encryption helpers
├── constants.ts # Shared constants + Zod schemas
├── utils.ts # toStartCase, extractPreparation, etc.
└── routes/
├── recipes.ts # CRUD + ingredients + subrecipes + premade meals
├── ingredients.ts # CRUD + findOrCreate + batchFindOrCreate + units
├── mealPlans.ts # CRUD + inventory + slot allocation
├── workouts.ts # Exercises, templates, sessions, sets, muscle stats, import
├── ai.ts # lookup, estimateCookedWeight, parseRecipe, parseProduct
├── settings.ts # AI config + body profile
├── restNotifications.ts # Push subscription, scheduling, cancellation, and test notification API
└── user.ts # User endpoints
workers/rest-notifications/ # Queue consumer that claims due jobs and sends Web Push
scripts/
└── seed-exercises.ts # System exercises with muscle group mappings + strength standards
Nutrition lookup priority: USDA FoodData Central API → AI (user's configured provider)
| Provider | Default Model | Fallback Chain |
|---|---|---|
| Gemini | gemini-2.5-flash | → gemini-2.5-flash-lite-preview → gemma-3-27b-it |
| OpenAI | gpt-4o-mini | — |
| Anthropic | claude-sonnet-4-20250514 | — |
Capabilities:
Per-user settings (both off by default):
batchLookups — batch N ingredient AI calls into 1modelFallback — retry with cheaper models on 429Dark theme with warm soapstone undertones. Key tokens in src/index.css:
surface-0 (base), surface-1 (cards), surface-2 (hover/elevated)ink (primary text), ink-muted (secondary), ink-faint (tertiary)macro-protein (copper), macro-carbs (golden), macro-fat (olive), macro-kcal (warm orange), macro-fiber (sage)oklch(0.72 0.15 50))edge border color4px/6px) for instrument-grade precision# Install dependencies
yarn
# Run dev server (frontend + backend)
yarn dev
# Build
yarn build
# Lint/format
yarn fix
# Database migrations
yarn db:generate # Generate migration from schema changes
yarn db:migrate # Apply migrations to local D1
# Run tests
yarn test
Frontend (.env.local):
VITE_CLERK_PUBLISHABLE_KEY — Clerk publishable keyWorkers (.dev.vars locally, Cloudflare dashboard for production):
ENCRYPTION_SECRET — 32-byte hex string for AES-GCM key encryptionUSDA_API_KEY — USDA FoodData Central API keyCLERK_PUBLISHABLE_KEY — Clerk publishable keyCLERK_SECRET_KEY — Clerk secret keyVAPID_PUBLIC_KEY — URL-safe public key used for browser push subscriptionsVAPID_PRIVATE_KEY — matching private key used only by server-side deliveryREST_ALERTS_ENABLED — runtime feature gate; production enables it while Pages previews set it to false in workers/wrangler.tomlRest alerts use the macromaxxing-rest-notifications Cloudflare Queue. Production needs the same VAPID key pair in the Pages project and the dedicated macromaxxing-rest-notifications Worker. The deploy workflow creates the queue, deploys its consumer before Pages, and configures both runtimes from the VAPID_PUBLIC_KEY and VAPID_PRIVATE_KEY GitHub Actions secrets. Never add either key to wrangler.toml.
MIT