operational software
Build the screens your customers live in all day.
Grids. Charts. KPIs. Boards. Timelines. Live data. Analytics. Connected by one data layer. Lattice gives software teams the infrastructure behind complex operational applications, so they can spend their engineering time building the product that makes them different.
See what Lattice replaces Open the live application →
Vanilla JavaScript. Zero runtime dependencies. Works with React, Vue, Angular, Svelte and your existing stack. Licensed per domain, not per developer.
Open the full demo → Start from a working screen → Read the documentation →
what it replaces
One dependency where a screen like that usually needs five.
The application above is a grid, a second grid, a derived summary panel, a KPI strip, two charts, a kanban board and a project timeline, all fed by one live connection. Assembled the usual way, that is a grid vendor, a charting vendor, a board or scheduling library, a statistics package and a realtime layer of your own, each with its own data shape, its own idea of a filter, its own release cycle and its own invoice. Every seam between them is something your team writes, tests and then owns forever.
The table
Hundreds of thousands of rows, virtualised, with sorting, multi-condition filtering, grouping, pivoting, pinned columns and rows, inline editing with validation and undo, conditional formatting, saved views and real .xlsx export.
The charts
A chart library that reads the grid's filtered rows rather than a copy of them, so a filter on the table is the chart's filter too, and a drag on a chart is a filter on the table. Trendlines, annotations, dual axes and forecast bands included.
The board and the plan
The same rows as cards in status columns, dragged by mouse or keyboard with card ageing and flow metrics, and as an editable schedule with dependencies, the critical path, resource levelling and earned value. Both write back through the grid's own edit path.
The numbers
KPI tiles with thresholds and sparklines, and a statistics engine underneath: quantiles, correlation, regression, control charts and process capability, forecasting, seasonality and anomaly detection, computed over exactly the rows the user has filtered to.
The live layer
One feed, partitioned across every view at once, with keyed updates, relationships, burst handling, reconnect and replay, cross-tab mirroring and its own throughput reporting. This is the part teams always underestimate and always end up writing.
The data you cannot send
A grid over a dataset too large to ship to a browser: filtering, sorting, grouping and paging become queries answered by DuckDB, OData, REST or your warehouse, and only the rows on screen come back.
Every one of those is a module you opt into. A page that never loads the board pays nothing for the board, and the pieces you do load share one dataset, one filter model, one theme and one licence.
the thing underneath
One data layer under every view.
A grid, a kanban board, a chart and a panel of KPI tiles are not four products in Lattice. They are four ways of reading one dataset, and they all take their rows through the same contract: a keyed diff of what was added, changed and removed. That is why the screen above holds together. One connection is partitioned once, and each view is handed only its own slice, by identity, so a change lands in the one row that moved rather than repainting a panel and losing the reader's place.
It is also why adding a view is small. The work queue in the demo is one set of records read as a grid, as a board and as a timeline; switching between them changes nothing about where the data comes from, and a drag on the board reaches the grid, the tiles and the chart because it goes back into the same feed everything else reads.
Views stay related without staying coupled
Click a shipment and the work queue narrows to that shipment's exceptions, on the identifier they share. One line of configuration, no query written by hand, and neither view knows the other exists.
Summaries are derived, not duplicated
The hub panel beside the shipments is built from the shipments, so filtering the table rewrites the summary and picking a summary row filters the table. No second fetch, no second copy to keep in step.
the questions that come after the demo
It has to hold up on a Tuesday afternoon.
Scale you can put in front of a customer
The demo above holds fifty thousand shipments in a grid that sorts, filters and searches without pausing, while a feed updates it continuously. When the dataset is bigger than the browser should ever see, push the query to where the data lives instead.
Your product, not ours
Themes are CSS variables, so the grid takes your palette, your typography and your density rather than announcing a vendor. Cells, headers, cards and tiles all accept renderers of your own, and every string the grid says comes from a message catalogue you control.
Keyboard and screen-reader users
Every operation is reachable without a pointer, a screen reader hears where a user stands in the whole dataset rather than in the rows on screen, and moving a card on the board is fully keyboard driven with the move announced. Conformance work against WCAG 2.2 level AA is ongoing rather than a finished claim, and the site says so plainly.
It fits the stack you already have
Vanilla JavaScript with no runtime dependencies, plus adapters for React, Vue, Angular and Svelte, a web component, an htmx integration and Python packages for Jupyter and Dash. The data layer does not change between them.
Users can change what they see
Saved views capture a filter, a sort and a column layout under a name a person chooses, stored in the browser or in your own backend. Ship a set of defined views with the product and let each user keep their own beside them.
A model in the loop, on your terms
Bring your own model and key. It explains a figure, answers a question as a validated read-only query your engine runs, and proposes an edit a person approves before anything is written. No data leaves for a service of ours, because there isn't one.
How it holds a million rows → The AI layer → Every feature, as a demo →
the commercial shape
Priced per domain, not per developer.
A per-seat licence charges you for headcount you are already paying for and turns every hire, contractor and agency onto a procurement form. Lattice is licensed per domain, which is something you already know without asking anyone, so the number does not move when the team does. A named domain is $1,000 and includes a year of support and as many developers as you like.
Development on localhost needs no key at all, and staging, preview and CI render the whole product behind a trial watermark. So a team can build the entire screen, put it in front of a customer and know it works before anyone signs anything.
Pricing in full → The licence agreement → Compared with AG Grid →
Spend your engineering time on the product, not the screens under it.
Start from a working operational screen rather than an empty page: the starter kits are whole applications you can run, read and take apart. Nothing to license until you ship.