BetterConvex

Best-in-class stack

tRPC + TanStack Query + Better Auth

What's included

cRPC

tRPC, ported to Convex. AI-ready.

Real-time native

WebSocket subscriptions flow directly into TanStack Query cache. No extra setup.

TanStack Query native

useQuery, useMutation, useInfiniteQuery. All the patterns you know, with real-time updates.

Relationships built-in

Ents gives you relations, fluent queries, and ctx.table(). No more manual joins.

Auth that works

Better Auth integration with session management, route guards, and lifecycle hooks.

RSC ready

Fire-and-forget prefetch or awaited preloading. Hydration included.

Simple to use

It's quick and easy to build a typesafe API with Better Convex.

1

Define your procedures

Chain .input(), .output(), .query() to build type-safe procedures.

// convex/functions/greeting.ts
export const greeting = publicQuery
  .input(z.object({ name: z.string() }))
  .output(z.string())
  .query(async ({ input }) => {
    return `Hello ${input.name}`;
  });
2

Create your client

Bridge Convex with TanStack Query. The useCRPC hook gives you a typed proxy to all your procedures.

// src/lib/convex/crpc.tsx
import { api } from '@convex/_generated/api';
import { meta } from '@convex/meta';
import { createCRPCContext } from 'better-convex/react';

export const { useCRPC } = createCRPCContext(api, meta);
3

Connect and start querying!

Full TypeScript autocompletion from server to client. Queries subscribe to real-time updates via WebSocket.

// app/page.tsx
const crpc = useCRPC();

const { data } = useQuery(
  crpc.greeting.queryOptions({ name: 'World' })
);

// Mutations work the same way
const create = useMutation(crpc.posts.create.mutationOptions());
create.mutate({ title: 'Hello' });