BetterConvex
Best-in-class stack
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.
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}`;
});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);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' });