diff --git a/apps/mobile/src/app/recipe/[id].tsx b/apps/mobile/src/app/recipe/[id].tsx
index 654be7b..5ec7be7 100644
--- a/apps/mobile/src/app/recipe/[id].tsx
+++ b/apps/mobile/src/app/recipe/[id].tsx
@@ -205,7 +205,13 @@ export default function RecipeScreen() {
)}
{recipe.description ?? recipe.descriptionSv}
- {recipe.creatorDisplayName && Skapat av {recipe.creatorDisplayName}}
+ {recipe.creatorDisplayName && (
+
+ {recipe.creatorDisplayName.includes("Redaktion")
+ ? `Skapat av ${recipe.creatorDisplayName}`
+ : `Källa: ${recipe.creatorDisplayName}`}
+
+ )}
{!recipe.safety.safe && (
diff --git a/packages/database/src/seed/data/chef-recipes.ts b/packages/database/src/seed/data/chef-recipes.ts
new file mode 100644
index 0000000..a9e5455
--- /dev/null
+++ b/packages/database/src/seed/data/chef-recipes.ts
@@ -0,0 +1,407 @@
+import type { SeedRecipe } from "./recipes.js";
+
+/**
+ * Namngivna kock-recept (spec: named-chef attribution). EGNA formuleringar
+ * (sourceType own_editorial) av kockarnas kända signaturrätter – rätter kan inte
+ * upphovsrättsskyddas, bara den exakta texten, så texten här är nyskriven.
+ * Krediteras diskret via creatorDisplayName ("Källa: "), aldrig badge/flik.
+ * De ligger bland alla andra recept och lyder samma diet-/allergifilter.
+ *
+ * HÅRDA REGLER (annars kraschar seed): ids finns i katalogen; (ing, unit)
+ * beräkningsbar (GRAM/KILOGRAM alltid; volym kräver density; COUNT gramsPerPiece).
+ */
+export const CHEF_RECIPES: SeedRecipe[] = [
+ {
+ slug: "gordon-kramig-aggrora",
+ titleSv: "Krämig äggröra",
+ descriptionSv:
+ "Långsamt rörd, silkeslen äggröra som lyfts av en klick crème fraiche på slutet – Gordon Ramsays kända sätt att göra frukostägg lyxiga.",
+ cuisine: "international",
+ mealTypes: ["breakfast"],
+ tags: ["vegetarian", "high_protein", "quick"],
+ methods: ["stovetop"],
+ equipment: ["stove"],
+ difficulty: "easy",
+ prepMin: 3,
+ cookMin: 7,
+ portions: 2,
+ spiceLevel: 0,
+ mealPrepFriendly: false,
+ freezerFriendly: false,
+ peakSeasons: [],
+ holidayTags: [],
+ verificationStatus: "editorial",
+ creatorDisplayName: "Gordon Ramsay",
+ dnaProtein: "egg",
+ dnaVegetables: [],
+ dnaFlavor: ["creamy", "buttery", "savory"],
+ ingredients: [
+ { ing: "egg", nameSv: "Ägg", qty: 6, unit: "COUNT", optional: false },
+ { ing: "butter", nameSv: "Smör", qty: 30, unit: "GRAM", optional: false },
+ { ing: "creme_fraiche", nameSv: "Crème fraiche", qty: 1, unit: "DECILITER", optional: false },
+ { ing: "salt", nameSv: "Salt", qty: 1, unit: "TEASPOON", optional: false },
+ ],
+ steps: [
+ { text: "Vispa upp äggen lätt. Lägg smöret och äggen kalla i en kastrull." },
+ {
+ text: "Värm på medelvärme och rör hela tiden. Lyft av från plattan med jämna mellanrum så äggen inte blir torra – de ska bli krämiga, inte fasta.",
+ },
+ { text: "Ta av från värmen medan de fortfarande är lite lösa, rör ner crème fraiche och salta. Servera direkt." },
+ ],
+ },
+ {
+ slug: "jamie-jordnotskyckling",
+ titleSv: "Jordnötskyckling med ris",
+ descriptionSv:
+ "Snabb wokad kyckling i en fyllig jordnötssås med soja och lime, serverad på ris – i andan av Jamie Olivers snabba vardagsrätter.",
+ cuisine: "international",
+ mealTypes: ["dinner"],
+ tags: ["high_protein", "quick"],
+ methods: ["stovetop"],
+ equipment: ["stove"],
+ difficulty: "easy",
+ prepMin: 10,
+ cookMin: 20,
+ portions: 4,
+ spiceLevel: 1,
+ mealPrepFriendly: true,
+ freezerFriendly: false,
+ peakSeasons: [],
+ holidayTags: [],
+ verificationStatus: "editorial",
+ creatorDisplayName: "Jamie Oliver",
+ dnaProtein: "chicken_thigh",
+ dnaCarb: "rice_white",
+ dnaVegetables: [],
+ dnaFlavor: ["nutty", "umami", "tangy"],
+ ingredients: [
+ { ing: "chicken_thigh", nameSv: "Kycklinglårfilé", qty: 500, unit: "GRAM", optional: false },
+ { ing: "peanut_butter", nameSv: "Jordnötssmör", qty: 80, unit: "GRAM", optional: false },
+ { ing: "soy_sauce", nameSv: "Soja", qty: 2, unit: "TABLESPOON", optional: false },
+ { ing: "garlic", nameSv: "Vitlöksklyfta", qty: 2, unit: "COUNT", optional: false },
+ { ing: "lime", nameSv: "Lime", qty: 40, unit: "GRAM", optional: false },
+ { ing: "rice_white", nameSv: "Ris", qty: 300, unit: "GRAM", optional: false },
+ ],
+ steps: [
+ { text: "Koka riset. Skär kycklingen i bitar och stek den gyllene i en het panna." },
+ {
+ text: "Rör ihop jordnötssmör, soja, pressad vitlök och limejuice med en skvätt vatten till en slät sås.",
+ },
+ { text: "Häll såsen över kycklingen, låt puttra ett par minuter tills den tjocknar. Servera på riset." },
+ ],
+ },
+ {
+ slug: "nigella-kladdig-chokladkaka",
+ titleSv: "Kladdig chokladkaka utan mjöl",
+ descriptionSv:
+ "Intensiv, seg chokladkaka helt utan mjöl – ren choklad, smör, ägg och socker. Indulgent på Nigella Lawsons vis, och naturligt glutenfri.",
+ cuisine: "international",
+ mealTypes: ["dessert"],
+ tags: ["vegetarian", "gluten_free", "baking", "cake"],
+ methods: ["oven"],
+ equipment: ["oven"],
+ difficulty: "medium",
+ prepMin: 15,
+ cookMin: 30,
+ portions: 8,
+ spiceLevel: 0,
+ mealPrepFriendly: false,
+ freezerFriendly: true,
+ peakSeasons: [],
+ holidayTags: ["fika"],
+ verificationStatus: "editorial",
+ creatorDisplayName: "Nigella Lawson",
+ dnaVegetables: [],
+ dnaFlavor: ["chocolate", "sweet", "rich"],
+ ingredients: [
+ { ing: "dark_chocolate", nameSv: "Mörk choklad", qty: 200, unit: "GRAM", optional: false },
+ { ing: "butter", nameSv: "Smör", qty: 150, unit: "GRAM", optional: false },
+ { ing: "egg", nameSv: "Ägg", qty: 4, unit: "COUNT", optional: false },
+ { ing: "sugar", nameSv: "Strösocker", qty: 150, unit: "GRAM", optional: false },
+ ],
+ steps: [
+ { text: "Smält choklad och smör försiktigt tillsammans och låt svalna något." },
+ { text: "Vispa ägg och socker pösigt och vänd ner chokladsmeten." },
+ {
+ text: "Häll i en smord form och grädda i mitten av ugnen tills ytan stelnat men mitten fortfarande är kladdig, cirka 25–30 minuter.",
+ temperatureC: 170,
+ },
+ ],
+ },
+ {
+ slug: "ottolenghi-hummus",
+ titleSv: "Krämig hummus",
+ descriptionSv:
+ "Len, citronfrisk hummus på kikärter med vitlök och olivolja – Yotam Ottolenghis signatur, perfekt som röra eller på mezebordet.",
+ cuisine: "middle_eastern",
+ mealTypes: ["starter", "snack", "buffet"],
+ tags: ["vegan", "vegetarian", "gluten_free"],
+ methods: ["no_cook"],
+ equipment: ["blender"],
+ difficulty: "beginner",
+ prepMin: 10,
+ cookMin: 0,
+ portions: 6,
+ spiceLevel: 0,
+ mealPrepFriendly: true,
+ freezerFriendly: false,
+ peakSeasons: [],
+ holidayTags: [],
+ verificationStatus: "editorial",
+ creatorDisplayName: "Yotam Ottolenghi",
+ dnaVegetables: [],
+ dnaFlavor: ["garlic", "citrus", "nutty"],
+ ingredients: [
+ { ing: "chickpeas_canned", nameSv: "Kikärter", qty: 400, unit: "GRAM", optional: false },
+ { ing: "garlic", nameSv: "Vitlöksklyfta", qty: 1, unit: "COUNT", optional: false },
+ { ing: "lemon", nameSv: "Citron", qty: 1, unit: "COUNT", optional: false },
+ { ing: "olive_oil", nameSv: "Olivolja", qty: 3, unit: "TABLESPOON", optional: false },
+ { ing: "salt", nameSv: "Salt", qty: 1, unit: "TEASPOON", optional: false },
+ ],
+ steps: [
+ { text: "Skölj och låt kikärterna rinna av. Spara några hela till garnering." },
+ {
+ text: "Mixa kikärter, pressad vitlök, citronsaft, olivolja och salt slätt med en skvätt vatten tills krämigt.",
+ },
+ { text: "Lägg upp, ringla över lite olivolja och toppa med de sparade kikärterna." },
+ ],
+ },
+ {
+ slug: "marcus-glaserad-lax",
+ titleSv: "Soja- och honungsglaserad lax",
+ descriptionSv:
+ "Ugnsbakad lax med en blank glasyr av soja, honung och vitlök, serverad på ris – smakrikt och elegant i Marcus Samuelssons anda.",
+ cuisine: "nordic",
+ mealTypes: ["dinner"],
+ tags: ["high_protein", "gluten_free"],
+ methods: ["oven"],
+ equipment: ["oven"],
+ difficulty: "easy",
+ prepMin: 10,
+ cookMin: 20,
+ portions: 4,
+ spiceLevel: 0,
+ mealPrepFriendly: false,
+ freezerFriendly: false,
+ peakSeasons: [],
+ holidayTags: [],
+ verificationStatus: "editorial",
+ creatorDisplayName: "Marcus Samuelsson",
+ dnaProtein: "salmon",
+ dnaCarb: "rice_white",
+ dnaVegetables: [],
+ dnaFlavor: ["umami", "sweet", "garlic"],
+ ingredients: [
+ { ing: "salmon", nameSv: "Laxfilé", qty: 500, unit: "GRAM", optional: false },
+ { ing: "soy_sauce", nameSv: "Soja", qty: 2, unit: "TABLESPOON", optional: false },
+ { ing: "honey", nameSv: "Honung", qty: 40, unit: "GRAM", optional: false },
+ { ing: "garlic", nameSv: "Vitlöksklyfta", qty: 2, unit: "COUNT", optional: false },
+ { ing: "rice_white", nameSv: "Ris", qty: 300, unit: "GRAM", optional: false },
+ ],
+ steps: [
+ { text: "Koka riset. Rör ihop soja, honung och pressad vitlök till en glasyr." },
+ { text: "Lägg laxen i en ugnsform och pensla på glasyren." },
+ {
+ text: "Baka mitt i ugnen tills laxen är precis genomgången, cirka 15 minuter. Pensla med skyn en gång till och servera på riset.",
+ temperatureC: 200,
+ },
+ ],
+ },
+ {
+ slug: "giada-zucchinipasta-parmesan",
+ titleSv: "Zucchinipasta med parmesan",
+ descriptionSv:
+ "Enkel pasta med mjukstekt zucchini, vitlök och rikligt med riven parmesan – lätt och italiensk i Giada De Laurentiis stil.",
+ cuisine: "italian",
+ mealTypes: ["dinner", "lunch"],
+ tags: ["vegetarian"],
+ methods: ["stovetop"],
+ equipment: ["stove"],
+ difficulty: "easy",
+ prepMin: 10,
+ cookMin: 20,
+ portions: 4,
+ spiceLevel: 0,
+ mealPrepFriendly: true,
+ freezerFriendly: false,
+ peakSeasons: ["summer"],
+ holidayTags: [],
+ verificationStatus: "editorial",
+ creatorDisplayName: "Giada De Laurentiis",
+ dnaCarb: "pasta_dry",
+ dnaVegetables: ["zucchini"],
+ dnaFlavor: ["savory", "garlic", "salty"],
+ ingredients: [
+ { ing: "pasta_dry", nameSv: "Pasta", qty: 350, unit: "GRAM", optional: false },
+ { ing: "zucchini", nameSv: "Zucchini", qty: 2, unit: "COUNT", optional: false },
+ { ing: "cheese_hard", nameSv: "Parmesan", qty: 80, unit: "GRAM", optional: false },
+ { ing: "olive_oil", nameSv: "Olivolja", qty: 2, unit: "TABLESPOON", optional: false },
+ { ing: "garlic", nameSv: "Vitlöksklyfta", qty: 2, unit: "COUNT", optional: false },
+ ],
+ steps: [
+ { text: "Koka pastan. Tärna zucchinin och skiva vitlöken." },
+ { text: "Fräs zucchini och vitlök mjuka i olivoljan." },
+ { text: "Vänd ner den avrunna pastan med lite pastavatten och den rivna parmesanen tills krämigt. Servera direkt." },
+ ],
+ },
+ {
+ slug: "emeril-rakgryta-creole",
+ titleSv: "Räkgryta Creole",
+ descriptionSv:
+ "Kryddig tomatgryta med räkor, paprika och lök på ris – en klassisk Louisiana-creole i Emeril Lagasses smakrika stil.",
+ cuisine: "american",
+ mealTypes: ["dinner"],
+ tags: ["high_protein"],
+ methods: ["stovetop"],
+ equipment: ["stove"],
+ difficulty: "medium",
+ prepMin: 15,
+ cookMin: 30,
+ portions: 4,
+ spiceLevel: 2,
+ mealPrepFriendly: true,
+ freezerFriendly: true,
+ peakSeasons: [],
+ holidayTags: [],
+ verificationStatus: "editorial",
+ creatorDisplayName: "Emeril Lagasse",
+ dnaProtein: "shrimp",
+ dnaCarb: "rice_white",
+ dnaVegetables: ["bell_pepper", "onion"],
+ dnaFlavor: ["spicy", "savory", "tomato"],
+ ingredients: [
+ { ing: "shrimp", nameSv: "Räkor", qty: 400, unit: "GRAM", optional: false },
+ { ing: "canned_tomatoes", nameSv: "Krossade tomater", qty: 400, unit: "GRAM", optional: false },
+ { ing: "bell_pepper", nameSv: "Paprika", qty: 1, unit: "COUNT", optional: false },
+ { ing: "onion", nameSv: "Gul lök", qty: 1, unit: "COUNT", optional: false },
+ { ing: "garlic", nameSv: "Vitlöksklyfta", qty: 2, unit: "COUNT", optional: false },
+ { ing: "rice_white", nameSv: "Ris", qty: 300, unit: "GRAM", optional: false },
+ ],
+ steps: [
+ { text: "Koka riset. Fräs hackad lök, paprika och vitlök mjuka." },
+ { text: "Häll i de krossade tomaterna och låt sjuda tills såsen tjocknar, cirka 15 minuter. Krydda gärna starkt." },
+ { text: "Vänd ner räkorna och låt dem bli varma ett par minuter. Servera över riset." },
+ ],
+ },
+ {
+ slug: "ina-citron-timjankyckling",
+ titleSv: "Citron- och timjankyckling",
+ descriptionSv:
+ "Saftig ugnsrostad kyckling med citron, vitlök och timjan – enkel, elegant vardagslyx i Ina Gartens Barefoot Contessa-anda.",
+ cuisine: "american",
+ mealTypes: ["dinner"],
+ tags: ["high_protein", "gluten_free"],
+ methods: ["oven"],
+ equipment: ["oven"],
+ difficulty: "easy",
+ prepMin: 10,
+ cookMin: 35,
+ portions: 4,
+ spiceLevel: 0,
+ mealPrepFriendly: true,
+ freezerFriendly: false,
+ peakSeasons: [],
+ holidayTags: [],
+ verificationStatus: "editorial",
+ creatorDisplayName: "Ina Garten",
+ dnaProtein: "chicken_thigh",
+ dnaVegetables: [],
+ dnaFlavor: ["citrus", "herby", "garlic"],
+ ingredients: [
+ { ing: "chicken_thigh", nameSv: "Kycklinglårfilé", qty: 600, unit: "GRAM", optional: false },
+ { ing: "lemon", nameSv: "Citron", qty: 1, unit: "COUNT", optional: false },
+ { ing: "thyme_dried", nameSv: "Timjan", qty: 4, unit: "GRAM", optional: false },
+ { ing: "garlic", nameSv: "Vitlöksklyfta", qty: 3, unit: "COUNT", optional: false },
+ { ing: "olive_oil", nameSv: "Olivolja", qty: 2, unit: "TABLESPOON", optional: false },
+ ],
+ steps: [
+ { text: "Blanda olivolja, pressad vitlök, timjan och saften av citronen. Vänd kycklingen i marinaden." },
+ { text: "Lägg kycklingen i en ugnsform med de urpressade citronhalvorna." },
+ {
+ text: "Rosta mitt i ugnen tills kycklingen är genomstekt och gyllene, cirka 30–35 minuter.",
+ temperatureC: 200,
+ },
+ ],
+ },
+ {
+ slug: "raymond-tradgardsomelett",
+ titleSv: "Trädgårdsomelett",
+ descriptionSv:
+ "Fluffig fransk omelett med svamp, spenat och lite ost – enkel och förfinad i Raymond Blancs stil, klar på några minuter.",
+ cuisine: "french",
+ mealTypes: ["breakfast", "lunch"],
+ tags: ["vegetarian", "gluten_free", "high_protein", "quick"],
+ methods: ["stovetop"],
+ equipment: ["stove"],
+ difficulty: "easy",
+ prepMin: 8,
+ cookMin: 7,
+ portions: 2,
+ spiceLevel: 0,
+ mealPrepFriendly: false,
+ freezerFriendly: false,
+ peakSeasons: [],
+ holidayTags: [],
+ verificationStatus: "editorial",
+ creatorDisplayName: "Raymond Blanc",
+ dnaProtein: "egg",
+ dnaVegetables: ["mushroom", "spinach"],
+ dnaFlavor: ["savory", "buttery", "fresh"],
+ ingredients: [
+ { ing: "egg", nameSv: "Ägg", qty: 4, unit: "COUNT", optional: false },
+ { ing: "butter", nameSv: "Smör", qty: 20, unit: "GRAM", optional: false },
+ { ing: "mushroom", nameSv: "Champinjoner", qty: 100, unit: "GRAM", optional: false },
+ { ing: "spinach", nameSv: "Spenat", qty: 60, unit: "GRAM", optional: false },
+ { ing: "cheese_hard", nameSv: "Riven ost", qty: 40, unit: "GRAM", optional: false },
+ ],
+ steps: [
+ { text: "Fräs skivad svamp mjuk i lite av smöret, vänd ner spenaten tills den faller ihop. Ta upp." },
+ { text: "Vispa äggen lätt. Smält resten av smöret i pannan och häll i äggen, dra in kanterna tills nästan stelt." },
+ { text: "Lägg svamp, spenat och ost på ena halvan, vik ihop omeletten och låt osten smälta. Servera direkt." },
+ ],
+ },
+ {
+ slug: "rick-fiskgratang",
+ titleSv: "Krämig fiskgratäng",
+ descriptionSv:
+ "Torsk i len gräddsås under ett lock av krämig potatismos och gratinerad ost – en brittisk fish pie-klassiker i Rick Steins anda.",
+ cuisine: "international",
+ mealTypes: ["dinner"],
+ tags: ["high_protein"],
+ methods: ["oven"],
+ equipment: ["oven"],
+ difficulty: "medium",
+ prepMin: 25,
+ cookMin: 30,
+ portions: 4,
+ spiceLevel: 0,
+ mealPrepFriendly: true,
+ freezerFriendly: true,
+ peakSeasons: [],
+ holidayTags: [],
+ verificationStatus: "editorial",
+ creatorDisplayName: "Rick Stein",
+ dnaProtein: "cod",
+ dnaCarb: "potato",
+ dnaVegetables: [],
+ dnaFlavor: ["creamy", "savory", "buttery"],
+ ingredients: [
+ { ing: "cod", nameSv: "Torskfilé", qty: 500, unit: "GRAM", optional: false },
+ { ing: "potato", nameSv: "Potatis", qty: 5, unit: "COUNT", optional: false },
+ { ing: "milk_3", nameSv: "Mjölk", qty: 3, unit: "DECILITER", optional: false },
+ { ing: "cream", nameSv: "Grädde", qty: 2, unit: "DECILITER", optional: false },
+ { ing: "butter", nameSv: "Smör", qty: 40, unit: "GRAM", optional: false },
+ { ing: "cheese_hard", nameSv: "Riven ost", qty: 80, unit: "GRAM", optional: false },
+ ],
+ steps: [
+ { text: "Koka potatisen mjuk och mosa den med smör och lite av mjölken till ett krämigt mos." },
+ {
+ text: "Lägg torsken i en smord ugnsform, häll över grädden blandad med resten av mjölken och salta.",
+ },
+ {
+ text: "Bred moset över fisken, strö på riven ost och gratinera i ugnen tills gyllene och bubblande, cirka 25 minuter.",
+ temperatureC: 200,
+ },
+ ],
+ },
+];
diff --git a/packages/database/src/seed/data/recipes.ts b/packages/database/src/seed/data/recipes.ts
index 28db1ff..bd4248e 100644
--- a/packages/database/src/seed/data/recipes.ts
+++ b/packages/database/src/seed/data/recipes.ts
@@ -63,12 +63,20 @@ export interface SeedRecipe {
dnaVegetables: string[];
dnaFlavor: string[];
verificationStatus?: "editorial" | "verified" | "unverified" | "community" | "rejected";
+ /** Namngiven källa/kock för diskret attribution (t.ex. "Gordon Ramsay").
+ * Utelämnad = husets redaktion. Visas som liten "Källa: …"-rad, aldrig badge. */
+ creatorDisplayName?: string;
ingredients: SeedRecipeIngredient[];
steps: SeedRecipeStep[];
}
import { VERIFIED_RECIPES } from "./verified-recipes.js";
import { EXTRA_RECIPES } from "./extra-recipes.js";
+import { CHEF_RECIPES } from "./chef-recipes.js";
/** Hela seed-katalogen: committade verifierade recept + nya redaktionella extrarecept. */
-export const SEED_RECIPES: SeedRecipe[] = [...VERIFIED_RECIPES, ...EXTRA_RECIPES];
+export const SEED_RECIPES: SeedRecipe[] = [
+ ...VERIFIED_RECIPES,
+ ...EXTRA_RECIPES,
+ ...CHEF_RECIPES,
+];
diff --git a/packages/database/src/seed/run.ts b/packages/database/src/seed/run.ts
index 66a5de8..5dca1c0 100644
--- a/packages/database/src/seed/run.ts
+++ b/packages/database/src/seed/run.ts
@@ -767,7 +767,7 @@ async function insertRecipe(
verificationStatus: recipe.verificationStatus ?? "editorial",
sourceType: "own_editorial" as const,
sourceRegistryId,
- creatorDisplayName: `${BRAND.name} Redaktion`,
+ creatorDisplayName: recipe.creatorDisplayName ?? `${BRAND.name} Redaktion`,
};
const [row] = await db