# tablecn: a shadcn/ui data table with server-side state and PartyKit collaboration

> tablecn packages the shadcn/ui data table and data grid patterns into a Next.js reference app, with TanStack Table for the grid, Drizzle and PostgreSQL on the server, and PartyKit for multiplayer. It is a clone-and-run starting point rather than an npm package.

**sadmann7/tablecn** — Data table and data grid components built with shadcn/ui, featuring sorting, filtering, pagination, infinite scrolling, and real-time collaboration.

- Repository: https://github.com/sadmann7/tablecn
- Website: https://tablecn.com
- Stars: 6,294 · Forks: 559
- Language: TypeScript
- License: MIT
- Published: 2026-09-22 · Updated: 2026-09-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/sadmann7-tablecn

## What tablecn solves for shadcn/ui data tables

The shadcn/ui data table example is a client-side pattern. It sorts and filters rows already in the browser, and its own documentation notes that for larger datasets you should move pagination and sorting to the server. That gap is where tablecn sits. The README lists server-side pagination, sorting and filtering as the first feature, alongside customizable columns, filters generated from column definitions, Notion and Airtable style advanced filtering, a Linear style filter menu for command palette filtering, an action bar on row selection, infinite scrolling with virtualization, and real-time collaboration.

The audience is narrow but real: teams already committed to shadcn/ui and Tailwind CSS who need a table that survives more rows than a browser tab should hold, and who would rather start from a working Next.js app than assemble TanStack Table, a query layer, a schema and a filter UI themselves. The repository is a private Next.js application, not a published component library. package.json has "private": true and version 0.1.0, so there is no supported npm install of tablecn itself. You copy from it, or you clone it.

## How the table, store, database and PartyKit fit together

The stack is layered, and each layer owns a different piece of state. Next.js is the framework. Tailwind CSS handles styling, shadcn/ui supplies the component primitives, and TanStack Table renders the grid. TanStack DB is listed as the reactive store, which is the layer that lets a filter change propagate without a full server round trip on every keystroke. PostgreSQL is the database, Drizzle ORM the query and schema layer, and Zod the validation layer. PartyKit provides the multiplayer channel.

The data flow implied by the README is conventional for this pattern: table state such as page index, sort and filter values is serialized into a request, the server applies it through Drizzle against PostgreSQL, and the result feeds TanStack Table. What distinguishes tablecn from a hand-rolled version is the filter generation. The README states that filters are auto generated from column definitions, which means the column metadata is the single source of truth for both rendering and the filter UI. That is a genuine design commitment: change a column definition and its filter follows, but an unusual filter also has to be expressed through the column definition rather than bolted on beside it.

The multiplayer path is separate. The party/ directory and partykit.json exist at the top level, and the README describes PartyKit as a separate deployment. Multiplayer is therefore not a mode of the main app; it is a second service the app talks to through NEXT_PUBLIC_PARTYKIT_HOST.

## Installing tablecn locally with Docker and pnpm

The README gives a quick setup path that assumes Docker and pnpm. Clone the repository and enter it first.

```bash
git clone https://github.com/sadmann7/tablecn
cd tablecn
```

Copy the environment template. The .env.example file ships working local defaults, including DATABASE_URL="postgresql://tablecn:securepassword@localhost:5432/tablecn" and NEXT_PUBLIC_PARTYKIT_HOST="localhost:1999", so the Docker path works without editing anything.

```bash
cp .env.example .env
```

Then run the setup script. According to the README this installs dependencies, starts the Docker PostgreSQL instance, pushes the schema and seeds sample data, so you should end up with a running database and a populated table.

```bash
pnpm ollie
```

The package.json scripts show what that expands to: pnpm install, then db:start, which is docker compose up -d, then db:setup, which is db:push followed by db:seed. The docker-compose.yml file pins postgres:17.4 and maps ${DATABASE_PORT} to 5432.

If you prefer to run the steps yourself, the manual path is pnpm install, then copy .env.example to .env, then start the database and push the schema.

```bash
pnpm install
cp .env.example .env
pnpm db:start
pnpm db:setup
pnpm dev
```

The dev server is the Next.js default. To exercise the collaboration feature, the README points at a separate script that runs both servers concurrently.

```bash
pnpm dev:multiplayer
```

That script is concurrently "next dev" "partykit dev", so the PartyKit dev server listens on the port referenced by NEXT_PUBLIC_PARTYKIT_HOST. If the table renders and filters apply, the setup is complete. If the page loads but rows are empty, the seed step is the first thing to check.

## Deployment splits into two services, and that is the main cost

The README points at deployment guides for Vercel, Netlify and Docker, which is the ordinary Next.js story. Multiplayer is not. The README states that the multiplayer demo uses PartyKit as a separate deployment and gives one command for it.

```bash
pnpm deploy:multiplayer
```

After deploying, you set NEXT_PUBLIC_PARTYKIT_HOST in your deployment environment variables. That single line is the whole documented deployment story for the collaboration feature, and it is where the operational cost lands. A database-backed table is one service to run. Adding collaboration makes it two, with its own host, its own environment variable and its own deploy step, and the README does not cover scaling, persistence or failure behaviour for the PartyKit side. The .env.example also lists UPLOADTHING_TOKEN and the Upstash Redis variables as optional, and marks them optional specifically for the data-grid-live variant, so those are conditional on which grid you copy rather than baseline requirements.

