Building a realtime React admin panel with Ably and refine

Building complex, data-intensive realtime full-stack applications from the ground up can be daunting and time-consuming. Fortunately, there are several front-end frameworks in the react ecosystem that can improve your development speed and reduce time to production. One such framework is refine.

refine is a react-based framework for building data-intensive applications such as admin panels and dashboards. It comes with built-in features for routing, authentication, and i18n. It supports most popular UI frameworks, design systems, and cloud-based platforms like Firebase, Supabase, and Ably.

When looking to build a realtime data-intensive application, refine and Ably can get you up and running quickly. This tutorial will introduce you to refine and Ably by building a simple realtime React admin panel.

What is refine

refine is a customizable React framework you can use to build web applications. It has built-in solutions for: authentication, routing, networking, i18n, and state management.

refine comes in handy when building data-intensive front-end applications such as dashboards and admin panels. The refine ecosystem has integrations for popular UI frameworks like Ant Design, Material UI, Chakra UI, and Mantine.

How to set up a refine application

If you are starting with refine, you can quickly set up a basic generic application using the browser tool option or from create refine app CLI tool.

The create refine app and will create a new refine application with the necessary configuration.

Follow the one of options below to create a refine application.

Using project setup option

Using the refine command line tool

You can simply run the following command:

npm create refine-app@latest

Then choose the following options:

✔ Downloaded remote source successfully.
✔ Choose a project template · refine(CRA)
✔ What would you like to name your project?: · refine-ably-demo-app
✔ Choose your backend service to connect: · REST API
✔ Do you want to use a UI Framework?: · Material UI
✔ Do you want to add example pages?: · Yes
✔ Do you need any Authentication logic?: · None
✔ Do you need i18n (Internationalization) support?: · No
✔ Would you mind sending us your choices so that we can improve superplate? · Yes

Please be aware that we have selected “Yes” in response to the prompt “Do you want to add example pages?”. By doing so, the CLI will automatically include pre-configured example pages, which will help us to save time.

Start the development server

Navigate to the project directory you created in the previous step and launch the development server using one of the commands below.

npm run dev

The command above will launch the development server on localhost on port 3000. The landing page of your refine project should look like the image below.

Default blog page

How to create Ably app and generate an API key

To start using the Ably platform, you need to have an account.

Ably signup page

After login, create a new app. Ably will generate an API key which you will use to integrate Ably with your refine application.

Create new Ably app button

Main concepts in refine

When working with refine, you will encounter several concepts. We will explore some of these concepts in the sub-sections below.

Data Provider and resources

Data providers are among the main building blocks of refine. Data-intensive front-end applications like dashboards interact with the back-end to access data. With refine, this interaction takes place in data providers.

refine comes with customizable built-in data providers for RESTful API, GraphQL API, and cloud databases like Firebase and Supabase. We will use a RESTful API data provider in the section below.

As highlighted above, an admin panel is a data-intensive application. We need to source this data from somewhere. While creating the refine app in one of the sections above, we chose RESTful API as our back-end service.

Therefore, the command line tool installed the RESTful API data provider out of the box. When you check the App.jsx file, one of the props passed to the <Refine /> component is the dataProvider. You can also use a custom data provider if the built-in data provider doesn’t meet your needs.

refine has a fake RESTful API that we will use in this article. You can use a different RESTful service if you want. One of the resources in the fake RESTful API is the blog_posts resource. We will use it in this example.

As highlighted above, you interact with the back-end inside data providers when working with refine. The back-end API you source data from comprises resources on which you can perform CRUD operations.

You can use the resources prop of the <Refine /> component to add the API resources. The resources prop is an array of resource objects looks like below.

The resources are specified using the resources prop of the <Refine /> component like so:

          name: "blog_posts",
          list: "/blog_posts",
          show: "/blog_posts/show/:id",
          create: "/blog_posts/create",
          edit: "/blog_posts/edit/:id",
          meta: {
            canDelete: true,


Inferencers are use to generate CRUD pages based on your data model and reduces the time you would spend when creating components from scratch.

The generated components are usually basic and generic. You can customize them to suit your project’s requirements.

As we have a preference for using the CLI to include example pages, the inferencer code is already pre-configured and integrated into the application. We will use Material UI inferencer since we used Material UI as the UI framework in the refine project we created above.

We will use Material UI inferencer since we used Material UI as the UI framework in the refine project we created above.


import { IResourceComponentsProps } from "@refinedev/core";
import { MuiListInferencer } from "@refinedev/inferencer/mui";

export const BlogPostList: React.FC<IResourceComponentsProps> = () => {
  return <MuiListInferencer />;

When you navigate to the /blog_posts path, your app will fetch a list of blog_posts and display it in a table like in the image below.

How to activate a Realtime feature with Ably on the app

After creating a simple refine application and obtaining an API key from Ably, let us integrate a Realtime feature to our CRUD app using Ably. Follow the steps below.

Step 1 — Open the refine project in a text editor

Open the refine project you created in one of the previous sections above in a text editor or a development environment of your choice.

Step 2 — Install refine Ably client package

As hinted above, the refine ecosystem has several packages for integrating cloud platforms and Realtime solutions like Ably. Depending on your package manager, install the @refinedev/ably package from the NPM package registry using one of the commands below.

npm install @refinedev/ably

Step 3 — Integrate Ably with refine

After successfully installing the @refinedev/ably package in the previous step, integrate Ably with refine. Start by creating a .env file at the root of your refine project directory for keeping your Ably API key.

Add the following environment variable to the .env file and set its value to your Ably API key. Replace 1234 with your Ably API key. Be sure to restart the development server after creating an environment variable.


Add the .env file you have created to your .gitignore file so you don’t expose it in a version control system like Git.

Create the src/utility/ablyClient.ts and src/utility/index.ts files. Copy and paste the code below into the src/utility/ablyClient.ts you have created.

The code below uses your Ably API key to create an Ably client and exports it to use anywhere in your refine application.

import { Ably } from "@refinedev/ably";

export const ablyClient = new Ably.Realtime(process.env.REACT_APP_ABLY_API_KEY!);

Similarly, copy and paste the code below into the src/utility/index.ts file you created. It will enable you to import exports from the src/utility directory.

export * from "./ablyClient";

The <Refine /> component is the entry point for any refine application. The App component renders the <Refine /> component in the App.tsx file. The liveProvider prop of the <Refine /> component is for integrating refine with any realtime provider.

The liveProvider prop is agnostic of any realtime solution. You can use it with any realtime provider. In this article, you will use it to integrate Ably with your refine application. Apply the changes below to your App.tsx file.

import { ablyClient } from "utility";
import { liveProvider } from "@refinedev/ably";

function App() {
  return (
                liveMode: "auto",

export default App;


Quick info for live mode options.

auto: Queries of related resource are invalidated in Realtime as new events from subscription arrive.

manual: Queries of related resource are not invalidated in Realtime, instead onLiveEvent is run with the event as new events from subscription arrive.

off: Disables live mode.

Refer to live provider docs for more information


That is everything you need to do to integrate Ably with your refine application.

You can now perform CRUD operations on the blog_posts in the fake API we used. When you delete, update, or create a new product, Ably will broadcast the changes in realtime.

As demonstrated below, any modifications made to an existing record are immediately reflected, all thanks to the Ably live provider.

The realtime dashboard working

This tutorial illustrates how you can build a basic CRUD app with realtime feature with refine and Ably. There is a lot you can do with refine and Ably that have not been highlighted in this article. Check out the refine or Ably documentation.

You can find the source code of the Ably live provider example implementation here.