I rebuilt the Auth0 Activity Page with webhooks and Tinybird

If you know, you grow. I rebuilt the Auth0 activity page with added features so I can learn more about my user growth.

I rebuilt the Auth0 Activity Page with webhooks and Tinybird

I cloned the Auth0 activity page - and made it better - by connecting the Auth0 logs to Tinybird and sprinkling on some LLM magic.

This is how I did it.

Connect Auth0 to Tinybird

Auth0 webhooks let you send Auth0 log streams to any HTTP endpoint that accepts a POST request, meaning you can synchronize events like logins, signups, etc. with external systems and learn a lot about your product usage.

I started by connecting Auth0 logs to Tinybird.

One nice thing about Auth0 is you can backfill one month of data from the webhook. I don't know of any other service that provides this with webhooks, and it gave me a nice starting point.

A screenshot of Auth0 log stream configuration
Selecting backfill data from the Auth0 log stream

The Data Infrastructure

One could write a book about real-time data infrastructure, but the work I had to do fits on a PostIt note. I just put a Tinybird URL in the Auth0 webhook settings and I was ready to go.

Tinybird's Events API is an HTTP streaming endpoint that receives JSON payloads and writes them to an OLAP database. A piece of middleware (at Tinybird, we internally call it "The Gatherer") buffers and compacts data optimizing for high throughput and preventing data loss.

Once I had some data in Tinybird, I needed to learn about the events schemas. Auth0 logs consist of at least 139 different JSON schemas, which made this seem a bit overwhelming at first.

I did two things:

  1. Used the JSON type column in my Tinybird Data Source for the Auth0 log events, together with a String event_type column and a timestamp column, so they can be properly used for filtering and/or indexing.

    I might eventually need to unnest the JSON columns, but I'm not sure about it for now.
  1. Educated an LLM about the semi-structured schema of the Auth0 logs. I use Cursor and AnthropicAI's claude-sonnet, and if I wanted them to help write SQL I could just expect them to work with an unstructured event JSON column without knowing its schema.

So once I had collected some data, I got one sample event of each type and used it as context for the LLM.

I fed this sample data to the LLM to teach it about the schema of each event_type, the nested data types, and even possible relations and insights.

Building the Dashboard

To build the dashboard, Cursor suggested this stack:

  • Tinybird for the data infrastructure and backend
  • NextJS as a frontend framework
  • Vercel for deployment
  • RadixUI and recharts for the UI components

I used Cursor to build a single component end to end, from the data layer to the application, all in a few minutes.

This is how I added the Daily Active Users (DAUs) trend, for example:

  1. Created a Tinybird Pipe that returns the time series data containing dates and DAUs:
  1. Created a Next.js component that renders the chart => source here
  2. Created a small Tinybird TypeScript library to request the API endpoint: 
  1. Created the React hook to fetch the data and pass it to the component.

After a bit of back and forth with Cursor, I glued together a working version of my first card, end-to-end.

My local development environment consists of npm + the Tinybird CLI connected to a remote Tinybird branch. Both are well integrated locally and remotely with git for CI/CD using environment variables, Tinybird branches, and Vercel previews.

Cloning the whole Auth0 Activity Dashboard

Following the same workflow above, I used Cursor to build Pipes and components for:

  • Total event counters
  • Daily signups
  • Daily login failures

This doesn't really provide anything beyond what you might already get in Auth0, but it’s trivial to set up, and you can easily extend it to look at new things that Auth0 doesn't give you...

Beyond the basics

Once I had the basic dashboard, I started thinking about new features I wanted. Adding them to my prototype was easy. There are, in fact, a bunch of insights hidden in the Auth0 logs but not exposed via the activity page that I find critical to understanding product usage.

My Auth0 logs are multi-tenant, so I wanted to add a tenant_name parameter to the dashboard to filter the results by different tenants. Same for application and connection names: 

Simple dashboard dropdown components for filtering Auth0 metrics by tenant, application, and connection
The frontend components for the dashboard filters by tenant, application, and connection

I also wanted to add hourly, daily, and monthly aggregations and a time range selector.

Simple dashboard components for filtering Auth0 metrics by date range and defining different time range groupings
The frontend components for the dashboard time range selector and time groupings

To do that, I updated the Tinybird Pipe for daily active users with some query params and added logic:

I used React hooks to request the Endpoints with new parameters when the selections change, and then update the UI.

Then I could filter all the dashboard panels by date range, tenant, application, or connection and aggregate the trends by hour, day, or month.

A clone of the Auth0 Activity Page dashboard
The Auth0 Activity Page clone, but with better filtering

There’s even more gold hidden in the Auth0 logs (remember there are at least 139 different event types…). I continued building my data layer with other insights:

  • cumulative count of signups
  • top browsers
  • top devices
  • top authentication methods
  • cohorts analysis
  • suspicious logins
  • Organizations with more active users
  • Churned users, etc.

You can find some example components and Pipe definitions in the Tinynest repo.

Auth0 also allows for SAML and OIDC authentication, so I even built a Pipe and component to filter logs for specific SAML tenants and provide an audit log dashboard for each of them. So, I could even expose this data to my users to help them debug auth events.

An example filterable logs table from Auth0
The Auth0 log events table that can be filted by SAML tenant, for example

What else?

I'm not a frontend developer. I'm more of a backend developer and data engineer, so the code and design generated by Cursor and sonnet are not perfect and need humans to improve it (or just rebuild it from scratch).

But the nice thing is that this workflow - build a simple Next.js app with Tinybird for analytics - allows me to develop the data layer and the frontend together and validate a working prototype dashboard from end to end. I can iterate, test, and integrate both pieces together without having to context-switch, using an integrated data + web stack that gives me a workflow I'm comfortable with. The Tinybird data layer is declarative and does not require further development (well, maybe tests would be good xD).

With added LLM and AI assistant superpowers, I can move really fast (I built this entire dashboard in less than a day).

By the way, all the code for this Auth0 dashboard is public as a part of the Tinynest project. You can check it out here.

The full project includes dashboards not just for Auth0, but for many other common dev stack tools like Vercel, Stripe, GitHub, Sentry, Resend, Clerk, and more.

If you are interested in how the data layer is built, you can check the Tinybird data project configuration here.

Want to start doing this yourself? Fork the project, configure your Auth0 tenant to use the webhook, and start sending logs to Tinybird. You'll have my dashboard pre-built, and you can take it as far as you want.