Upstash Integration with Next.js

upstash.com

Upstash Redis + Next.js = scalable web features without backend complexity.

This project showcases how I integrated Upstash into my personal website, sandimaulanajuhana.com, to create a fast, lightweight, and serverless page view counter — optimized for edge runtime and minimal cost.

⚙️ Use Case: Realtime Page View Counter

When a page is visited:

  1. A POST request to /api/views/[slug] increments the view counter in Redis.
  2. A GET request fetches the current number of views.
  3. The number is shown live using a React component.

API Route Example

// /api/views/[slug]/route.ts
import { redis } from '@/lib/redis'
import { NextRequest, NextResponse } from 'next/server'

export async function POST(request: NextRequest) {
  const { pathname } = new URL(request.url)
  const slug = pathname.split('/').pop()
  await redis.incr(`views:${slug}`)
  return NextResponse.json({ success: true })
}

export async function GET(request: NextRequest) {
  const { pathname } = new URL(request.url)
  const slug = pathname.split('/').pop()
  const views = await redis.get<number>(`views:${slug}`)
  return NextResponse.json({ views: views ?? 0 })
}

React Component

components/ViewCounter

'use client'

import { useEffect, useState, useRef } from 'react'

type ViewCounterProps = {
  slug: string
  increment?: boolean
  silent?: boolean
}

export default function ViewCounter({
  slug,
  increment = true,
  silent = false,
}: ViewCounterProps) {
  const [views, setViews] = useState<number | null>(null)
  const hasPosted = useRef(false)

  useEffect(() => {
    if (increment && !hasPosted.current) {
      hasPosted.current = true
      fetch(`/api/views/${slug}`, { method: 'POST' }).catch(console.error)
    }

    fetch(`/api/views/${slug}`)
      .then((res) => res.json())
      .then((data) => setViews(data.views))
      .catch(console.error)
  }, [slug, increment])

  if (views === null || silent) return null

  return (
    <span className="ml-3 text-emerald-500 dark:text-emerald-500">
      📖 {views.toLocaleString()} Reads
    </span>
  )
}

🚀 Why Upstash? ⚡ Ultra fast — Redis in-memory speed

🌍 Edge-ready for global low-latency

💸 Serverless pricing — great for solo developers

🧘 Stateless integration — works cleanly with App Router routes

🧪 Experimental Add-on: Telegram Bot Notifications I extended the counter with a Telegram bot that sends:

Article slug

Device type

IP & location (via Vercel Analytics)

Timestamp

Rate-limited by IP & time window to prevent spam.

📘 Related Article
👉 Counting Page Views with Upstash Redis in a Next.js App Router Project

This project is part of a larger effort to explore practical, scalable solutions using serverless tech — and Redis is one of my favorite tools to build lightweight features without backend overhead.