uv run python app.py cd frontend
bun install # first time only
VITE_API_BASE="http://localhost:5000" bun run dev- Build: recommended to run from inside the
frontend/folder:
cd frontend
bun run buildThis emits the production bundle to frontend/dist/ (served automatically by Flask when present).
If you only run uv run python app.py, make sure to rebuild after frontend changes so Flask serves the latest UI:
cd frontend && bun run buildThen reload the browser. The camera modal and capture flow will be available on the “Add” view.
- Full-screen camera modal for preview and capture.
- Visible spinner overlay while parsing the image.
- Manual focus slider appears when supported by the device; otherwise a hint is shown.
- Ingredient order is preserved exactly as parsed (no alphabetic sort).
- Adding a new ingredient/extra row prepends at the top for quick entry.
The backend auto-loads .env at startup and uses these variables:
OPENAI_API_KEY(required)OPENAI_BASE_URL(optional for custom endpoints)RECIPE_IMAGE_MODEL(optional; defaults togpt-5-mini)
Setup
- Copy
./.env.exampleto./.envand fill values:cp .env.example .env
- Start the app:
uv run python app.py
Notes
-
Do not commit keys to source control. Prefer a password manager or OS keychain for storage.
-
Menu Planner parity lives in the React shell: spinner suggestions, search, serving adjustments, menu export, and ingredient rename tooling all run off the existing
/api/*routes. -
Add Recipe lives in the same UI: drag/drop or camera capture, optional AI prompt, YAML preview, and manual form edits before posting to
/api/recipes. -
Edit Recipes is React-native too: search/filter, adjust name/slug/servings/flags, tweak ingredients/extras, and PATCH via
/api/recipes/<slug>. -
Config dashboard (categories, ingredient mappings, staples + label) is now in React with shortcuts into the rename tools.
-
If the frontend dev server runs on another port, keep the Flask API running via
uv run python app.pyand pointVITE_API_BASEto that origin.
podman build -t menu-app .
podman run -p 80:5000 menu-app- Go to GitHub Settings → Developer Settings → Personal Access Tokens
- Choose "Tokens (classic)" or "Fine-grained tokens"
- Generate new token with required permissions:
write:packagesread:packagesdelete:packages(optional)
- Save the token securely (e.g., in 1Password)
- Note the token name shown in GitHub settings (this will be your username for podman login)
- Login to GitHub Container Registry:
# Replace TOKEN_NAME with the name of your token from GitHub settings
# Replace YOUR_PAT with your actual PAT
echo YOUR_PAT | podman login ghcr.io -u TOKEN_NAME --password-stdin- Tag your local image:
podman tag menu-app:latest ghcr.io/julietkiloromeo/menu-app:latest- Push the image:
podman push ghcr.io/julietkiloromeo/menu-app:latest- Login to GHCR:
# Replace TOKEN_NAME and YOUR_PAT as before
echo YOUR_PAT | podman login ghcr.io -u TOKEN_NAME --password-stdin- Pull the image:
podman pull ghcr.io/julietkiloromeo/menu-app:latest- If login fails, verify:
- Token name is correct (from GitHub settings, not your GitHub username)
- PAT hasn't expired
- PAT has correct permissions
- If push fails, ensure:
- Repository exists and is properly configured for packages
- You have appropriate permissions on the repository
- Image is tagged correctly with the ghcr.io prefix
- Never commit your PAT to version control
- Use environment variables or secure secret management (like 1Password) to store PATs
- Consider using fine-grained tokens with minimal necessary permissions
- Regularly rotate your PATs