Key concepts
The terms that the Backlit SDK and the reference use, and how they relate.
This page defines the terms that the rest of the documentation uses. Read it one time from top to bottom. Each concept builds on the concepts before it, and each one links to the reference page that has the details.
The request cycle
Each screen in a Backlit app is the result of one request and one response.
- The web client requests an address, such as the
listview of thesubscribersresource. - The host adapter receives the HTTP request and gives it to the Backlit app.
- The app loads the resource and runs the view. The view is your code. It reads the data and returns builders.
- The SDK produces a tree of protocol nodes from the builders. During this step, it validates the structure of the tree and converts your data to protocol values.
- The host adapter sends the response as JSON.
- The web client finds the component for the
kindof each node in its registry and renders the tree.
A user interaction starts the same cycle again. The client submits an action or requests a different view, and the server answers with a response.
Protocol and nodes
The protocol is the contract between a server and a client. It defines the nodes
that a server can send and the requests that a client can make. The
@backlit/contract package expresses it as TypeScript types.
A node is one element in a response. Each node has a kind, such as view,
table, or form, and the properties of that kind. A node contains no styles and
no layout coordinates. It contains only what a client cannot infer.
You do not write nodes by hand. You use builders, such as table() and form(),
and the SDK produces the nodes from them.
App, areas, and navigation
The app is the root of the declaration. You create it with defineApp. An app has
one or more areas, and an area is a named set of resources with a navigation list
for the sidebar. A small app has one area. A larger app can have an area for each
team or each domain, such as operations and finance.
A navigation entry points to one view of one resource. Resources are lazy imports, so the app can describe itself to the client without loading them. The description that the client receives when it starts is the manifest. It contains the areas, the navigation, the display preferences, and the installed extensions.
See App and areas.
Resources
A resource is a named entity of your domain, such as a subscriber or an order. It has two jobs. It holds the field declarations of the entity, and it is the place where you register views, actions, and lookups. The resource name is the first part of each address.
A resource does not fetch data and does not map to a database table. A resource can have no fields at all, which is usual for a dashboard.
See Resources.
Fields
A field describes one piece of data: its name, its data type, its format, and how the client renders it. The field name is the key that Backlit reads from your records. You declare a field one time, and tables, datalists, and forms all accept the same declaration.
A field is not a mapping to a database column. The data can come from anywhere, and a field can describe a computed value, an aggregate, or a statistic.
The same field has a read-only rendering and an input rendering. A date field is
formatted text in a table and a date picker in a form. Backlit calls these two uses
the display role and the input role. For each role, the SDK converts the value of
your record to a protocol value. A Date object becomes an ISO string, for example.
When a value cannot be converted, the SDK reports a defect and continues without that
value. It does not stop the response.
See Fields and Field roles.
Views
A view is one screen of a resource. You register it with resource.view(name, callback). The callback is a resolver: it runs on your server for each request,
reads the data through your own data layer, and returns the content of the screen.
The address of a view is the resource name, the view name, and the args. A view can
declare params, such as ['id'] for an edit screen, and the args are the request
values for those params. An address is not a URL. The host application converts an
address to a URL, so your URL structure stays under your control.
See Views.
Search state
State is the set of values that change what a view shows but do not identify it: the filters, the sort order, and the current page. State is in the query string, so a filtered list has a URL that a user can share.
You define filters, a sorter, and a paginator, and you register them on a view. The SDK parses the query string into typed values and describes the controls to the client. Your resolver applies the values to your query. Backlit does not filter or paginate your data.
A filter is not a field. A filter describes one query value and the control that changes it.
See Search state and Filters.
Actions
An action is an operation that changes data. You register it on a resource with a name, a schema, and a handler. The SDK validates the payload against the schema before the handler runs, so the handler receives typed data.
An action returns one of four responses.
- A success response reports that the operation is complete.
- A redirect response sends the client to a different view or to an external URL.
- A refresh response tells the client to load the current view again, or only the zones that it names.
- An error response has an HTTP status, a code, and optional errors for the form fields.
Each response can also contain a notification that the client shows to the user.
See Actions.
Blocks
A block is a node that you can put in the content of a view. Some blocks display
data, such as table, list, datalist, and timeline. Container blocks give
structure to a page, such as section, panel, tabs, and group, and they hold
other blocks in a slot. You compose a screen by nesting blocks.
A widget is a small block that shows one figure or one chart. Widgets are usually together in a widget group at the top of a dashboard.
Forms
A form is a block that collects values and submits them to one action. You create it from the action, so the form and the schema of the action cannot go out of sync. The inputs come from the fields of the resource. A validation error that the action returns appears next to the related input.
See Forms.
Targets
A target connects a block to a view, an action, or a lookup. You create a target from the definition and not from a string, so TypeScript checks the params.
linkToandvisitToopen a view. They can open it as a page, in a modal, or in a drawer.submitToruns an action, for example from a row of a table, with an optional confirmation dialog.- A lookup is a resolver that supplies options to an input, such as a search for a customer in a select control.
See Targets.
Zones
A zone is a named part of a view that the client can load again without the rest of the page. A zone has its own resolver. When an action returns a refresh response that names a zone, the client requests only that zone. The server runs the view callback to find the zone, runs the resolver of that zone, and skips the other zones. Use a zone for a part of a page that changes after an action, or that is slow to load.
See Zones.
Hosts
The host is the application that mounts Backlit. On the server, a host adapter such
as @backlit/hono connects the routes of your HTTP framework to the app. Your
middleware, your authentication, and your database stay in the host. On the client,
the host is the Vite application that mounts the Backlit shell and owns the router.
See Request handling.
Extensions and custom pages
An extension is a package with a server module and a client module. It can add field types, blocks, widgets, charts, and complete resources with their views and actions. When the client starts, it compares the extensions in the manifest with its own extensions, so a server module without its client module is found immediately.
A custom page is a JSX file in the pages directory of the frontend app. It is
normal React inside the Backlit shell, for a screen that no block can express.
See Extensions and Write a custom page.