tanstack-table
$
npx mdskill add EpicenterHQ/epicenter/tanstack-tableEnables Svelte data table UI state with TanStack Table patterns
- Solves UI state management for dynamic Svelte data tables
- Uses @tanstack/svelte-table, @tanstack/table-core, and @epicenter/ui/table
- Applies sorting, filtering, pagination, and row identity logic
- Delivers reusable table components with stable rendering and state
SKILL.md
.github/skills/tanstack-tableView on GitHub ↗
---
name: tanstack-table
description: TanStack Table UI state patterns for @tanstack/svelte-table, @tanstack/table-core, createTable, ColumnDef, FlexRender, renderComponent, sorting, filtering, pagination, row identity, and @epicenter/ui/table composition. Use when building or reviewing Svelte data tables, not Epicenter workspace storage tables.
metadata:
author: epicenter
version: '1.0'
---
# TanStack Table
## Reference Repositories
- [TanStack Table](https://github.com/TanStack/table) - Headless table state and row models
- [Svelte](https://github.com/sveltejs/svelte) - Svelte 5 component and reactivity model
## Upstream Grounding
When TanStack Table adapter APIs, row models, controlled state, sorting, filtering, pagination, or Svelte rendering helpers affect correctness, ask DeepWiki a narrow question against `TanStack/table`. Verify against the installed `@tanstack/svelte-table` and `@tanstack/table-core` versions.
This skill is for UI table state. Use `workspace-api` for Epicenter CRDT table storage and migrations.
## Local API Baseline
Epicenter currently uses `@tanstack/svelte-table` with:
```typescript
import {
createTable as createSvelteTable,
FlexRender,
renderComponent,
} from '@tanstack/svelte-table';
import type { ColumnDef } from '@tanstack/table-core';
```
## Table Construction Rules
- Always set `getRowId` for persisted or local-first rows. Do not rely on array index identity.
- Keep `data` referentially stable. Avoid creating a fresh array in the table options getter unless the table is intentionally rebuilt.
- Define columns with `satisfies ColumnDef<Row>[]`.
- Give accessor columns stable ids, especially when sorting, hiding, or persisted preferences are involved.
- Use `renderComponent` for reusable header and cell components.
- Include only row models the UI uses: core always, sorted/filter/pagination only when the surface needs them.
## Controlled State
- Control only state Epicenter owns externally, such as sorting, global filter, column visibility, row selection, or pagination.
- If an `onXChange` handler is present, the matching `state.get x()` must also be present.
- Keep state ownership in one component or handle. Do not split sorting, filters, and pagination across unrelated stores without a reason.
## Rendering
- TanStack Table owns row, column, and cell state. `@epicenter/ui/table` owns semantic table markup and styling.
- Render headers and cells with `FlexRender`.
- Key rows by `row.id` and cells by `cell.id`.
- Empty states stay in `epicenter-ui`: when row count is zero, render `Empty.Root` in the table body or surrounding panel.
- Add explicit keyboard behavior for clickable rows. A click handler alone is not a row interaction model.
- Use TanStack Virtual separately for large lists. Do not treat virtualization as a built-in table feature.
More from EpicenterHQ/epicenter
- agent-goalWrite `/goal` prompts for long-running agent work in Codex or Claude Code. Use for slash goal, agent goal, durable objective, autonomous coding run.
- approachability-auditReview code as a new TypeScript developer. Use when code feels indirect, clever, hard to follow, or needs a pass on abstractions, names, first-read clarity.
- arktypeArktype: runtime validation, discriminated unions with .merge()/.or(), spread keys. Use when mentioning arktype, type(), union types, command/event schemas.
- attach-primitiveContract and invariants for `attach*` composition primitives in `packages/workspace` (side-effectful building blocks like attachIndexedDb, attachSqlite, attachBroadcastChannel, attachEncryption, attachTable, openCollaboration), and when to use `create*` (pure construction) instead. Use when writing or reviewing an `attach*` or `create*` function, naming a new workspace primitive, composing inside a workspace builder, or deciding whether a primitive registers listeners at call time.
- authEpicenter auth packages: `@epicenter/auth`, `@epicenter/auth-svelte`, OAuth sessions, identity state, auth-owned fetch/WebSocket, and workspace lifecycle binding. Use when editing Epicenter auth clients, session state, hosted sign-in, or auth/workspace integration.
- autumnAutumn billing in Epicenter: `autumn.config.ts`, `autumn-js` credit checks, `atmn` CLI, plan gates, and metered AI usage. Use when changing billing, pricing, credits, plan access, refunds, or usage events.
- better-auth-best-practicesBetter Auth server/client setup: `auth.ts`, generated schema, DB adapters, sessions, cookies, env vars, and plugins. Use when mentioning Better Auth, betterauth, auth handlers, OAuth, email/password, or session configuration.
- better-auth-security-best-practicesBetter Auth security hardening: rate limits, secrets, CSRF, trusted origins, cookies, sessions, OAuth tokens, and audit logging. Use when reviewing auth security, brute-force protection, token handling, or deployment safety.
- change-proposalPresent proposed code changes visually before implementing. Use when: "show me options", "compare approaches", "what should we do", or when changes need before/after comparison.
- claude-code-consultUse this skill when the user asks to consult Claude, ask Claude Code, get another model's take, run a taste check, find cleaner options, or prepare a Claude prompt. Create a bounded second-opinion prompt or run a read-only Claude Code consult, then verify Claude's claims against local files.