Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

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 hooksuseFormData, 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:

SizeTypical useWhat the user sees
chipInline references, filter tags, table cells linking to entitiesA compact label — often with icon or color — identifying the entity at a glance
listItemVertical lists, pickers, search resultsOne row: primary label plus a few secondary fields
cardGalleries, dashboards, sidebarsA summary block — headline, optional image, selected key facts, optional actions
detailFull-page views, drawer panels, modalsThe 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:

BackendStackStatusTypical use
In-browser Oxigraph (WebAssembly)Oxigraph in a WebWorkerProductionLocal-first applications, no-server deployments
Remote SPARQL endpointHTTP SPARQL against Fuseki, Oxigraph, Blazegraph, …ProductionFederated data, existing institutional triple stores
N3 in-memory@rdfjs/data-model DatasetCore backed by n3 Store, queried via Comunica (@comunica/query-sparql-rdfjs)ProductionFast in-browser RAM store — tests, Storybook, prototyping (InMemoryStoreProvider)
IndexedDB hexastoreSame 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 ORMProductionInternal tools, classical web applications
REST APIConfigurable HTTP patternsProductionIntegration with existing HTTP services
HDT (WASM)Read-only access to compressed HDT dumps via a WASM implementationIn developmentLarge 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