Better Tables

Better Tables

Type-safe tables from your database schema to React UI — filtering, sorting, pagination, and URL state included.

Better Tables builds both halves of a data table from one definition: define your columns once in TypeScript, let an adapter turn filter, sort, and page state into real queries, and render with React components you own.

Packages

PackageRoleDistribution
@better-tables/coreColumn builders, managers, adapter contractsnpm
@better-tables/adapters-drizzleDrizzle query generation (Postgres / MySQL / SQLite)npm
@better-tables/uiReact table & filter componentsCLI copy (private)
@better-tables/clibetter-tables init — copies UI into your appnpm

Data flow: defineTable() column definitions → adapter executes queries → UI renders and manages client state, optionally synced to the URL.

import { betterTables, defineTable } from '@better-tables/core';
import { drizzleAdapter } from '@better-tables/adapters-drizzle';

export const tables = betterTables({
  database: drizzleAdapter(db),
  defaults: { pageSize: 20 },
});

export const ticketsTable = defineTable<typeof tables>()('tickets', (t) => ({
  columns: [
    t.text('subject').searchable().filterable().sortable(),
    t.option('status').options([{ value: 'open', label: 'Open' }]).filterable(),
  ],
}));

const result = await tables.fetchData(ticketsTable, {
  pagination: { page: 1, limit: 20 },
});

AI-friendly docs

On this page