How to make a recipe site that scales well
Bak&del is a site created to solve common frustrations with online recipe sites. Read how Dag used Sanity to make recipe instructions that scale (pun intended).
Published
Dag Stuan
Manager/engineer at Bekk
![](https://cdn.sanity.io/images/3do82whm/next/5dfb79942c79c0f4087fe777a1643fdeea61d179-1440x1080.png?w=3840&q=75&fit=clip&auto=format)
Recently, Dag Stuan, engineer at Bekk, shared a cool recipe project in the community with nifty use of Portable Text. We asked him to write about his process to make "Bak & del". The name Bak&del is a playful Norwegian pun that combines "bake" (to bake) and "del" (to share), perfectly capturing the spirit of a baking community. As a cheeky bonus, the word bakdel also means âbuttâ in Norwegian slangâbecause who says baking canât have a little spice?
One of the best things about programming is that you can solve everyday problems all by yourself. With my latest hobby project, Iâm doing just that. Meet bakdel.no (or go here for English version via Google Translate)!
![Bak&del website interface showing recipe options: âBoller,â âFirkornbrød,â and âHavrebrød,â each with an estimated preparation time. The tagline reads, âLettleste oppskrifter som skalerer.â](https://cdn.sanity.io/images/3do82whm/next/82450abf9cffe74e61283fceca83b1d84751f94c-1600x845.png?w=3840&q=75&fit=clip&auto=format)
The problem
In recent years, Iâve started baking bread and other yeast-based goods at home. I have a few recipes Iâve used for a long time, and I also look up recipes online when I want to bake a different type of bread or other baked goods
There are countless recipe sources online, so I rarely find recipes in the same place. Many of the sites are âokayâ to use, but I often feel thereâs more focus on the person publishing the recipe, than on me, the one actually baking. The recipes are filled with the life stories of the bloggers who write them, and packed with ads or affiliate links to things I can buy. Some sites even use a âbait-and-switchâ tactic, placing recipes behind a paywall after a while.
Although the actual recipes often are good, I also find them challenging to use. When Iâm on my phone, I have to constantly scroll between the ingredient list and the recipe text, and the instructions are often packed with information I donât need.
But the biggest issue, and the main reason I created Bakdel, is scaling. When I bake bread, I want to make three loaves at a time because thatâs what fits in my oven. The recipes I find are often for one or two loaves, so I have to scale them myself. So when I found myself with an Excel spreadsheet just for baking, I thought to myself âthere must be a better wayâŚâ.
![Table displaying ingredients and their quantities for breadmaking, with columns for ingredient names, original amounts, percentages, and scaled quantities for three loaves.](https://cdn.sanity.io/images/3do82whm/next/bc864323bec3c326843efcd6b3f2885e6d3b21eb-1130x498.png?w=3840&q=75&fit=clip&auto=format)
How could it be better?
What I wanted, was a place where I could:
- Store recipes I like in an easy-to-read, well-organized format. Without ads or unnecessary information.
- Avoid scrolling back and forth between the ingredient list and the recipe instructions while baking.
- Scale recipes so I can bake three loaves instead of two, or make waffles even if I only have two eggs left in the fridge on a Sunday.
The idea
At Bekk Trondheim, weâve had a few workshop evenings this fall where we learned to use Sanity and completed the Sanity Developer Certification. Sanity is a content operating system that allows me to define content in the form of âdocumentsâ or âobjects.â Unlike a traditional CMS, content in Sanity isnât tied to a presentation layer; itâs more akin to a traditional SQL database or other low-level content abstractions.
What sets Sanity apart from other headless CMS solutions is the ability to customize the editor experience. When setting up a project, youâre responsible for configuring Sanity Studio, the user interface for editing content. The studio is very customizable, which makes it relatively easy to tailor an editor experience to the content being created.
When I got familiar with how to set up Sanity, I had an idea; what if I could model recipes and ingredients as content in Sanity, and create references to ingredients within a recipeâs instructions? That way, I could create a content model that made it easy to add recipes and link to the ingredients within the recipe text.
![Interface snippet showing an âIngredient Referenceâ label with options to edit or delete, highlighting âPizzamel (100%)â as a selected ingredient.](https://cdn.sanity.io/images/3do82whm/next/ef94fff2f310ccb32c5bdec4afad3751a261af11-492x194.png?w=1080&q=75&fit=clip&auto=format)
With a bit more logic, I could scale the ingredients dynamically so that adjusted quantities could appear directly in the text. When I showed a small demo to some colleagues, I got the suggestion to add a feature for checking off ingredients as you go, which was also fairly quick to implement. With that, the core product was in place, and most of the time since has been spent on refinement.
![Baking instructions showing interactive ingredient references, including margarine, milk, flour, sugar, cardamom, and yeast, with scalable quantities and input fields for customization.](https://cdn.sanity.io/images/3do82whm/next/f05eaa49927b29c95126d3e7edced106f299b2ca-1376x400.png?w=3840&q=75&fit=clip&auto=format)
![Recipe editing modal with adjustable quantity and editable ingredient fields, including weight and measurement units, and options to reset or save changes.](https://cdn.sanity.io/images/3do82whm/next/93e2ce6c1cef48b33ebc4d13d1c49ef1bfdf56cb-1074x1546.png?w=3840&q=75&fit=clip&auto=format)
Below is a excerpt of the schema code that defines the Portable Text field for Instructions (find all of the code on GitHub):
// Definition for the instructions field for Portable Text
defineField({
name: "instructions",
title: "Instructions",
group: ["content"],
type: "array",
of: [
defineArrayMember({
type: "block",
styles: baseBlockStyles.filter((s) => s.value !== "h2"),
lists: baseBlockLists,
marks: baseBlockMarks,
of: [
{ type: recipeIngredientReferenceType.name },
{ type: scalableRecipeNumberType.name },
],
}),
alertArrayMember,
imageArrayMember,
imageGalleryArrayMember,
],
})
```
Other technology choices
When I code in my spare time, I try to balance using technology I know well, with trying something new. This way, I stay productive with familiar tools while also picking up some new knowledge along the way. Familiar technology and productivity also help me stay motivated to finish a usable product.
Bakdel is built as a Next.js app that includes both the website and the Sanity studio. For styling and UI components, I used Tailwind and Shadcn to speed up the setup. I also hadnât worked with these before, so it was a great chance to explore a bit of new tech. I also got a bit of a boost from Vercelâs v0 platform to get up and running quickly.
The app is hosted on Vercel, with DNS and proxy managed by Cloudflare. Together, these tech choices helped me get to production in a very short time, and the first version of the app was live after just a week of work.
Next Steps đŁď¸
A little over a month later, I have a product Iâm quite satisfied with and that I use several times a week when I bake. Itâs easy to add new recipes using Sanity Studio, the ingredients are embedded within the instructions, even when the recipe is scaled, and users can scale recipes based on individual ingredients. Plus, thereâs minimal unnecessary information, and no ads. đ
While I have no plans to compete with larger recipe sites, itâs nice to have at least one place to go when I want to bake, where I can easily store the recipes I like. And if others can benefit from the site as well, thatâs an added bonus.
I plan to incorporate even more scaling logic in the future, and recently I have also added the ability to change measurement units in recipes, allowing users to switch from deciliters to grams in the recipes themselves.
If you have a recipe suggestion thatâs missing, or if you have any other questions, feel free to reach out with your feedback!
You can find the app at bakdel.no, and the source code is available on GitHub.