# adriana-recipes — unified recipe dashboard *Unified recipe platform in the monorepo: SQLite + API + admin dashboard. Sources: archived app repos, Drive PRODUTOS, Meta exports. Epic: #622.* ## Current focus - [x] Public `/receitas` site + drop "origem" from admin UI (#681) - [x] Dedupe code + prod GCS cutover (3 exact archived, 14 variants renamed) (#763 / #621) - [x] In-dashboard one-click merge / not-a-duplicate / prefer-source (#621) ## Next up - [ ] livro_comer_sem_culpa nutrition macros — only in Firebase RTDB (rules expired 2021); needs live Firebase or is lost - [ ] adrianacarioba Firestore `receitas` — likely overlaps sendo_magro; import only if it adds recipes - [ ] Optional: migrate the 158 committed sendo JPEGs to GCS too (shed ~30 MB git bloat) — new uploads already go to GCS as of #670 - [ ] adriana-recipes: extractors (PDF/gdoc/text → candidates → recipes) (#618) - [ ] adriana-recipes: load archived app repos (Firebase/JSON dumps) (#619) ## Last touched - 2026-07-13 — Shipped dashboard one-click merge, not-a-duplicate, and prefer-source actions for recipe pairs (#621). - 2026-07-13 — Applied recipe de-dupe to prod GCS and landed the admin duplicates UX (#763). - 2026-07-12 — Added an in-repo runbook for the receitas subdomain domain mappings and DNS covering both the com and com br domains (#729). - 2026-07-12 — Added an "Área restrita" footer link to the CMS and made the public site work on both adrianacarioba.com and .com.br via an apex redirect stub (#707). - 2026-07-12 — Moved the public recipe site to its own subdomain receitas.adrianacarioba.com and fixed the hero and listing edge-margin bug (#702). - 2026-07-12 — Scoped the public /receitas mount to the adrianacarioba host only, so other hosts fall through to 404 (#687). - 2026-07-12 — Shipped the ungated public recipe site at /receitas with auto-derived tempo and difficulty tags, and dropped the origem source pill and filter from the admin UI (#681). - 2026-07-12 — Dashboard photo uploads now persist to GCS and stream back via the app's credentials, surviving redeploys without a public bucket; a data exposure was flagged (#670) - 2026-07-12 — Added an ingredient-line parser that splits quantity, unit, ingredient and notes, backfilled the whole database, and the importer now parses on import (#667) - 2026-07-11 — Editor UX overhaul: dashboard on :3000 dev, add-new comboboxes, structured ingredient rows, photo upload, spelled-out nutrition labels; dropped Importar (#657) ## Blockers - (none) ## Open questions - (resolved #681) The public surface is now the ungated `/receitas` site (published recipes only). The admin-gated Next `/view/[slug]` remains as an internal preview/print surface. ## Ideas - Auto-parse ingredient quantity/unit from the free-text lines (currently stored whole as name_pt) ## Infrastructure - Mount: `/adriana-recipes` (admin-gated, same wall as `/ynab` and `/drilux`); canonical store is monorepo SQLite + API, DB survives deploys via GCS `adrianacarioba/recipes.db`. Not Firebase. - **Public site**: `receitas.adrianacarioba.com` (ungated, served at the subdomain ROOT by the main `lucaslongo-site` via host routing in `server.js` → `isReceitasHost`, refs #702). Note `adrianacarioba.com` itself is a SEPARATE static-only Cloud Run service, so the dynamic app can't live there — hence the subdomain. Plain Express SSR (`server/public-site.mjs` + `server/public-queries.mjs`), NO Next build needed, published recipes only, never exposes `legacy_source`. Reads the same recipes.db as the admin mount (idempotent `initDb()` is shared). Tags (Dificuldade, Tempo) derived at query time from ingredient/step counts + `prep_time_minutes`. Dev hosts: `receitas.localhost:3000`, `receitas.adrianacarioba.localhost:3000`. **Prod needs** a Cloud Run domain mapping + Cloudflare CNAME — full runbook in [`RECEITAS-DNS.md`](RECEITAS-DNS.md) (also docs/domains.md). - **Local dev on :3000**: unlike the plain-Express tools, this is a Next app — build it once (`npm --prefix projects/adriana-recipes run build:mount`), then `npm start` (main site, port 3000, admin pass via KCI_PASSWORD) serves it at `localhost:3000/adriana-recipes`. The mount attaches the built UI whenever `.next` exists; without a build it falls back to an API-only page. - **Data split at deploy**: git ships code + `public/recipe-images/*.jpg`; `data/recipes.db` is gitignored and lives in GCS. Both must be in sync — commit images AND upload the DB, since `image_url` in the DB points at the committed JPEGs. - Importers: `npm run import:sendo` (vendored `data/sources/sendo_magro/receitas.json` + Drive photos), `npm run import:pdfs` (Drive PRODUTOS PDFs → review queue; needs Drive mounted). `SENDO_IMAGE_DIR` / `PRODUTOS_DIR` override the Drive paths.