# A fullscreen recipe browser for Storyblok, built from one sentence

*When a picker needs room, open it fullscreen, and keep a compact card in the form*

By Dominik Angerer · 4 November 2026 · https://d12r.io/e/storyblok-recipe-picker-fullscreen-field-plugin/

**TL;DR:** A Storyblok field with a fullscreen browser, search and filters, and a compact card in the form. Copy the prompt and build it yourself.

Some choices are visual. Picking the "recipe of the week" from a list of names doesn't work. You want to see the dishes. This field opens a fullscreen browser with search and filters, and leaves a small card in the form once you've picked.

> **Try it yourself**
>
> Paste this into Claude Code or Cursor:
>
> ```
> Fetch and follow the Storyblok field plugin instructions at https://raw.githubusercontent.com/DominikAngerer/storyblok-field-wizard/main/generator/PROMPT.md and build this field:
> A "recipe of the week" field for a food magazine using DummyJSON recipes (https://dummyjson.com/recipes). Inline it shows "No recipe selected yet." with a "Browse recipes" button, or, after a pick, a compact card with image, name, ID, a Change button and a remove (✕) button; it stores { "id", "name", "image" } (name and image are a snapshot), null when empty, and reads a bare id from an older version. Browse opens the fullscreen portal modal with a debounced search box, meal type, tag and difficulty filters, a Reset button and a result count; tiles show image, name, cuisine, difficulty and total time (prep + cook), the current pick is marked "Current selection", and a "Show more (N left)" button reveals the next page. The API takes only one filter per request, so send the search term (else the tag, else the meal type) to the server and apply the other filters, and difficulty, in the browser; load tags from /recipes/tags and hide the tag filter if that fails, and only offer difficulty values that exist in the data. Options: mealTypes (comma-separated, trimmed and de-duplicated, default Breakfast,Lunch,Dinner,Snack,Dessert,Appetizer,Side Dish,Beverage) and pageSize (default 12); the modal closes after a pick, on its Close button and on Escape, and has generous padding.
> ```
>
> Already have the Claude Code plugin? Run:
>
> ```
> /storyblok-field:storyblok-field "A DummyJSON recipe-of-the-week picker with a fullscreen browser, search, meal type, tag and difficulty filters, and a compact inline card"
> ```
>
> It takes about three minutes and needs Node 22+. You only need a Storyblok personal access token if you want to deploy.

> **Good to know: plugin names are global**
>
> Field plugin names in Storyblok are shared across all spaces, not per space. If the field doesn't render correctly in the preview, or the deploy fails with `DUPLICATED_NAME`, someone else probably has that name already. Give yours a different one, for example `@yourhandle/recipe-picker`. It happened to me with the [code editor field](https://d12r.io/e/storyblok-code-editor-field-plugin/).

## What it's for

A food magazine features one recipe each week. The editor wants to browse: desserts, easy ones, something Italian for dinner. Storyblok lets a field plugin switch to fullscreen, so this field uses that for browsing with search and filters, then goes back to a compact card in the form. The frontend gets the id, name and image, which is enough for a teaser, and can load the full recipe by id when it needs ingredients and steps. The recipes come from [DummyJSON](https://dummyjson.com), but the pattern fits any visual catalogue: case studies, events, videos.

> **Thanks to DummyJSON**
>
> The recipes in this field come from [DummyJSON](https://dummyjson.com/), a free fake REST API with placeholder data for development, testing and prototyping, built by [Ovi](https://github.com/ovi). No sign-up and no API key, which made it easy to try field plugins against real-looking data.

## What you get

![Fullscreen recipe browser with search, meal type, tag and difficulty filters, and a grid of recipe tiles](https://a.storyblok.com/f/296339501219281/2400x1800/f1a8d049e2/dummyjson-recipe-picker-02-browser-open-31c8a693.png)

*The fullscreen browser: filters on top, 12 tiles per page, "Show more" below.*

![Dessert plus Easy narrows the list to two recipes](https://a.storyblok.com/f/296339501219281/2400x1800/8f00a292aa/dummyjson-recipe-picker-05-filter-dessert-easy-433b304e.png)

*Meal type from the API, difficulty filtered in the browser: two results.*

![After picking, a compact card with image, name, ID, Change and remove button](https://a.storyblok.com/f/296339501219281/2144x1566/c80ca02fe6/dummyjson-recipe-picker-08-picked-ed5a487d.png)

*Back in the form: a compact card, and the stored JSON below.*

The stored value:

```json
{
  "id": 1,
  "name": "Classic Margherita Pizza",
  "image": "https://cdn.dummyjson.com/recipe-images/1.webp"
}
```

| Option | Default | What it does |
| --- | --- | --- |
| `mealTypes` | `Breakfast,Lunch,Dinner,Snack,Dessert,Appetizer,Side Dish,Beverage` | Meal types offered in the filter. |
| `pageSize` | `12` | Recipes shown before "Show more". |

## Using it in the frontend

```jsx
const recipe = blok.recipe_of_the_week // { id, name, image } | null

{recipe && (
  <a href={`/recipes/${recipe.id}`}>
    <img src={recipe.image} alt={recipe.name} />
    <h2>{recipe.name}</h2>
  </a>
)}
```

For ingredients and steps, fetch `https://dummyjson.com/recipes/${recipe.id}`.

## What I learned building it

- **Real APIs are messy.** DummyJSON accepts one filter per request, so the field sends the most selective one to the server and applies the rest in the browser. The data also mixes "Snack" and "Snacks" and has no "Hard" recipes. The guide now says to only offer filter values that exist. This field was generated before that rule, so its difficulty filter still offers "Hard".
- **The modal needs a way out.** The agent that built this field pointed out that my guide said nothing about closing a modal with Escape. The field closes on Escape, and the rule is now in the guide: Close button, Escape, and close after a pick.
- **A CSS order bug no test would catch.** I asked for more padding in the fullscreen view. The padding rule had been there all along, but the template loaded its shared `ui.css` *after* the field's own CSS, so `.sb-field { padding: 2px }` won at equal specificity. The fix here is a more specific selector, and the template now loads `ui.css` first, so every future field's CSS wins. A screenshot showed it right away.
- **Two close buttons.** Storyblok's modal has its own "×", and the field adds a "Close" button. Both work. It's cosmetic, so I kept both.

This field was generated by a fresh agent from one sentence and the guide, in about 2.7 minutes. The full story is in [the article about the original experiment](https://d12r.io/e/midnight-idea-generating-storyblok-field-plugins/). The other fields: [brand color picker](https://d12r.io/e/storyblok-brand-color-picker-field-plugin/), [product picker](https://d12r.io/e/storyblok-product-picker-field-plugin/), [author picker](https://d12r.io/e/storyblok-author-picker-field-plugin/), [code editor](https://d12r.io/e/storyblok-code-editor-field-plugin/).
