Migrate from svelte-headless-table to Simple Table for Svelte
A practical migration guide from svelte-headless-table to Simple Table for Svelte. Trade headless table primitives for batteries-included virtualization, pinning, grouping, and editing.
svelte-headless-table is a popular headless table builder—you compose plugins (sort, filter, group, paginate) and write the HTML yourself. It's powerful but you own all the wiring: virtualization, pinning, themes, accessibility.
Simple Table for Svelte is an MIT-licensed Svelte 4 / Svelte 5 data grid that ships virtualization for 1M+ rows, column pinning, row grouping with aggregations, and inline editing in the box.
This guide shows how to swap an existing svelte-headless-table view for @simple-table/svelte when your headless setup has grown more complex than you wanted.
Why migrate
- You want a working grid in 5 minutes, not a half-day of plugin wiring.
- You need real virtualization for 100k+ rows without integrating a separate virtual list.
- You want column pinning, grouping with aggregations, and inline editing as built-in primitives.
- You ship Svelte 5 with runes and want a component that aligns with that reactivity model.
Prerequisites
- SvelteKit / Svelte 4 or Svelte 5 project.
- Simple Table for Svelte installed: npm install @simple-table/svelte.
Install
npm install @simple-table/svelteAPI mapping cheat sheet
| svelte-headless-table | Simple Table for Svelte | Notes |
|---|---|---|
createTable + writable store | $state with default headers + rows | Reactivity via runes (Svelte 5) or stores (Svelte 4). |
table.column({ accessor, header }) | HeaderObject (accessor, label, width) | Same fields, declared on a plain object. |
addSortBy / addColumnFilters plugins | Built-in sort + filter | No plugin wiring needed. |
addGroupedRows | Built-in row grouping + aggregations | Configure via HeaderObject + props. |
Custom HTML composition | <SimpleTable /> + cell renderer components | Pass renderers for custom cells/headers. |
Bring-your-own virtualization | Built-in (set height) | Row + column virtualization for 1M+ rows. |
Step-by-step migration
Install Simple Table for Svelte
Add @simple-table/svelte and its stylesheet. Remove svelte-headless-table once you've migrated all consumers.
npm install @simple-table/svelte npm uninstall svelte-headless-table // app.html or a global CSS file import "@simple-table/svelte/styles.css";Convert columns
Replace
table.column({ accessor, header })calls with HeaderObject entries containing accessor + label + width.Replace stores with $state or stores
In Svelte 5, use
$state. In Svelte 4, keep using a writable store and pass it to:rows.Drop the plugin pipeline
Sort, filter, paginate, and group are built in—remove addSortBy / addPagination / addGroupedRows plugin code.
Move custom HTML to renderers
Anywhere you used
<Render of=… />with custom JSX-ish projection, pass a Svelte component via HeaderObject.cellRenderer.
Gotchas
- Less low-level control
- You give up DOM-level control over <table>, <tr>, <td>. In return you get virtualization and pinning that's tedious to build by hand.
- Plugin parity
- Most plugin features map 1:1 onto Simple Table props. The exception is exotic plugin compositions—open an issue if you have one and we'll point you at the equivalent prop.
FAQ
- Is Simple Table compatible with Svelte 5 runes?
- Yes. @simple-table/svelte exposes idiomatic props that work with $state, $derived, and SvelteKit's data-loading patterns.
- Can I keep svelte-headless-table for some views?
- Yes. They can coexist during a migration. Remove svelte-headless-table once the last consumer is gone.