# Vantage Framework > Vantage is an open-source Rust framework for business data: typed entities and tables over SQL (PostgreSQL, MySQL, SQLite), SurrealDB, MongoDB, REST/GraphQL APIs and more, with relations, expressions, Rhai scripting and live (push or poll) data. It is the engine under Vantage UI (https://vantage-ui.com/). This book teaches it bottom-up, from a first query to live APIs and adding a new persistence. Each link below is a chapter's markdown source. The whole book in one file: https://vantage-ui.com/book/llms-full.txt ## Introduction - [Introduction](https://vantage-ui.com/book/introduction.md): Vantage is a data entity persistence and abstraction framework for Rust. - [SQLite and the Query Builder](https://vantage-ui.com/book/intro/step1-first-query.md): Vantage is a big framework. It covers SQL databases, SurrealDB, MongoDB, CSV files, REST APIs — and ties them all together with a shared type system, expression engine, and data abstraction layer. - [Tables and Typed Data Access](https://vantage-ui.com/book/intro/step2-tables.md): A table is a structure representing a collection of records in a database: - [A Standalone Axum Server](https://vantage-ui.com/book/intro/step3-axum-server.md): Chapter 2 ended with a CLI that prints products to stdout. In this chapter we put the same model behind an HTTP API: - [Vista — the Universal Data Handle](https://vantage-ui.com/book/intro/step4-vista.md): Chapters 1–3 built a typed data layer: `Table`, conditions, relationships, CRUD. That layer is great when you know the entity at compile time. But step 3's generic `crud()` helper already showed the… - [Choose Your Path](https://vantage-ui.com/book/intro/fork.md): You now have a Vista — a runtime handle over your data that works the same no matter what's behind it. Everything up to here was the foundation. Everything past here is the reactive stack: a local cache, an event bus,… ## A Facade over a Custom API - [A Facade over a Custom API](https://vantage-ui.com/book/intro/step5-dio-lens.md): Chapter 4 gave you Vista — a universal handle that works with any backend. But every call still hits the backend. That was easy to forgive with a local SQLite file; this chapter picks a data source where it hurts: a… - [Augmentation — Enriching Rows](https://vantage-ui.com/book/intro/step6-augmentation.md): Chapter 5's inventory knows every station file's name and size — the two things an S3 listing gives away for free. Everything interesting is *inside* the files: how many readings a station has recorded, and how… - [Scenery — Reactive Views](https://vantage-ui.com/book/intro/step7-scenery.md): Chapter 6's CLI asks for one window of details and exits — the *asking* is still on the programmer. A real interface is a standing view: the user scrolls, and the window should follow; details land one by one, and the… - [Serving Scenery — Axum & Watch Streams](https://vantage-ui.com/book/intro/step8-axum-dio.md): Chapter 7's client of the Dio was a terminal driving two sceneries — one showing the rows, the other aggregating a running sum. Sceneries scale well beyond that: the framework can drive many active viewers at once, and… ## A Live API over SQL - [A Live API over SQL](https://vantage-ui.com/book/intro/step5-sql-dio.md): This path builds a live, cached, watchable view in front of a SQL database you own. We start from a Vista over a SQLite `product` table: a runtime handle that can already sort, search, paginate and write. That is a… - [Serving & Watching Live Stock](https://vantage-ui.com/book/intro/step6-sql-watch.md): The last chapter left a `Dio` holding a live copy of the `product` table. Now we put it behind HTTP, using the same adapter the S3 path uses. `DioRouter` doesn't know or care that its Dio is backed by SQL instead of… - [Moving to PostgreSQL](https://vantage-ui.com/book/intro/step7-sql-postgres.md): A file on disk is a fine place for a bar to start. When it outgrows one, with concurrent writers, a second instance or a backup story, you reach for a database server. In most stacks that is a migration project. Here… - [Real-Time Push with LISTEN/NOTIFY](https://vantage-ui.com/book/intro/step8-sql-notify.md): The app so far reconciles on a timer: `Refresher::new(reload).every(Duration::from_secs(1))`. That is polling. Once a second the Dio re-reads the master and reconciles. It works, but it is a beat behind every change,… - [Switching to SurrealDB](https://vantage-ui.com/book/intro/step9-surreal.md): Postgres was a migration *within* SQL: a different server, the same dialect family. SurrealDB is a different database: multi-model, schemaless by default, and reached over a WebSocket rather than a pooled SQL… ## Historical Timeline - [Historical Timeline](https://vantage-ui.com/book/history.md): Vantage didn't start as a multi-backend entity framework. It started as a weekend experiment to see if Rust could build SQL queries without feeling like Rust. - [What's New in 0.4](https://vantage-ui.com/book/whats-new-04.md): Version 0.4 is a ground-up rewrite of the type system and a massive expansion of persistence support. If 0.3 proved the architecture, 0.4 makes it production-ready. - [What's New in 0.5](https://vantage-ui.com/book/whats-new-in-05.md): Version 0.4 made the type system precise — every backend carries its own types, and a persistence implements only what its engine supports. Version 0.5 answers the question that follows: how does code that doesn't know… ## Migrating to 2.0 - [Migrating to 2.0](https://vantage-ui.com/book/migration-2.0.md): 2.0 rebuilds the interface of every layer above `Table`: `vantage-vista`, `vantage-diorama` and every driver's `TableShell`. Two crates are gone, about twenty shell methods are gone, the Lens has four settings… - [Vista](https://vantage-ui.com/book/migration-2.0/vista.md): `Vista` is the type-erased `Table`, and 2.0 makes it behave like one: it is `Clone`, owns its query, narrows with consuming `with_*` and changes in place only through `add_*` / `set_*` on a value you own. The… - [References, Catalog and Rhai](https://vantage-ui.com/book/migration-2.0/references-catalog-rhai.md): 1.x had five ways to name "something that gives me a Vista for a name": `TargetResolver`, `ModelResolver`, `ModelLoader`, `ContainedRefResolver` and each driver's `*SpecResolver` alias. It had two relation types,… - [Dio and Lens](https://vantage-ui.com/book/migration-2.0/dio-lens.md): In 1.x a Lens had eight hooks, each handed a `&Dio`, and a Dio could be narrowed, re-pointed and augmented after it was built, by anyone holding it. Rule 5 ended that: a Dio is a shared handle, so `&self` never changes… - [Writes and Ingress](https://vantage-ui.com/book/migration-2.0/writes-ingress.md): 1.x wrote through a family of `flash_*` methods, a facade that returned before the write landed (reporting a failure only as an event), and an id-less insert that skipped the Lens writer. Changes from outside came in… - [Sceneries](https://vantage-ui.com/book/migration-2.0/sceneries.md): In 1.x two identical opens returned the same `Arc`, so one grid's `set_search` changed what another grid showed, and an `.exclusive()` flag opted out. A scenery had two filter setters, a separate shown range, a cap… - [Aggregates](https://vantage-ui.com/book/migration-2.0/aggregates.md): 1.x had two aggregate vocabularies: diorama's own (`value_scenery().count()`, `.sum(c)`, `CustomAggregate`) and the vantage-diorama-aggregate crate's (`Count`, `Sum::new`, `CountWhere`, `AggregateLens`, `DerivedDio`),… - [Surface: Paths, Preludes and Features](https://vantage-ui.com/book/migration-2.0/surface.md): Most first-round compile errors in a port are paths. Rule 11 gives every public item one path: its module or the crate root, never both, and no crate re-exports another crate's items outside its prelude. Rule 8 made… - [Drivers](https://vantage-ui.com/book/migration-2.0/drivers.md): The drivers' own factory APIs (`from_table`, `from_yaml`, `with_resolver`) keep their shape; what changed is underneath and around them. Rule 1 removed the per-driver resolver aliases in favour of one `SpecResolver`… - [Downstream: vantage-ui and vantage-actions](https://vantage-ui.com/book/migration-2.0/downstream.md): This page is the work list for the port that follows 2.0: vantage-ui, its vantage-actions dependency (through vantage-lib), the skills bundle and the example apps. It is grouped by area and names files where the… ## Relations & Traversal - [Relations & Traversal](https://vantage-ui.com/book/relations.md): Vantage treats a relation as something you *traverse*, not something you *load*. Declared once on the model, a relation gives you: - [Traversing Sets and Records](https://vantage-ui.com/book/relations/traversal.md): The previous chapter declared the bakery model: Bakery → Clients (`client.bakery_id`) → Orders (`client_order.client_id`), with the relations `"orders"`, `"client"`, and `"bakery"` registered via `with_one` /… - [Expressions & Subqueries](https://vantage-ui.com/book/relations/expressions.md): The previous chapter used relations to *fetch* related rows — traverse from a client to their orders, get the orders back as a set. This chapter uses relations *inside* a query: a client row that carries its own order… - [Implicit References](https://vantage-ui.com/book/relations/implicit-references.md): The previous chapter (Expressions & Subqueries) closed with a recipe: take a relation, call `get_subquery_as` to build a correlated subquery for one field, and register it with `with_expression` so it projects as a… - [Vista, YAML and Rhai](https://vantage-ui.com/book/relations/vistas.md): Everything so far assumed you could write `Table` in your source code. Generic consumers can't. A UI grid, an admin panel, a scripting surface, a config-driven tool — none of them know your model types… - [Relations and Dio](https://vantage-ui.com/book/relations/dio.md): Everything in this guide so far has executed at or below the Vista: typed relations on the Table, traversal narrowing, subquery expressions, implicit references. This final chapter climbs one layer higher. A `Dio`… ## Model-Driven Architecture - [Model-Driven Architecture](https://vantage-ui.com/book/mda.md): Vantage is opinionated about how you structure business software. The framework prescribes a Model-Driven Architecture (MDA) where entities, relationships, and business rules live in a shared model crate — decoupled… - [Three Paths for Developers](https://vantage-ui.com/book/three-paths.md): Vantage gives you three ways to work with data. Each path builds on the previous one, and all three converge into a unified data abstraction layer. ## Scripting with Rhai - [Scripting with Rhai](https://vantage-ui.com/book/rhai.md): A Vantage application can keep much of its behaviour in configuration: YAML table specs, page definitions, action bodies, faker sims. Some of that configuration needs logic: a column derived from other columns, a… - [Hosts](https://vantage-ui.com/book/rhai/hosts.md): A script never runs on a bare Rhai engine. It runs in a `Host` from `vantage-rhai`: one engine with fixed limits, a bounded cache of compiled scripts, and the vocabularies registered on it. This chapter is for the Rust… - [The Table Handle](https://vantage-ui.com/book/rhai/tables.md): `table(name)` returns a handle: a table plus an ordered list of narrowing steps. Narrowing verbs add steps. Terminal verbs resolve the handle into a Vista, apply the steps, and read or write. - [Writes](https://vantage-ui.com/book/rhai/writes.md): On a host with `Terminals::ReadWrite`, a handle also writes. Every write goes through the resolved Vista, so it follows the backend's rules and whatever policy the host's resolver wrapped around it. - [Computed Columns](https://vantage-ui.com/book/rhai/computed.md): A computed column is a column whose value no backend stores. It is a short Rhai expression over `row`, the record as the backend returned it, and its last expression is the column's value. The expression lives in the… - [Records](https://vantage-ui.com/book/rhai/records.md): A record is a draft of one row. It reads like a map, stages edits, and flashes only what changed. Use it when a script edits a row field by field, or when a host hands a script "the current row" (Vantage UI's action… - [Surfaces](https://vantage-ui.com/book/rhai/surfaces.md): The data vocabulary is the same everywhere. What changes from one place to the next is the host: which tables `table(name)` reaches, which terminal verbs exist, and what the script is given in scope. This chapter goes… - [Layers](https://vantage-ui.com/book/rhai/layers.md): The data vocabulary acts on Vistas and nothing else. Three parts of the framework sit above Vista and give scripts words of their own: Servo drafts in `vantage-diorama`, Scenery shapes in Vantage UI, and faker sims.… - [Faker Sims](https://vantage-ui.com/book/rhai/faker.md): `vantage-faker` fills memory tables with generated rows. With its `sim` feature it also runs Rhai scripts as simulations over the same memory store: each sim is a script with its own clock, and a `SimDef` spawns copies… - [Expression Dialects](https://vantage-ui.com/book/rhai/dialects.md): Not every script in a Vantage configuration is a data script. Some build a backend's native query, some compute one value from one row, and some are text with a few holes in it. They run on the same `vantage-rhai`… - [Tables Defined by a Query](https://vantage-ui.com/book/rhai/query-tables.md): A table usually reads one physical table or collection. A YAML spec for SQLite, PostgreSQL, MySQL or SurrealDB can instead take its rows from a `SELECT` that a Rhai script builds. The script uses the backend's query… - [Query Builder Functions](https://vantage-ui.com/book/rhai/query-builders.md): This page lists every function the SQL and SurrealDB query builders register for Rhai. They are available where a script builds a native query: a query-sourced table's `rhai:` and `base:` scripts, and on SurrealDB and… ## Optimising Live Diorama Data - [Optimising Live Diorama Data](https://vantage-ui.com/book/optimising-diorama.md): An application reports its faults. It does not report its inefficiencies. A failed request raises an error, but a duplicate fetch stays unnoticed. Typical problems are: - [The setup](https://vantage-ui.com/book/optimising-diorama/stack.md): An enterprise source holds millions of records, and there can be hundreds of changes each second. The change channels are coarse: one channel for each table. But no user observes millions of records. A user looks at 20… - [Reading the Debug Stream](https://vantage-ui.com/book/optimising-diorama/debug-stream.md): The first thing that you learn from the stream is which line agrees with which moment on screen. Keep the window and the terminal beside each other. Sort a column, type in the quick-search box, and scroll, and watch… - [Where the Work Happens: Capabilities & Latency](https://vantage-ui.com/book/optimising-diorama/capabilities.md): Until now the source was capable. When the source can do everything, the layers above it do nothing that you can measure. - [Fetching What You Drop](https://vantage-ui.com/book/optimising-diorama/waste.md): This section examines the requests that the application did not have to send. These are more difficult to find. A wasteful application and an efficient application look the same on screen. - [Faults: Errors, Outages & Lies](https://vantage-ui.com/book/optimising-diorama/faults.md): Each source until now answered, and its answers were true. Production sources are not always honest. A source can fail one request while the user scrolls. It can stop for ten seconds. It can also report a row count… - [Locking It In: Cache Regression Tests](https://vantage-ui.com/book/optimising-diorama/regression.md): The numbers that you measured are true of the code as it is today. This section answers a different question: what happens in six months, when somebody adds a refresh timer or makes a query wider, and nobody repeats… ## Adding a New Persistence - [Adding a New Persistence](https://vantage-ui.com/book/new-persistence.md): So you want to connect Vantage to a new database? This guide walks through the process in nine incremental steps — each one unlocks more framework features. You don't have to implement all nine; stop whenever your… - [Step 1: Type System](https://vantage-ui.com/book/new-persistence/step1-types.md): Every database has its own idea of what types exist. SQLite has 5 storage classes (NULL, INTEGER, REAL, TEXT, BLOB). Postgres has dozens. SurrealDB has its own set with Things and Geometry types. - [Step 2: Expressions](https://vantage-ui.com/book/new-persistence/step2-expressions.md): With the type system in place, you can now use `Expression` to build and execute queries. This step has two deliverables: a convenience macro and the `ExprDataSource` trait implementation. - [Step 3: Operators](https://vantage-ui.com/book/new-persistence/step3-operators.md): Expressions let you build raw queries, but users shouldn't have to write `sqlite_expr!("{} > {}", (ident("price")), 100i64)` every time they want a condition. Operators give typed columns ergonomic methods like… - [Step 4: Query Builder](https://vantage-ui.com/book/new-persistence/step4-query-builder.md): In practice, nobody writes raw expressions for every query. This step adds the `Selectable` trait implementation for your SELECT builder and wires it up through `SelectableDataSource` so the rest of vantage can create… - [Step 5: Table & CRUD](https://vantage-ui.com/book/new-persistence/step5-table-crud.md): The same entities get used hundreds of times across a codebase — constructing a query from scratch every single time is tedious and error-prone. Vantage offers `Table<>` as an abstraction over your entity definitions:… - [Step 6: Relationships](https://vantage-ui.com/book/new-persistence/step6-relationships.md): Tables can declare relationships using `with_one` and `with_many`, then traverse them at runtime with `get_ref_as`. The relationship system is provided by `vantage-table` — your backend just needs… - [Step 7: Multi-Backend](https://vantage-ui.com/book/new-persistence/step7-multi-backend.md): At this point your backend works — you can define tables, query data, and traverse relationships. But a real application typically has a _model crate_ that defines entities once and offers table constructors for each… - [Step 8: Vista Integration](https://vantage-ui.com/book/new-persistence/step8-vista-integration.md): By the end of Step 6 your backend is a typed persistence: `Table`, conditions, relationships. That's what business logic wants, and it's exactly what generic code can't use. - [Step 9: Contained Relations](https://vantage-ui.com/book/new-persistence/step9-contained-relations.md): Some data doesn't live in its own table. A product carries an `inventory` object; an order carries a `lines` array. The records are real: they have fields, and you want to list them, add to them and edit one. But… ## Persistence-aligned Type System - [Persistence-aligned Type System](https://vantage-ui.com/book/type-system.md): Every Vantage persistence defines its own type trait — `SqliteType`, `PostgresType`, `SurrealType`, `MongoType`, `CsvType` — that maps Rust values to and from the storage format. This is how expressions like… - [Adding Custom Types](https://vantage-ui.com/book/type-system/custom-types.md): You can teach Vantage to store any Rust type by implementing the persistence type trait. Here's the pattern, using an `Animal` enum that maps to a text column across every backend: ## SQL: PostgreSQL, MySQL & SQLite - [SQL: PostgreSQL, MySQL & SQLite](https://vantage-ui.com/book/sql.md): The `vantage-sql` crate provides persistence implementations for three SQL databases via sqlx. All three share the same architecture — CBOR-based type systems, expression engine, query builder, and full `TableSource`… - [Primitives](https://vantage-ui.com/book/sql/primitives.md): Primitives are reusable building blocks for constructing SQL expressions. They handle quoting, escaping, vendor-specific syntax, and logical composition so you don't have to. - [Type Conversions](https://vantage-ui.com/book/sql/type-conversions.md): How Rust native types round-trip through different SQL column types. Tested via entity insert + read-back (Table API). ## SurrealDB - [SurrealDB](https://vantage-ui.com/book/surrealdb.md): The `vantage-surrealdb` crate targets SurrealDB — a document-graph database whose query language (SurrealQL) is close enough to SQL to share a vocabulary, but diverges where it matters: graph traversals instead of… - [Primitives](https://vantage-ui.com/book/surrealdb/primitives.md): Primitives are the named building blocks for SurrealQL expressions. Each one does a single job and lowers to the SurrealQL it's named for — you call `surreal::coalesce(a, b)` and get `a ?? b`, not a string you had to… ## HTTP APIs: REST & GraphQL - [HTTP APIs: REST & GraphQL](https://vantage-ui.com/book/http-apis.md): The `vantage-api-client` crate reads tables from HTTP APIs. `RestApi` turns a table into `GET {base_url}/{endpoint}?…`, and `GraphqlApi` turns it into one query document posted to an endpoint. Both send through… - [REST: the api: Block](https://vantage-ui.com/book/http-apis/rest-yaml.md): A REST spec is a `RestApiVistaSpec`. Its only driver-specific key is the table-level `api:` block. Columns and references use the universal spec keys, with no `api:` block of their own. - [GraphQL: the graphql: Blocks](https://vantage-ui.com/book/http-apis/graphql-yaml.md): A GraphQL spec is a `GraphqlApiVistaSpec`. It has a table-level `graphql:` block for the root field and what the server accepts, and an optional column-level `graphql:` block for a column whose server field has a… ## Topics - [Expressions & Queries](https://vantage-ui.com/book/expressions.md): Vantage builds queries without string concatenation. The `vantage-expressions` crate provides a type-safe, composable expression system that works across all persistence backends — SQL, SurrealDB, MongoDB, CSV, and… - [Records: Traversal, Invariants & Hooks](https://vantage-ui.com/book/record-lifecycle.md): Once a backend implements `TableSource` (see Adding a New Persistence), `vantage-table` gives every `Table` a uniform write pipeline. On each write the record flows through three stages before it reaches… - [Transactions](https://vantage-ui.com/book/transactions.md): Moving 30 from Alice's account to Bob's takes two patches. Without a transaction, if the second one fails, Bob has the money and Alice still has it too. A `Transaction` makes the two patches land together or not at… - [Config-Driven Vistas: YAML & Rhai](https://vantage-ui.com/book/config-driven-vistas.md): The Vista chapter built Vistas by wrapping typed tables — Rust code, compiled in. This page covers the other construction path: declare the Vista in YAML, load it at runtime, and seal it behind the same honest handle.… - [Live Data: Push, Poll & Freshness](https://vantage-ui.com/book/live-data.md): A cache only stays correct if it finds out when the underlying data changes. There are two ways it can: it asks (poll), or the database tells it (push). A Dio asks for push with one call on its builder,… - [Augmentation](https://vantage-ui.com/book/augmentation.md): A `Vista` reads one table from one backend. But a row is often only half the story: an S3 bucket listing tells you a file's key and size, not how many resources the terraform state inside it declares. A REST list of… ## Optional - [Vantage UI](https://vantage-ui.com/llms.txt): the AI-first app builder built on this framework - [Source on GitHub](https://github.com/romaninsh/vantage): the vantage-* crates