RecipeMemoir Import Copyright Fix
Enter hub password to continue.
That's not it. Try again.
Imported photos now stay yours until you replace them
Audited, refined, deployed, and verified on production · July 20, 2026 · Beta v0.9.3
Kill-assumption #2 from the plan red-team was right: URL and video imports copied a source photo to our storage and displayed it on a public user site with no hold. That's real copyright exposure. Photos are fully protected under US law, even though ingredient lists aren't. The fix now holds the photo, not the recipe.
What the audit found
- The exposure was real. The importer downloaded the source blog's photo, stored it with the recipe, and displayed it publicly with no hold. Video imports did the same with the video's thumbnail.
- Search engines received it too. The public recipe's JSON-LD included the copied image URL, so the source hotlink could travel beyond the styled page.
What changed (live now)
Beta v0.9.3 shipped this as D1 migration 034 and the new recipes.photo_third_party flag.
- Public visitors can read the full recipe. Title, ingredients, directions, and times remain visible. Only the imported photo is withheld. In its place, an on-brand card says, "Remind this cook to add one of her own photos here, or she can generate one with AI." The JSON-LD image is omitted too, so search engines never receive the source hotlink.
- Family can unlock the original photos. The owner can turn on a photo password at
/site/family.html. It's off by default, with the same opt-in shape as newsletter settings. Family members click "Unlock the photos," enter the password, and see the originals. - The owner always sees the originals. A logged-in owner or someone with the editor key also gets a "photos to replace" queue and a soft counter on the Family photos page: "N recipes are showing placeholder cards to visitors." Replacing a photo with an upload or an AI-generated image clears the hold instantly.
- The cache stays safe.
/api/photo/{id}.jpgedge-caches for a year and never varies by viewer. Thecollection.jsandrecipe.jspayloads decide whether to show the placeholder or real photo, and real URLs carry a?k=collection photo key. - The existing 1,743 recipes kept their photos. Their
photo_third_partyvalue remains 0. The hold applies to new imports going forward.
Proof it works
- All 349 automated tests pass, and the full three-audience flow was verified locally.
- On production, one recipe was flipped to held. The public got the placeholder and no JSON-LD image, the family password returned a key that fetched the real JPG, and neighboring recipes were unaffected. The test recipe was then restored to clean. /api/site/recipe/1 answers 200.
- ValidateSite was GREEN across two runs. A screenshot of the placeholder on the live styled recipe page also confirmed the card looks on-brand.
Why this is good for the business, not just the lawyers
RecipeMemoir now structurally refuses to republish a creator's photo to public visitors. The placeholder does useful work too: it asks family visitors to nudge the owner to add one of her own photos. Meanwhile, the recipe stays fully readable, which is better for the owner's site than hiding the whole thing.
Still open
- Build the rewrite pipeline for the directions text. This is a separate concern being built in a parallel session. Directions are the one copyrightable part of the recipe text. This fix was about photos.
- Decide on the back catalog. Recipes imported before today still carry source photos and are public. They're your own collection and the site predates the beta, so nothing was changed without asking; worth a deliberate pass once the AI photo generator can batch.