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 your plan. The Query API needs the Builder 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

Rate limits count per API key, not per viewer. One refresh of this dashboard costs 2 Query API requests. The interval must satisfy both limits of the plan:
  • Minute rule: interval >= 60 seconds * 2 / requests per minute.
  • Day rule: interval >= 86,400 seconds * 2 / requests per day.
The larger result wins. On every plan the day rule wins. 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. Divide the budget by the number of instances, or move the cache to a shared store.
  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.