Log inSign up

How to build in-app announcements with Flows

Learn how to build and launch your very own Flows powered announcements to engage users, highlight features, and achieve 100% open rate.

In-app announcement banner example

Ondrej PesickaJune 19, 20257 min read

Have you ever wanted to notify your users about a new feature launch or highlight a recent changelog? One of the most effective ways to do this is by delivering messages directly inside your app, right where your users already are.

In-app announcements offer a 100% open rate (unlike emails or social posts) and can be highly contextual to what users are doing. You can use them to promote new features, share changelogs, announce scheduled maintenance, or promote blog posts and events. They’re also flexible in format: they can appear as modals on login or as persistent banners in the sidebar or header.

How to build in-app announcements with Flows

Let’s walk through how to build an in-app announcement using Flows. Imagine you've just launched a new Dark Mode feature. You want to display a persistent banner in your app’s sidebar so users can learn more at any time. And you’d also like to reuse this banner for future announcements.

Step 1: Create the UI component

Start by building a reusable AnnouncementBanner component in React. This component will render the announcement using properties passed from Flows.

1import { ComponentProps } from "@flows/react";
2import Link from "next/link";
3
4type Props = ComponentProps<{
5 title: string;
6 description: string;
7 href: string;
8 continue: () => void;
9}>;
10
11export const AnnouncementBanner = (props: Props) => {
12 return (
13 <div className="background-gradient rounded-[9px] p-[1px] transition-all hover:scale-[1.02]">
14 <Link
15 href={props.href}
16 className="flex flex-row-reverse gap-0.5 rounded-lg border bg-white shadow-md transition-all hover:shadow-lg dark:bg-neutral-900 md:flex-col"
17 onClick={() => props.continue()}
18 >
19 {/* Decorative illustration – replace with your own if needed */}
20 <Illustration />
21 <div className="flex w-full flex-col justify-center gap-1 p-2">
22 <p className="text-sm font-semibold">{props.title}</p>
23 <p className="text-xs">{props.description}</p>
24 </div>
25 </Link>
26 </div>
27 );
28};
1import { ComponentProps } from "@flows/react";
2import Link from "next/link";
3
4type Props = ComponentProps<{
5 title: string;
6 description: string;
7 href: string;
8 continue: () => void;
9}>;
10
11export const AnnouncementBanner = (props: Props) => {
12 return (
13 <div className="background-gradient rounded-[9px] p-[1px] transition-all hover:scale-[1.02]">
14 <Link
15 href={props.href}
16 className="flex flex-row-reverse gap-0.5 rounded-lg border bg-white shadow-md transition-all hover:shadow-lg dark:bg-neutral-900 md:flex-col"
17 onClick={() => props.continue()}
18 >
19 {/* Decorative illustration – replace with your own if needed */}
20 <Illustration />
21 <div className="flex w-full flex-col justify-center gap-1 p-2">
22 <p className="text-sm font-semibold">{props.title}</p>
23 <p className="text-xs">{props.description}</p>
24 </div>
25 </Link>
26 </div>
27 );
28};

The Props type defines the data Flows will pass to the component: a title, description, href, and a continue function that dismisses the banner when clicked. We will fill these properties when we create the workflow in Flows.

Announcement banner component UI example

This is how our component looks like when rendered in the app. For now we hardcoded it into the layout to test it, but now it’s time to integrate it with Flows so we can use it in workflows.

Step 2: Register the component in the FlowsProvider

Next, we need to tell Flows about our AnnouncementBanner component so that it can be used in workflows. We do this by adding it to the components prop in the FlowsProvider.

