feat: recipes — web URL import with JSON-LD shortcut + LLM fallback#3
Open
BrainMode wants to merge 1 commit into
Open
feat: recipes — web URL import with JSON-LD shortcut + LLM fallback#3BrainMode wants to merge 1 commit into
BrainMode wants to merge 1 commit into
Conversation
…allback)
First slice of the recipe import pipeline. Web URLs only — YouTube/Instagram/
TikTok/Image follow in subsequent PRs.
Pipeline:
1. detectSource(url) → DetectedSource type
2. For 'web_url': fetch HTML
3. Parse JSON-LD (jsonld.ts) → 80% of recipe blogs covered, no LLM cost
4. If JSON-LD has exactly one Recipe, SHORTCUT: stamp provenance, return
directly (Brzycki-fast, ~2s end-to-end)
5. Else: Firecrawl markdown fallback → LLM-Synthesis with Opus 4.7
6. ExtractionResult with per-field provenance back to client
Files:
- src/lib/integrations/firecrawl/extract.ts — FirecrawlApp wrapper, scrapeUrl
with markdown+html formats
- src/lib/recipes/sources/web.ts — fetch + JSON-LD-first + Firecrawl-fallback
+ paywall/Cloudflare detection
- src/lib/recipes/extraction-strategy.ts — orchestrator (web + manual_text path
fully wired, other source-types return 'unsupported_source' politely)
- src/lib/recipes/synthesis.ts — fs-based prompt loader fix (was throwing stub)
- src/lib/recipes/import.ts — public-API wrapper extractRecipe()
API:
- POST /api/recipes/import — synchronous, returns { result, bundle }
60s maxDuration cap fits Web-URL extraction (JSON-LD <2s, Firecrawl ~10s,
LLM ~10-20s)
Server actions (src/app/(app)/recipes/actions.ts):
- saveRecipe — writes recipes + ingredients (with provenance jsonb) + steps
(with provenance jsonb) + recipe_equipment
- deleteRecipe
UI:
- /recipes — list with tags + cooking time + kcal preview
- /recipes/import — URL/text input, live pipeline log, recipe preview with
per-ingredient provenance badges, save button
- /recipes/[id] — detail with provenance, scaled servings, source link
Verified: typecheck + lint + 90 tests + build all green.
Next PR (Phase 4b): YouTube + Instagram + TikTok via youtube-dl-exec +
ElevenLabs Scribe for audio fallback.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
First slice of the multi-source recipe import pipeline. Web URLs only in this PR — YouTube/Instagram/TikTok/Image follow in subsequent PRs.
Pipeline:
schema.org/Recipe)Verification
npm run typecheck— greennpm run lint— greennpm run test— 90 passingnpm run build— 13 routes, /recipes/import 5.4kBTest plan
jsonldprovenance badgesOut of scope (next PRs)
🤖 Generated with Claude Code