Enterprise getting started: a complete example
One page, one file, from an empty folder to a working grid with Excel, PDF and CSV export. Nothing is elided - every command and every line below was run end to end against the published packages.
If you already have a project, skip to step 2.
1. Create a project
npx sv create svgrid-trial --template minimal --types ts --no-add-ons
cd svgrid-trial
Those flags skip every interactive prompt, so the sequence is copy-pasteable.
For a plain Vite app instead, npm create @svgrid@latest scaffolds one with
the grid already wired in - the component below drops into either.
2. Install
npm install @svgrid/grid @svgrid/enterprise
npm install jszip pdfmake # optional peers, for Excel and PDF export
jszip and pdfmake are optional peer dependencies, lazy-loaded the first
time you actually call an export. Skip them if you only need CSV, TSV or HTML;
exportData throws a message naming the missing package if you call a format
whose peer is absent.
No build configuration is required. If you are on @svgrid/enterprise
2.5.x or earlier, see older versions below - those releases
shipped TypeScript source and needed two optimizeDeps entries in
vite.config.js.
3. The component
Replace the contents of src/routes/+page.svelte (or src/App.svelte in a
Vite project) with this. It is self-contained: licence, theme, grid and
exports, with nothing else to wire up.
<script>
import { SvGrid } from '@svgrid/grid'
import { installEnterprise } from '@svgrid/enterprise'
// One of 20 themes that ship with the package. Swap the id for material,
// nord, dracula, fluent, carbon, ag-alpine, and so on. Each carries a full
// light AND dark palette; dark activates on <html data-theme="dark">.
import '@svgrid/grid/themes/shadcn.css'
// No key while you evaluate: everything works and shows a watermark.
// After you buy, call setLicenseKey(yourKey) once, before any Enterprise
// feature runs, and the watermark goes away.
let api = $state(null)
let status = $state('')
// Capabilities are boolean props - `sortable`, `filterable`, `editable`,
// `groupable`, `pageable` - and each injects the feature it needs. For finer
// control, register features explicitly with `tableFeatures({ ... })` and
// pass them as `features`.
// Starts 'light' rather than reading the DOM, so this file is safe to render
// on the server too. The effect below syncs it once we are in the browser.
let theme = $state('light')
$effect(() => {
const saved = localStorage.getItem('theme')
if (saved) theme = saved
})
$effect(() => {
document.documentElement.dataset.theme = theme
try {
localStorage.setItem('theme', theme)
} catch (e) {
// Private mode / storage disabled. The toggle still works for this tab.
}
})
// Your data. Swap for a fetch() in onMount, a load function, or props.
let rows = $state([
{ id: 1, name: 'Ada Lovelace', team: 'Engineering', salary: 145000, active: true },
{ id: 2, name: 'Alan Turing', team: 'Research', salary: 160000, active: true },
{ id: 3, name: 'Grace Hopper', team: 'Engineering', salary: 152000, active: false },
{ id: 4, name: 'Katherine Johnson', team: 'Data', salary: 138000, active: true },
{ id: 5, name: 'Edsger Dijkstra', team: 'Research', salary: 149000, active: false },
])
const columns = [
{ field: 'name', header: 'Name', editorType: 'text', width: 200 },
{ field: 'team', header: 'Team', editorType: 'text', width: 150 },
{
field: 'salary',
header: 'Salary',
width: 130,
align: 'right',
format: { type: 'currency', currency: 'USD' },
},
{ field: 'active', header: 'Active', editorType: 'checkbox', width: 90 },
]
// installEnterprise() augments the grid API with the Pro methods:
// exportData, importData, print, pivot, AI.
async function run(label, fn) {
if (!api) return
try {
await fn()
status = `${label} ready`
} catch (err) {
status = `${label} failed: ${err instanceof Error ? err.message : String(err)}`
}
}
</script>
<main>
<header>
<div>
<h1>SvGrid Enterprise</h1>
<p>Sort, filter, select, and double-click a cell to edit.</p>
</div>
<button
type="button"
onclick={() => (theme = theme === 'dark' ? 'light' : 'dark')}
aria-label="Switch to {theme === 'dark' ? 'light' : 'dark'} mode"
>
{theme === 'dark' ? 'Light' : 'Dark'}
</button>
</header>
<div class="grid-shell">
<SvGrid
data={rows}
{columns}
sortable
filterable
editable
selectionMode="row"
showRowSelection={true}
showRowNumbers={true}
rowHeight={38}
containerHeight="100%"
fitColumns={true}
onApiReady={(next) => (api = installEnterprise(next))}
/>
</div>
<div class="actions">
<button type="button" onclick={() => run('CSV', () => api.exportData({ format: 'csv', filename: 'team' }))}>
Export CSV
</button>
<button type="button" onclick={() => run('Excel', () => api.exportData({ format: 'xlsx', filename: 'team' }))}>
Export Excel
</button>
<button type="button" onclick={() => run('PDF', () => api.exportData({ format: 'pdf', filename: 'team' }))}>
Export PDF
</button>
<button type="button" onclick={() => run('Print', () => api.print())}>Print</button>
{#if status}<span class="status">{status}</span>{/if}
</div>
<p class="hint">
Export respects the current sort, filter and grouping. Change the theme
import at the top of this file to re-skin the grid and this page together.
</p>
</main>
<style>
/* Page chrome reads the same --sg-* tokens as the grid, so it re-themes with it. */
:global(body) {
margin: 0;
background: var(--sg-bg);
color: var(--sg-fg);
font-family: var(--sg-font, system-ui, sans-serif);
}
main { max-width: 760px; margin: 3rem auto; padding: 0 1rem; }
header { display: flex; align-items: flex-start; justify-content: space-between; gap: 1rem; }
h1 { margin: 0; font-size: 1.4rem; }
p { color: var(--sg-muted); }
.actions { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; margin-top: 1rem; }
button {
flex: none;
padding: 0.4rem 0.8rem;
border: 1px solid var(--sg-border);
border-radius: var(--sg-radius, 6px);
background: var(--sg-bg-subtle, transparent);
color: var(--sg-fg);
font: inherit;
font-size: 0.85rem;
cursor: pointer;
}
button:hover { background: var(--sg-row-hover-bg); }
button:focus-visible { outline: 2px solid var(--sg-accent); outline-offset: 2px; }
.status { font-size: 0.82rem; color: var(--sg-muted); }
.grid-shell { height: 320px; }
.hint { font-size: 0.85rem; }
</style>
4. Run it
npm run dev
Open http://localhost:5173. You should get a five-row grid: click a header to sort, use the funnel for Excel-style filtering, double-click a cell to edit, and the four buttons write real files.
What the three pieces do
| Line | Why it's there |
|---|---|
setLicenseKey(...) |
Runs once, before any Enterprise call. Without it the pack still works, but watermarks and nudges the app. See licensing. |
installEnterprise(next) |
Wraps the SvGridApi from onApiReady and returns it with exportData, importData, print, pivot and AI attached. The <SvGrid> component itself stays Community. |
import '@svgrid/grid/themes/shadcn.css' |
Optional. Declares the --sg-* tokens for one of 20 presets. Without it the grid still renders, using the built-in fallbacks. |
Server-side rendering
The component above is SSR-safe as written: theme starts at a literal, and
every DOM and localStorage access sits inside $effect, which only runs in
the browser. No export const ssr = false is needed.
If you move DOM access to module scope or into component initialisation, it
will run on the server and throw. Keep it in $effect or onMount.
Older versions
@svgrid/enterprise 2.5.x and earlier shipped TypeScript source rather than a
built bundle. Vite's dependency pre-bundler cannot parse the .svelte.ts rune
modules in it, so those versions need two entries in vite.config.js:
optimizeDeps: {
// Without this the dev server fails to start:
// RolldownError ... Unexpected token (on `import type`)
exclude: ['@svgrid/grid', '@svgrid/enterprise'],
// Excluding it also stops ITS imports being pre-bundled, and jszip and
// pdfmake are CommonJS. Without this, xlsx and pdf export fail with
// "JSZip is not a constructor" / "pdfMake.createPdf is not a function".
include: ['jszip', 'pdfmake/build/pdfmake', 'pdfmake/build/vfs_fonts'],
},
2.6.0 moved the package to a built dist, so neither entry is needed. Upgrading
is the better fix.
Next
- Evaluation - what shows without a key, and how to remove it.
- Licensing - key formats, seats, renewals.
- Data export - styles, headers, images, multi-sheet.
- Data import - column mapping and per-row validation.
Related articles
- Render Your First Svelte Data Grid in Under 5 Minutes - How to add a fast, accessible, sortable data grid to a Svelte 5 app with SvGrid - covering data, typed columns, feature composition, and the imperative API.
- How We Started Building SvGrid - The boundary we drew on day one - between the logic engine and the render layer - is what everything else rests on. Here is how that line was drawn and what it cost to get right.
- An Autocomplete Cell Editor in SvGrid - Build a typeahead cell editor from scratch - filtering suggestions as the user types, committing cleanly on selection, and handling remote data without leaking requests.