Capabilities today
This chapter describes Graviola as it exists in production today. Directions that are not yet implemented in the form described are kept in Architectural trajectory.
Schema-driven CRUD
Given a JSON Schema definition with @id and @type semantics, Graviola provides:
GenericForm— a top-level component that, given a schema and an entity IRI, generates a form, loads the entity from the configured store, manages dirty state and validation, and writes changes back. No per-entity-type code is required.SemanticJsonForm— the lower-level component, used when explicit control over schema, UI schema, or data flow is needed.- CRUD hooks —
useFormData,useFormEditor,useCRUDWithQueryClient, integrated with TanStack Query for caching and invalidation.
The CRUD pipeline translates JSON Schema definitions into store-appropriate operations. For SPARQL backends, this means generating CONSTRUCT queries for reads and INSERT/DELETE patterns for writes; for Prisma backends, it means typed ORM operations; for REST, configurable endpoint patterns.
Whether JSON Schema (and companion UI or mapping files) are authored by hand or generated in the application build — for example from LinkML — does not change this pipeline: Graviola consumes the same outputs at runtime.
Form rendering
Graviola uses JSON Forms as its UI rendering substrate. The framework ships a renderer registry covering:
- Standard field types (text, number, date, boolean, enum)
- Linked-data-aware renderers (entity pickers that query the configured store, authority lookup widgets)
- Layout renderers (grids, tabs, sections)
- Specialized renderers for color input, MapLibre GL maps, and Markdown editing
Renderers are registered once and dispatched by schema shape rather than by entity type. Adding a new entity type to a Graviola application typically requires no new renderer code.
SemanticTable
SemanticTable is a schema-driven table component providing:
- Pagination, sorting, and filtering against the configured store
- Soft-delete (move to trash, restore from trash)
- CSV export
- Column visibility configuration
- Row selection and inline editing hooks
The table derives its columns and filters from the same JSON Schema used by the forms, so a change in the schema propagates to both surfaces without intervention.
Semantic detail views
Forms and tables answer editing and browsing. Detail views answer how a single entity should look when space is tight (a chip in a search result), medium (a card in a gallery or sidebar), or unconstrained (a full detail page or modal). Graviola treats these as one family of read-only, schema-driven representations, not separate components per entity type.
The production component is DetailRenderer (@graviola/edb-detail-renderer). It selects a layout and field renderers from the same JSON Schema that drives forms and tables, using the same structural dispatch principle described in The shape of a federated application: small tester functions rank how well they can render a schema node or entity in a given context; the best match wins.
View sizes
DetailRenderer accepts a view size that constrains how much of the entity is shown:
| Size | Typical use | What the user sees |
|---|---|---|
chip | Inline references, filter tags, table cells linking to entities | A compact label — often with icon or color — identifying the entity at a glance |
listItem | Vertical lists, pickers, search results | One row: primary label plus a few secondary fields |
card | Galleries, dashboards, sidebars | A summary block — headline, optional image, selected key facts, optional actions |
detail | Full-page views, drawer panels, modals | The entity laid out in sections with linked nested entities resolved |
The same Person schema can appear as a chip in a table column, a card in a browse grid, and a full detail layout in a modal — without three hand-written React components.
Detail UI schema
Like JSON Forms editing UI, detail rendering uses a separate UI schema — a JSON Forms UISchemaElement tree scoped to schema nodes, not a duplicate of the domain schema. Defaults are generated by generateDefaultDetailUISchema (with skipScope / scopeOverride for per-field control). Card layouts have a parallel default via generateDefaultCardUISchema. Applications override presentation — which fields appear at which size, section groupings, header image — without changing the underlying data model.
Modals and composite surfaces
Higher-level components wrap DetailRenderer for common application patterns:
EntityDetailModal— read-only entity inspection in a dialog (from@graviola/edb-advanced-components)EditEntityModal— detail view paired with the form pipeline for in-place editing
SemanticTable column cells and linked-data form fields reuse the same chip and compact renderers when an entity reference needs to be shown inline.
Headless core, MUI bindings
Dispatch logic, testers, and scope resolution live in @graviola/edb-detail-renderer-core (no MUI dependency). The MUI implementation — layouts, chips, card variants, control renderers — lives in @graviola/edb-detail-renderer. Custom design systems can attach to the core package the same way custom form renderers attach to JSON Forms.
Interactive examples and renderer overrides are documented in the framework Storybook (apps/storybook in the Graviola monorepo); apps/testapp shows DetailRenderer wired against a local Oxigraph store.
Declarative authority mapping
Graviola's mapping layer is the production-tested mechanism for transforming records from external authority sources into the application's local data model. Mappings are written as JSON-LD-flavored declarative documents, not code. Each mapping entry pairs a source path (JSONPath against the authority response) with a target path in the local schema, optionally invoking a named strategy for non-trivial transformations.
The strategy catalog includes operations for concatenation, first-match selection, date-string-to-integer conversion, entity creation with authoritative back-links, template substitution, and recursion into nested mappings. The catalog is extensible, and new strategies can be added without modifying the mapping engine.
This layer is currently used for ingestion from Wikidata, GND, and DBpedia in cultural heritage applications. It is documented and has been refined across multiple deployments.
Storage backends
The current storage contract is the Store interface in @graviola/store-core (capability facets + CapabilityDescriptor). Many packages still expose the legacy AbstractDatastore name; behavior is the same seam.
Concrete Store implementations and providers available today:
| Backend | Stack | Status | Typical use |
|---|---|---|---|
| In-browser Oxigraph (WebAssembly) | Oxigraph in a WebWorker | Production | Local-first applications, no-server deployments |
| Remote SPARQL endpoint | HTTP SPARQL against Fuseki, Oxigraph, Blazegraph, … | Production | Federated data, existing institutional triple stores |
| N3 in-memory | @rdfjs/data-model DatasetCore backed by n3 Store, queried via Comunica (@comunica/query-sparql-rdfjs) | Production | Fast in-browser RAM store — tests, Storybook, prototyping (InMemoryStoreProvider) |
| IndexedDB hexastore | Same Comunica SPARQL layer over @graviola/indexeddb-dataset (persistent hexastore in the browser) | Experimental (slow) | Durable browser persistence without the Oxigraph worker (IndexedDBStoreProvider) |
| Prisma (PostgreSQL, SQLite, others) | Typed ORM | Production | Internal tools, classical web applications |
| REST API | Configurable HTTP patterns | Production | Integration with existing HTTP services |
| HDT (WASM) | Read-only access to compressed HDT dumps via a WASM implementation | In development | Large read-mostly RDF corpora without full materialisation |
The two Comunica + @rdfjs dataset providers live in @graviola/indexeddb-store-provider. Both expose the same SPARQL CRUD surface to the framework; they differ only in where triples are held — RAM (n3.Store) versus IndexedDB. Oxigraph and remote SPARQL use separate engines (@graviola/local-oxigraph-store-provider, @graviola/sparql-store-provider).
The SPARQL path supports multiple dialects for remote and Oxigraph backends (standard SPARQL 1.1, Oxigraph, Blazegraph, Allegro) selectable per deployment. Comunica-backed stores use standard SPARQL 1.1.
Federation across multiple registered stores is trajectory — see Store topology.
Browser/server symmetry
Graviola's foundation and schema-to-query layers are constrained to be free of React, MUI, or any browser-only dependency. This constraint is enforced because the same packages are consumed by command-line tools (@graviola/edb-cli) and a REST API server (apps/edb-api) running on Bun. The translation from JSON Schema to SPARQL, the graph-to-JSON extraction, and the data-mapping engine all run identically in browser and server environments.
This symmetry is a load-bearing property of Graviola's design and shapes how new capabilities are added.
See also
- Architecture and data flow — how these pieces connect.
- The shape of a federated application — why detail views are a family of sizes, not one component.
- LinkML as an authoring source for schemas — optional build-time generation of today's artifacts.
- Glossary — Store, AbstractDatastore (legacy), Structural dispatch, Declarative mapping, JSON Forms.
- Architectural trajectory — planned extensions (lenses, calcs, signing, provenance, federation) not guaranteed by this chapter.
- Store topology — proposed federation registry design.