Skip to main content
This example builds a dashboard in Next.js that shows one count card and one chart. A Next.js route on the server holds the API key and calls the Query API. The browser polls that route at an interval that stays inside the rate limit of the workspace. The Query API needs the Starter plan or higher and an API key with the Query API permission. Read Query API.

Files

Create the project and install the chart library.
Put the tenant alias and the API key in .env.local. Do not add a NEXT_PUBLIC_ prefix to the key. A NEXT_PUBLIC_ variable is compiled into the browser bundle.

The API client

The client wraps the three endpoints. On a status code other than 2xx, it throws a GrainApiError that carries the status code and the Retry-After value.

The route

The route makes two Query API calls per refresh: one count and one query of up to 1,000 events. It keeps the last result in memory for CACHE_MS milliseconds. Every browser that opens the dashboard inside that window gets the cached result, so the number of viewers does not change the number of Query API calls.
A request to the route returns the count, the events, and the range.

The count card

The chart

The chart groups the events by eventDate and shows one point per day of the range.

The page

The page polls /api/metrics. If the route answers 429, the page waits for the number of seconds in Retry-After before the next poll. The poll interval and the route cache use the same number, so a poll inside the cache window costs no Query API call.

The poll interval

The rate limit counts per workspace, not per viewer: 120 requests per minute, on every plan. One refresh of this dashboard costs 2 Query API requests, so the limit permits a refresh every second. The route cache decides the real cost. The default of 900 seconds costs 192 requests a day and leaves the limit free for other clients of the workspace. Set NEXT_PUBLIC_DASHBOARD_REFRESH_SECONDS to the same value, so the browser does not poll more often than the cache refreshes. A refresh that a user triggers by hand costs the same 2 requests and must count against the same budget.

Errors

Limits

Deployment

  1. Run npm run build, then deploy with vercel.
  2. Set GRAIN_TENANT_ID, GRAIN_API_KEY, DASHBOARD_REFRESH_SECONDS, and NEXT_PUBLIC_DASHBOARD_REFRESH_SECONDS in the environment of the host.
  3. If the host runs more than one instance, each instance holds its own cache and makes its own requests. Move the cache to a shared store when many instances run.
  4. Put the dashboard behind your own authentication. The route answers any caller.
Read Data export for a script that pages through every event. Read Filters for the filterSet operators.