Connect

React

Typed hooks on published cloud datasets, with each customer seeing only their own rows.

hypequery cloud is not live yet

You can't sign up for or deploy to cloud today. These pages describe the planned service, and details will change before launch. What runs today is the open-source TypeScript and Python SDKs, in your own backend.

Once your datasets are published to hypequery cloud, a React app can query them with typed hooks. You don't write route config or types by hand, and you don't need a server proxy. A React app built with @hypequery/react against self-hosted Serve works the same way: cloud's dataset endpoints return the same data, metadata, and errors as Serve. For the full hooks guide, see Connect: React.

Generate the client from the live release

npm install @hypequery/react @tanstack/react-query
npx hypequery login            # once per machine: picks the project and environment
npx hypequery generate:client --cloud --output src/hypequery-client.ts

This writes:

  • ClientApi: the types of every published dataset.
  • clientManifest: each dataset's route and schema hash.
  • clientBaseUrl: where the environment is served, such as https://acme-production.hypequery.app.

Commit the file. To keep it current:

  • hypequery deploy analytics/cloud.ts --client src/hypequery-client.ts regenerates it every time you publish.
  • npx hypequery generate:client --cloud --output src/hypequery-client.ts --check fails CI when it has drifted.

Give each signed-in user their own client

// src/analytics.tsx
import { useMemo, type ReactNode } from 'react';
import { createAnalyticsHooks, createHypequeryClient, HypequeryProvider } from '@hypequery/react';
import { clientBaseUrl, clientManifest, type ClientApi } from './hypequery-client';

// Hooks without a fixed client read the one HypequeryProvider supplies.
export const { useDataset } = createAnalyticsHooks<ClientApi>();

export function AnalyticsProvider({ userId, children }: { userId: string; children: ReactNode }) {
  const client = useMemo(
    () => createHypequeryClient<ClientApi>({
      baseUrl: clientBaseUrl,
      manifest: clientManifest,
      token: () => getUserToken(),
    }),
    [userId],
  );
  // Keyed by user: signing in as someone else starts an empty cache.
  return <HypequeryProvider key={userId} client={client}>{children}</HypequeryProvider>;
}

Render AnalyticsProvider inside your sign-in boundary, with the signed-in user's ID. Cached results belong to one client, so one user never sees another's rows after switching accounts without a reload.

getUserToken returns a short-lived end-user token. Never put an API key (hqgw_…) in browser code: Cloud answers browsers only for end-user tokens. The token is one of:

  • Your own JWT (Clerk, Auth0, Supabase, Cognito or any JWKS issuer). Register the issuer for the environment and name the claim that holds the customer ID. The browser then sends the token your auth provider already gives it, with no backend code.
  • A hypequery token minted by your backend. Your server checks who is signed in, then calls POST https://<environment>.hypequery.app/embed/tokens with a server API key and { "subject", "tenantId", "permissionSet" }, and returns the token. The customer must be registered in the environment's tenant registry.

Either way, the customer comes from the signed token, so a user only ever sees their own customer's rows. Add your app's origin to the environment's allowed origins (http://localhost:3000 for development).

Query

import { useDataset } from './analytics';

export function RevenueByCountry() {
  const { data, error, isLoading } = useDataset('orders', {
    dimensions: ['country'],
    measures: ['revenue'],
  });
  if (isLoading) return <p>Loading…</p>;
  if (error) return <p>{error.message}</p>;
  return <pre>{JSON.stringify(data?.data, null, 2)}</pre>;
}

Dataset names, dimensions and measures type-check against the live release.

When the model changes

Each request carries the schema hash its endpoint was generated from. If a publish changes an endpoint, Cloud refuses requests from the old client with 409 CLIENT_SCHEMA_CHANGED, and the hook's error is a ClientSchemaChangedError, which is still an HttpError. Regenerate the client, review the type errors, and redeploy your app:

import { ClientSchemaChangedError } from '@hypequery/react';

if (error instanceof ClientSchemaChangedError) {
  // Ship a build with a regenerated client; retrying won't help.
}

generate:client --cloud and the 409 check need a Cloud release that serves client contracts. If yours doesn't yet, the command says so and writes nothing.

generate:client only overwrites files it generated, and refuses a release whose datasets are served under a path prefix. That happens when a dataset path collides with a reserved Cloud path such as /mcp; rename the path and deploy again.

Hand it to your coding agent

Paste this into Claude Code, Cursor or another coding agent in your app's repo:

Connect this React app to our hypequery Cloud datasets.
1. Install @hypequery/react and @tanstack/react-query.
2. Run `npx hypequery generate:client --cloud --output src/hypequery-client.ts`
   (run `npx hypequery login` first if it asks). Don't edit the generated file.
3. Create src/analytics.tsx: export useDataset from createAnalyticsHooks<ClientApi>() with no config,
   and an AnalyticsProvider that builds createHypequeryClient<ClientApi>({ baseUrl: clientBaseUrl,
   manifest: clientManifest, token: () => getUserToken() }) per signed-in user and renders
   <HypequeryProvider key={userId} client={client}>, so switching accounts never reuses cached rows.
4. getUserToken must return the signed-in user's end-user token: our auth provider's JWT if
   hypequery Cloud is set up to trust it, otherwise a token our backend mints from
   POST <clientBaseUrl>/embed/tokens with a server API key. Never put an hqgw_ key in browser code.
5. Render AnalyticsProvider inside the sign-in boundary and replace one chart with useDataset to prove it works.
6. Add `npx hypequery generate:client --cloud --output src/hypequery-client.ts --check` to CI.

Or proxy through your server

If your app has no end-user tokens, keep a server API key out of the browser instead: add a same-origin route in your app that forwards requests to cloud with the key, and point the React client at that route.

'use client';

import { createHooks, createHypequeryClient, HypequeryProvider } from '@hypequery/react';
import type { ReactNode } from 'react';

// The API explorer generates these types for each endpoint.
type AnalyticsApi = {
  orders: {
    input: { dimensions?: string[]; measures?: string[]; limit?: number };
    output: { data: Array<Record<string, string | null>> };
  };
};

const client = createHypequeryClient<AnalyticsApi>({
  // Same-origin route; your server adds the cloud API key.
  baseUrl: '/api/analytics',
  manifest: {
    orders: { method: 'POST', path: 'datasets/orders/query' },
  },
});

export const { useQuery } = createHooks<AnalyticsApi>();

export function AnalyticsProvider({ children }: { children: ReactNode }) {
  return <HypequeryProvider client={client}>{children}</HypequeryProvider>;
}

The server route is also where you set x-hypequery-tenant-id for the signed-in user, using a trusted backend key.

Route paths

Write manifest paths without a leading slash, for example datasets/orders/query. The client resolves each path against baseUrl, and a path starting with / replaces the base URL's own path, dropping the cloud gateway prefix.

The API explorer generates a ready-made React snippet for each endpoint.

On this page

Get early access to hypequery cloud.

Cloud hosts the same model you run in your backend, with a managed API and MCP server, versions, and rollback. We're letting teams in a few at a time. Join the waitlist and we'll reach out when your project can go live.

How do you want to build your analytics layer? (Optional)
What features do you most need? (Optional)

Pick as many as you like.

Only your email is required. All other questions are optional.