1import { FlowsProvider } from "@flows/react";
2import { AnnouncementBanner } from "./AnnouncementBanner"; // Adjust path as needed
3
4const App = () => {
5 return (
6 <FlowsProvider
7 organizationId="your-organization-id"
8 environment="development"
9 userId="your-user-id"
10 components={{
11 AnnouncementBanner, // Pass the component to the FlowsProvider
12 }}
13 tourComponents={{}}
14 >
15 {/* Your app code here */}
16 </FlowsProvider>
17 );
18};
1import { FlowsProvider } from "@flows/react";
2import { AnnouncementBanner } from "./AnnouncementBanner"; // Adjust path as needed
3
4const App = () => {
5 return (
6 <FlowsProvider
7 organizationId="your-organization-id"
8 environment="development"
9 userId="your-user-id"
10 components={{
11 AnnouncementBanner, // Pass the component to the FlowsProvider
12 }}
13 tourComponents={{}}
14 >
15 {/* Your app code here */}
16 </FlowsProvider>
17 );
18};

Step 3: Create a block template

Now that we have our AnnouncementBanner component, we can create a block template for it in Flows. This makes it easy for your team to reuse the component in workflows.

Screenshot of the announcement banner block template configuration in Flows

Configure the block template like this:

Once published, this block template can be used in any workflow.

Step 4: Add a slot in your app layout

To display the banner, we need to add a FlowsSlot component to your app's layout. This will tell Flows where to render the component in the app structure. For this example, we’ll place it in the sidebar.

1import { FlowsSlot } from "@flows/react";
2
3export const Sidebar = () => {
4 return (
5 <div>
6 {/* Your sidebar content */}
7 <FlowsSlot id="sidebar" />
8 </div>
9 );
10};
1import { FlowsSlot } from "@flows/react";
2
3export const Sidebar = () => {
4 return (
5 <div>
6 {/* Your sidebar content */}
7 <FlowsSlot id="sidebar" />
8 </div>
9 );
10};

This FlowsSlot acts as an anchor point for where Flows will render the component. The id is used to reference the slot in the workflow configuration.

Step 5: Create the announcement workflow

Now we are ready to create a workflow that will show the announcement banner to users when they log in to the app.

Screenshot of the workflow configuration in Flows
  1. Start by adding a Start block without any conditions (for now).
  2. Add the Announcement banner block and fill in the title, description, and link.
  3. Set the Slot ID to sidebar to match the slot in your app.
  4. Connect the Start block to the Announcement banner block.

When ready, publish the workflow to your development environment (or any other environment you are using) for testing.

Screenshot of the publish dialog in Flows

Log in to the app, and you should see the banner rendered in the sidebar. Clicking it should redirect you and dismiss the banner.

Step 6: Publish to production

When you’re happy with the workflow, publish it to your production environment.

We recommend adding conditions to the Start block to target only relevant users. For example targeting only users who registered before the feature was launched, or users with a specific role.

Screenshot of the start block conditions configuration in Flows

Publishing new announcements without code changes

Now let’s say a few days later, you launch another new feature: two-factor authentication. You can reuse the same workflow setup without writing any additional code.

First let’s update the content that we have in the current announcement banner workflow. Note that we are making changes in the draft version of the workflow.

Screenshot of the updated announcement banner content in Flows

Since we are not editing the content of the old announcement, but rather, create a new announcement to replace the old one, we will publish the new version with the Restart all users migration option. This will creating a new version of the workflow that restarts all users and shows them the new announcement. The end result is that any users who meets the workflow start block conditions will see the new announcement banner with the updated content.

Screenshot of the restart all users migration option in Flows

Note that we did this entirely through Flows without having to update any code. For any future announcements, we can just repeat this part of the process.

Wrapping up

In this post, we walked through how to:

This approach gives your product and marketing teams full control over user communication while allowing you to build components that match your product's design and functionality.

If you’d like to see the full working example, check out the live demo and the accompanying GitHub repo for this post.

Next steps

We can’t wait to see what kinds of announcements you’ll build with Flows! In the meantime, check out:

✨ By the way, we also use the same approach to announce features and updates in Flows itself. Meta, right?

Get started today!

Build the product adoption experiences you've always wanted.

Get started for free