The practical consequence is that the multiplayer feature is the part of tablecn you should evaluate most sceptically. The single-player table is a database and a Next.js app. The collaborative table is a distributed system with a second vendor in it.

## Where tablecn is the wrong choice

The clearest limitation is distribution. tablecn is a private application, so there is no package to depend on, no semver contract and no upgrade path other than reading diffs. If your team expects to run a package manager command and receive fixes, this is the wrong shape. The registry.json and registry/ directory at the top level suggest the project does publish shadcn-style registry items, and the build script runs build:registry before next build, but the README does not document using the registry as a distribution channel, so treat that as unexplored rather than supported.

The second limitation is documentation depth. The README is short and delegates to an external documentation site. It does not document the component API, the shape of the filter objects, the schema of the seeded tables, or the protocol between the app and the PartyKit server. It also does not document rollback, migration strategy or what happens to in-flight edits when a collaborator disconnects. For a project whose selling point is a sophisticated filter UI, the absence of a written filter contract is the gap that will cost the most time.

The third is scope. This is a demonstration application with a seeded schema. Adopting it means adopting its Drizzle schema, its seed script and its assumptions about how table state is serialized. Teams with an existing query layer and an existing filter model will spend more time removing tablecn's choices than adding its UI.

## How tablecn differs from the plain shadcn/ui data table

The obvious alternative is the shadcn/ui data table example itself, which the credits section names as the source of the initial implementation. The difference is architectural rather than cosmetic. The upstream example is a client-side table: it receives rows, and sorting, filtering and pagination happen in the browser. tablecn moves that state to the server and pairs it with a real PostgreSQL schema through Drizzle, so the table can page through data it never loads in full. It also adds the filter generation from column definitions and the advanced filter UI, which the upstream example does not attempt.

The trade is weight. The upstream pattern drops into an existing app with a component copy and no backend. tablecn brings PostgreSQL, Drizzle, Zod, TanStack DB and, for collaboration, PartyKit. If your dataset fits comfortably in memory, the upstream example is the smaller commitment and the better fit. tablecn earns its complexity only when the server-side path is the point.

TanStack Table is the shared foundation in both cases, so the grid rendering itself is not the differentiator. What you are choosing between is a component and an application.

## Licence and the cost of keeping up

The repository is MIT licensed, with LICENSE.md at the top level. MIT permits commercial use, modification and redistribution provided the copyright notice and permission notice are retained. Since tablecn is a private application rather than a package, the practical question is not whether you may use it but what obligations attach to the files you copy into your own repository. The repository also credits shadcn/ui for the initial data table implementation, and shadcn/ui components carry their own upstream licences, so a copy that mixes tablecn code with shadcn/ui primitives inherits more than one notice. That is a question for your own legal review, not something this article can settle.

Maintenance is the other cost. The last push to the default branch was on 2026-09-21, and the repository is not archived. There are no retrieved releases, so there is no changelog to read and no version tags to pin against. Upgrading means diffing the repository against your fork. The check script runs oxlint, oxfmt in check mode and tsc --noEmit, which gives you a fast signal on whether a pulled change is internally consistent, but it says nothing about whether the change breaks your integration. Budget for reading source, not release notes.

## Conclusion

Adopt tablecn if you want a working shadcn/ui data table with server-side pagination, sorting, filtering and an optional PartyKit multiplayer layer, and you are willing to run a PostgreSQL instance and read the code instead of an API reference. Skip it if you need a versioned npm dependency, a documented public component API, or a path to production multiplayer that does not require operating a second deployment. Before committing, verify the documentation at diceui.com actually matches the components in src/, confirm the MIT licence in LICENSE.md covers the registry files you plan to copy, and decide whether NEXT_PUBLIC_PARTYKIT_HOST will point at a PartyKit project you are prepared to deploy and pay for.

## FAQ

### How do I install tablecn?

Clone the repository, copy .env.example to .env, and run pnpm ollie, which per the README installs dependencies, starts the Docker PostgreSQL instance, pushes the schema and seeds sample data. The manual path is pnpm install, pnpm db:start, pnpm db:setup and pnpm dev.

### Is tablecn available on npm?

No. package.json sets "private": true and the version is 0.1.0, so tablecn is not published as a dependency. The README points readers at the documentation site and the repository rather than an install command for the package itself.

### How does tablecn handle server-side pagination and filtering?

The README lists server-side pagination, sorting and filtering as the first feature, with Drizzle ORM against PostgreSQL on the server and TanStack Table rendering the result. Filters are auto generated from column definitions, so the column metadata drives both the grid and the filter UI.

### How do I run the tablecn multiplayer demo locally?

Run pnpm dev:multiplayer, which the package.json defines as concurrently running the Next.js dev server and the PartyKit dev server. The .env.example sets NEXT_PUBLIC_PARTYKIT_HOST to localhost:1999 for local development.

### What licence does tablecn use?

The repository is MIT licensed and includes LICENSE.md at the top level. Because tablecn is a private application you copy from rather than install, the notices that matter are the ones attached to the files you take.

## Sources

- [Issues](https://github.com/sadmann7/tablecn/issues)
- [License: MIT](https://github.com/sadmann7/tablecn/blob/main/LICENSE)
- [Project website](https://tablecn.com)
- [README](https://github.com/sadmann7/tablecn/blob/main/README.md)
- [sadmann7/tablecn on GitHub](https://github.com/sadmann7/tablecn)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/sadmann7-tablecn
