Introducing Breve: an arty coffee app built for iOS 26

I'm really excited to finally introduce my new app, Breve: Barista Recipes, released just a few days ago. Breve is available on iPhone and iPad and comes with a large collections of coffee recipes and guides that adapt to whatever equipment users have on hand, from espresso machines, to simple hands-on tools.

Coffee drink collections in Breve on iPad and a Cortado recipe on iPhone

Breve is built for iOS 26 and combines the new Liquid Glass design with soft colorful background gradients and watercolor-style artworks. If you want to check it out, you can find it on the App Store. If you feel like leaving a rating or review, it would mean a lot and help more people come across it.

I've been working on Breve for the last few months, and it gave me a great platform to experiment with the new iOS 26 APIs, and system integrations. While I kept the app itself secret until the launch date, I've been documenting many of my technical learnings on the blog. Now that Breve is out, I'd like to revisit those key learnings and share insights that may be useful for others working on their iOS 26 projects too.

# Background extension effect

One of the interesting design solutions in Breve is the recipe detail header with the watercolor illustration blending into the background. I achieved this look using a combination of background extension effects, blurs and gradient overlays.

Espresso recipe in light mode and Bicerin recipe in dark mode on iPhone

The new backgroundExtensionEffect() modifier in iOS 26 lets us extend and blur visual content beyond a view's bounds, creating continuous backgrounds behind elements like sidebars, inspectors, and overlay controls. But we can also use it more creatively, for example, by extending and blurring an image into the surrounding safe area.

If you want to learn more about the new backgroundExtensionEffect() modifier in SwiftUI and see some examples of how it can be used, take a look at my post: Create immersive backgrounds in SwiftUI with backgroundExtensionEffect().

# Stretchy header

It's a common design pattern in modern iOS apps to have a large image at the top of a scroll view, extending all the way into the top safe area, like I have in the recipe view in Breve. To avoid revealing empty space above the image, when the user pulls down to overscroll, I added a stretchy header effect.

Scrollable recipe detail screen where a full-width coffee image at the top stretches smoothly when overscrolled iPhone 16 Frame

There are a few ways to achieve this effect in SwiftUI and I most commonly see developers using onScrollGeometryChange() where they get the scroll offset, write it to a shared app state, and then use it to compute the frame of the image. But we can also do it in a slightly simpler way using the visualEffect() API.

If you'd like to add something similar in your apps, feel free to use my strechy() modifier built with the visualEffect(). You can get the code for it from my post: Stretchy header in SwiftUI with visualEffect().

# Search functionality

For the search functionality in Breve I decided to use a separate tab. This pattern appears in many Apple apps such as Health, Music, and Books and works nicely with the Liquid Glass tab view in iOS 26. To adopt this pattern in SwiftUI, we need to create a Tab with the search role and apply the searchable() modifier to the TabView. You can see the example code for it, and other search placements in iOS 26 in my article: SwiftUI Search Enhancements in iOS and iPadOS 26.

On iPhone the search tab appears visually separated from the others and transforms into a glassy search field when selected.

Tab view and search tab in Breve on iPhone

On iPad, the search field is placed in the navigation bar by default, and it works well with a sidebar adaptable tab view.

Sidebar adaptable tab view and search tab in Breve on iPad

Breve is a very content-rich app, so making sure users can quickly find what they are looking for is important. To make the content searchable not only within the app but also through system-wide Spotlight search, I indexed it with Core Spotlight. It's possible to use the same search index for both, and I wrote a detailed post on how this can be done: Core Spotlight integration for Spotlight and internal app search.

# Liquid glass sheets

In addition to the Liquid Glass tab view with search, Breve also makes use of the new Liquid Glass sheet appearance for preferences, paired with a morphing transition from the settings button.

Preferences sheet morphing from the settings toolbar button iPhone 16 Frame

To take advantage of the new iOS 26 Liquid Glass sheet design, we need to make sure that our presentation detents include at least one partial-height option. And to implement the morphing transition, we can use the matchedTransitionSource() modifier on the ToolbarItem, paired with navigationTransition() on the view inside the sheet. I walk through all the necessary setup in Presenting Liquid Glass sheets in SwiftUI on iOS 26.

Like in many other apps, the Preferences sheet in Breve contains a form and also pushes views onto a navigation stack within the sheet content. In such cases, the default Liquid Glass background in partial-height gets obscured by the form and the navigation destination background, unless we add a few extra configurations. I described how the glassy sheet appearance can be achieved in more complex sheets in my post on SwiftUI Liquid Glass sheets with NavigationStack and Form. I use the techniques covered in my article, such as reading the current sheet detent and adjusting the scroll content background, to make sure that my Preferences sheet presents the form appropriately in both medium and large detents.

Preferences sheet in Breve in medium and large detents

# AlarmKit integration

In terms of system integration, I thought the most appropriate iOS 26 framework to bring into the first release of Breve would be AlarmKit.

AlarmKit lets us schedule one-time alarms, weekly repeating alarms, and countdown timers that start immediately, and in Breve it's used for brewing timers. The framework provides APIs to request authorization from users, customize alerts that cut through silent mode and Focus, and display a live countdown in a Live Activity. I walk through the setup, which is quite involved, in my blog post: Schedule a countdown timer with AlarmKit.

Unfortunately, there are no APIs for displaying a live countdown inside the app, so I had to write some custom logic for it in Breve, placing the countdown either in a tab view accessory or in the bottom toolbar, depending on where in the app the user is. I'll try to cover that in an upcoming post.

Timer running in a tab view accessory and in a Live Activity


Breve gave me plenty of chances to try out new APIs and design ideas, and I've got a backlog of learnings that I haven't had a chance to turn into blog posts yet. I'm going to do my best to share as much as I can in the near future.