How I created a live subscribers counter in NextJS (with source code)
Tags: nextjs, api, showdev
Published: 2024-06-11 12:53:00


# How I Created a Live Subscribers Counter in NextJS

Hey web developers,
I built an engaging feature on a newsletter subscription page to enhance the user experience and trust of my [Obsibrain](https://www.obsibrain.com) landing page. One intriguing way of doing this is by displaying a live subscriber counter. In this article, I will walk you through how I created such a feature using Next.js API and the Brevo API.

## Introduction

In this tutorial, we will build a function that fetches the number of subscribers from Brevo and displays the total number on the front-end. Whenever there is a new subscriber, the counter will be updated in real-time.

## First things first, the basic Next.js API route

This is the foundation of a Next.js API route. 
The `GET` function is an asynchronous function that serves as the request handler for HTTP GET requests to this API endpoint.

This API route is located under:
`app > api > get-subscriptions > route.ts`

```typescript
import type { NextRequest, NextResponse } from 'next/server'

export async function GET(req: NextRequest, res: NextResponse) {
  // More code...
}
```
## Getting the Subscribers from Brevo

First things first, let's fetch the list of subscribers. We use the Brevo API for this purpose. 
(explanation inside the code snippet)

Here's the code snippet:

```typescript
import dotenv from 'dotenv'
import type { NextRequest, NextResponse } from 'next/server'

dotenv.config()

const BASE_URL = `https://api.brevo.com/v3`
const API_KEY = process.env.BREVO_API_KEY

// full url
const url = [BASE_URL, 'contacts'].join('/')

export async function GET(req: NextRequest, res: NextResponse) {
    try {
    // making the request with the required headers
      const response = await fetch(url, {
        method: 'GET',
        headers: {
          'Accept': 'application/json',
          'api-key': `${API_KEY}`,
        }
      })

      const data = await response.json()

	// checking for the response to be 'ok' and be successful
      if (!response.ok) {
        return new Response(JSON.stringify({ message: 'Error getting list of subscriptions' }), { status: 500 })
      }
    } catch (error) {
      return new Response(JSON.stringify({ message: 'Error getting list of subscriptions', error }), { status: 500 })
    }
}
```

## Invalidating on Each New Subscriber

To keep our subscriber list fresh and updated, we use the revalidation option provided by Next.js to invalidate the cached data and fetch fresh data periodically both on backend and frontend.

```typescript
export const revalidate = 300

export async function GET(req: NextRequest, res: NextResponse) {
//...
}
```

By setting `revalidate` to 300 seconds, the data will be revalidated every 5 minutes (backend) to ensure we are displaying the most current subscriber count.

```typescript
const response = await fetch(url, {
        method: 'GET',
        headers: {
          'Accept': 'application/json',
          'api-key': `${API_KEY}`,
        },
        next: { tags: ['subscriptions'] }, // NextJS tags
        
      })
```

The `tags` property is an array of strings that can be used to uniquely identify a request. This is particularly useful when you want to invalidate the cache for a specific request in the future.

This means that whenever the cache for this specific request needs to be invalidated (for example, when a new subscriber is added), Next.js can target this request by looking for the `'subscriptions'` tag (used in frontend in our case but can be invalidated on backend as well).

```typescript
import { revalidateTag } from 'next/cache'

revalidateTag('subscriptions') // revalidate the cache for the get-subscriptions route
```

## Returning the Data

Once we've fetched the subscriber data, the final step is to return this information in a structured format. The function wraps up the data in a JSON response that includes the total number of subscribers.

Here's the concluding part of the code:

```typescript
return new Response(
  JSON.stringify({
    message: 'Subscriptions fetched successfully',
    data: { totalSubscriptions },
  }),
  { status: 200 },
)
```

This structured response allows the front-end to easily consume the data and dynamically update the subscriber count, ensuring a live, optimized (with cache) and interactive user experience.

## Any Questions?

If you have any questions about my setup or if you encounter any issues while implementing this feature, feel free to reach out. I'm more than happy to provide additional explanations, give advice, or help troubleshoot any problems you might run into.