How to build a live telemetry tracker using decoupled React components, atomic PostgreSQL upserts, and non-blocking Next.js API routes to prevent CLI race conditions.
reactnextjsdrizzle-ormdatabaseWhen building the component registry for this portfolio, I wanted a way to track how many times a component was installed via the CLI (
npx shadcn add).While standard web applications often just render a raw metric string (e.g.,
10,420), I wanted something that felt more tactile and hardware-inspired. By segmenting the digits into distinct monospaced blocks, we create a highly legible, aesthetic counter that feels right at home on an engineering dashboard.But building a live counter isn't just about CSS. We have to solve a few structural problems:
- Separation of Concerns: The UI component itself must remain pure and stateless so it can be easily distributed.
- Concurrency: If a popular component drops, hundreds of developers might run the CLI command simultaneously. We need to prevent database race conditions.
- Performance: Tracking telemetry shouldn't slow down the actual CLI download speed for the end user.
Here is how I engineered the full stack architecture using React, Next.js Server Actions, and Drizzle ORM.
1. The Pure UI Component
Following the Shadcn philosophy, we start by building a completely isolated, stateless UI component. It doesn't know anything about databases or server fetching.
It simply accepts a
value prop, pads it with leading zeros to maintain a consistent width (e.g., 00420), and maps over each digit to render it inside a dedicated tile.// src/components/ui/download-counter.tsx
'use client'
import * as React from 'react'
import { cn } from '@/utils/utils'
export interface DownloadCounterProps extends React.HTMLAttributes<HTMLDivElement> {
value: number
padLength?: number
}
/**
* Renders a stylized digital counter, padding the provided value with leading zeros.
*/
export function DownloadCounter({
value,
padLength = 5,
className,
...props
}: DownloadCounterProps) {
const displayCount = (value ?? 0).toString().padStart(padLength, '0')
return (
<div
className={cn('flex items-center gap-1 sm:gap-1.5', className)}
{...props}
>
{displayCount.split('').map((digit, i) => (
<span
key={i}
className="flex h-10 w-8 items-center justify-center rounded-md bg-muted/50 font-mono text-lg font-medium tracking-tight text-foreground"
>
{digit}
</span>
))}
</div>
)
}
Because it's decoupled, you can use it anywhere immediately with static data:
<DownloadCounter value={420} padLength={5} />2. Telemetry Database Schema
To make the counter live, we need a place to store the metrics. We create a minimalist PostgreSQL table that tracks the total
installs for each unique component slug.// src/lib/db/schema.ts
import { pgTable, varchar, integer } from 'drizzle-orm/pg-core'
export const component_metrics = pgTable('component_metrics', {
slug: varchar('slug', { length: 255 }).primaryKey(),
installs: integer('installs').default(0).notNull(),
})
3. Atomic Server Actions
Next, we need a secure way to interface with the database. We write two Next.js Server Actions: one to fetch the data for the UI, and one to increment the data when a CLI installation occurs.
The increment action is where things get interesting. If we run a standard
SELECT followed by an UPDATE count + 1, we run the risk of a race condition. If two users install the component at the exact same millisecond, they might both read 10, and both write 11, effectively losing a metric.To solve this, we rely on Drizzle's
onConflictDoUpdate to perform an Atomic Upsert. We push the math down to the PostgreSQL engine itself, ensuring the increment is perfectly transactional.// src/lib/actions/views.ts
'use server'
import { db } from '@/lib/db/drizzle'
import { component_metrics } from '@/lib/db/schema'
import { eq, sql } from 'drizzle-orm'
// Fetches the live count for the UI
export async function getInstallsAction(slug: string) {
if (!slug) return { installs: null }
try {
const [result] = await db
.select({ installs: component_metrics.installs })
.from(component_metrics)
.where(eq(component_metrics.slug, slug))
return { installs: result?.installs ?? 0 }
} catch (error) {
return { installs: null }
}
}
// Atomically increments the count during an installation
export async function incrementInstallAction(slug: string) {
if (!slug) return { installs: null }
try {
const [result] = await db
.insert(component_metrics)
.values({ slug, installs: 1 })
.onConflictDoUpdate({
target: component_metrics.slug,
set: { installs: sql`${component_metrics.installs} + 1` }, // Atomic increment
})
.returning({ installs: component_metrics.installs })
return { installs: result?.installs ?? 0 }
} catch (error) {
return { installs: null }
}
}
4. Hydration & The Frontend Wrapper
Now we need to bridge the server and the client. We build a React client component that mounts, fires off the
getInstallsAction, and handles the loading state.While waiting for the network response, we return a smooth
animate-pulse skeleton. Once the database integer arrives, we pass it into our pure DownloadCounter UI.// src/components/live-counter.tsx
'use client'
import { useEffect, useState } from 'react'
import { DownloadCounter } from '@/components/ui/download-counter'
import { getInstallsAction } from '@/lib/actions/views'
export function LiveCounter({ slug }: { slug: string }) {
const [installs, setInstalls] = useState<number | undefined>(undefined)
useEffect(() => {
getInstallsAction(slug).then(res => {
if (res.installs !== null) setInstalls(res.installs)
})
}, [slug])
if (installs === undefined) {
return <div className="h-10 w-48 animate-pulse rounded-md bg-muted" />
}
return <DownloadCounter value={installs} />
}
5. Non-Blocking API Triggers
Finally, we need to actually trigger the
incrementInstallAction whenever someone uses the CLI.In our Next.js API route that serves the component JSON payload, we invoke the server action, but we do not await it. By using
.catch() instead of await, we create a "fire-and-forget" telemetry ping. The CLI payload is returned to the user instantly, while the database upsert happens silently in the background.// src/app/r/[slug]/route.ts
import { incrementInstallAction } from '@/lib/actions/views'
import { NextResponse } from 'next/server'
export async function GET(
request: Request,
{ params }: { params: { slug: string } }
) {
// Fire and forget the telemetry tracker (non-blocking)
incrementInstallAction(params.slug).catch(console.error)
// Return the component JSON payload instantly
return NextResponse.json({ ...registryPayload })
}
By decoupling the UI from the database logic, utilizing atomic upserts to prevent race conditions, and leveraging non-blocking API triggers, we've built an extremely robust, edge-ready metrics system that scales effortlessly.