Understanding Benno
What you’ll learn
Section titled “What you’ll learn”In this guide, you’ll learn:
- how to think about data in Solid,
- what the challenges are when working with data in Solid, and
- how Benno’s data modelling simplifies this.
To start writing Solid apps with Benno, it’s helpful to first understand how Solid works. If you already know how Solid works, feel free to skip to What Makes Solid hard, and how does Benno help?.
Understanding Solid
Section titled “Understanding Solid”A Solid Pod is essentially just a webserver under the user’s control. It can host images, videos, PDFs, etc. They all have their own URLs. But more importantly, Solid stores RDF, the designated method to store structured data. Essentially, you can think of a URL storing RDF data as containing a set of objects not unlike rows in a database — we’ll call these Things.
Like database rows, Things will usually have an identifier. Unlike database rows, however, that identifier is not e.g. a number of a UUID, but a URL.
And where database rows have named columns, for Things these names (we’ll call them Properties) are also URLs!
Like database rows, columns/Properties can have values of different data types: strings, integers, decimals, booleans… And URLs get their own type too!
I’m sure you see the pattern here. In Solid, data is meant to be linked: Things can contain references to other Things, which can contain references to other Things, etc.
Let’s make this a little more concrete by way of an example. In a traditional database, you might store user information like this:
username | name | homepage |
|---|---|---|
Integer:42 | String:"Vincent Tunru" | String:"https://vincenttunru.com" |
Now what would this table look like if this were a Thing hosted at a Solid Pod instead?
| Thing URL | http://xmlns.com/foaf/0.1/name | http://xmlns.com/foaf/0.1/homepage |
|---|---|---|
URL:https://mypod.example/profile#vincenttunru | String:"Vincent Tunru" | URL:https://vincenttunru.com |
What makes Solid hard, and how does Benno help?
Section titled “What makes Solid hard, and how does Benno help?”A key feature of Solid is that it separates apps from data; data will be written to your user’s Solid Pod, regardless of where your app is hosted.
The user can connect their Solid Pod to other apps as well, and all those apps can write to the user’s Pod in their own way.
This is great for the user, as it gives them more control over their data. At the same time, it gives you, the app developer, less control over that data. This means that, unlike with traditional databases, you cannot enforce the type of data stored for every Property, or even that there is data for a given Property in the first place!
For example, using @inrupt/solid-client, reading a user’s name might look like this:
import { getSolidDataset, getStringNoLocale, getThing, getUrl, type UrlString,} from "@inrupt/solid-client";
async function fetchProfile(webId: UrlString) { const profileDataset = await getSolidDataset(webId); const profileThing = getThing(profileDataset, webId); if (profileThing === null) { return null; } const podRoot = getUrl( profileThing, "http://www.w3.org/ns/pim/space#storage", ); const name = getStringNoLocale( profileThing, "http://xmlns.com/foaf/0.1/name", );
if (typeof podRoot === "undefined") { return null; }
return { podRoot: podRoot, name: name, };}So far, this meant that Solid apps have had to practice extremely defensive coding: whenever an app tries to read or write data –any data– it theoretically had to first check whether similar data already existed, and if so, what type it was.
Benno allows you to define your expected data models once, and then does the data validation for you. We’ll see how in the next chapter.