Skip to main content

Solid

Solid (Social Linked Data) decouples data from applications. Your data lives in a "pod" that you control, and apps request access.

Core Concepts

Pods

A pod is a personal data store:

https://alice.pod.example/
├── profile/
│ └── card # WebID profile
├── public/ # Publicly accessible
├── private/ # Access controlled
├── photos/
├── documents/
└── settings/

You can run your own pod or use a provider. The data is yours either way.

WebID

Your WebID is your identity in Solid:

https://alice.pod.example/profile/card#me

It's a URL that, when accessed, returns information about you (as Linked Data).

# Example WebID Profile
@prefix foaf: <http://xmlns.com/foaf/0.1/>.
@prefix solid: <http://www.w3.org/ns/solid/terms#>.

<#me>
a foaf:Person;
foaf:name "Alice";
foaf:knows <https://bob.example/profile/card#me>;
solid:oidcIssuer <https://solidcommunity.net>.

Access Control

Solid supports two access control systems:

WAC vs ACP Comparison

FeatureWAC (Web Access Control)ACP (Access Control Policy)
ComplexitySimplerMore expressive
Inheritance.acl files per resourcePolicy chaining
GranularityResource levelAttribute-based
MaturityStable, widely usedNewer, more flexible
DefaultMost serversCSS default

WAC Example

# .acl file
@prefix acl: <http://www.w3.org/ns/auth/acl#>.

<#owner>
a acl:Authorization;
acl:agent <https://alice.example/profile/card#me>;
acl:accessTo <./document>;
acl:mode acl:Read, acl:Write, acl:Control.

<#public>
a acl:Authorization;
acl:agentClass foaf:Agent;
acl:accessTo <./document>;
acl:mode acl:Read.

ACP Example

# Access control policy
@prefix acp: <http://www.w3.org/ns/solid/acp#>.

<#policy>
a acp:AccessControlPolicy;
acp:allow [
acp:agent <https://alice.example/profile/card#me>;
acp:mode acp:Read, acp:Write
].

Permission Modes

ModeWACACPDescription
Readacl:Readacp:ReadView contents
Writeacl:Writeacp:WriteModify contents
Appendacl:Appendacp:AppendAdd without modify
Controlacl:ControlN/AChange permissions

Technical Foundation

Linked Data Platform (LDP)

Solid builds on LDP — a W3C standard for HTTP-based Linked Data:

OperationHTTP MethodExample
ReadGETGET /photos/cat.jpg
Create in containerPOSTPOST /photos/
Create at URLPUTPUT /photos/dog.jpg
UpdatePUT or PATCHPATCH /profile/card
DeleteDELETEDELETE /photos/old.jpg

Content Negotiation

Solid supports multiple RDF formats:

GET /document HTTP/1.1
Accept: text/turtle, application/ld+json
FormatMIME TypeUse Case
Turtletext/turtleHuman-readable
JSON-LDapplication/ld+jsonJavaScript-friendly
N-Triplesapplication/n-triplesStreaming
RDF/XMLapplication/rdf+xmlLegacy systems

Containers

Containers are like folders. They hold resources and other containers:

GET /photos/ HTTP/1.1
Accept: text/turtle

Response:

@prefix ldp: <http://www.w3.org/ns/ldp#>.

<>
a ldp:Container, ldp:BasicContainer;
ldp:contains <photo1.jpg>, <photo2.jpg>, <albums/>.

Container Operations

# Create a new container
POST /data/ HTTP/1.1
Link: <http://www.w3.org/ns/ldp#Container>; rel="type"
Slug: my-collection

# Add to container
POST /data/my-collection/ HTTP/1.1
Content-Type: text/turtle

<> a <http://schema.org/Note>;
<http://schema.org/text> "Hello world".

SPARQL Updates (Optional)

Some servers support SPARQL for complex updates:

# Add a triple
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
INSERT DATA {
<#me> foaf:knows <https://bob.example/profile/card#me>.
}
# Query example
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?friend WHERE {
<#me> foaf:knows ?friend.
}

Authentication

Solid-OIDC Flow

DPoP (Demonstrating Proof-of-Possession)

Solid uses DPoP tokens to prevent token theft:

GET /private/data HTTP/1.1
Authorization: DPoP <access_token>
DPoP: <dpop_proof>

Common Patterns

Type Indexes

Find data by type:

# Type index pointing to data locations
<#notes>
a solid:TypeRegistration;
solid:forClass <http://schema.org/Note>;
solid:instance </notes/>.

Preferences

Store settings in a known location:

/settings/prefs.ttl
/settings/privateTypeIndex.ttl
/settings/publicTypeIndex.ttl

Inbox

Receive notifications:

# Profile declares inbox location
<#me>
ldp:inbox </inbox/>.

Implementations

Servers

ServerLanguageStatus
JSSJavaScriptActive
CSSTypeScriptReference
NSSNode.jsMaintenance

Client Libraries

LibraryLanguageFeatures
solid-clientJavaScriptHigh-level API
rdflib.jsJavaScriptLow-level RDF
solid-client-authnJavaScriptAuthentication

Apps

Specifications

SpecDescription
Solid ProtocolMain specification
Solid-OIDCAuthentication
WACWeb Access Control
ACPAccess Control Policy

Solid Lite

Solid Lite is a minimal profile of Solid — the 20% that gives 80% of the value. Great for getting started.

Quick Example

Reading a profile:

import { getSolidDataset, getThing, getStringNoLocale } from "@inrupt/solid-client";
import { FOAF } from "@inrupt/vocab-common-rdf";

const dataset = await getSolidDataset("https://alice.pod.example/profile/card");
const profile = getThing(dataset, "https://alice.pod.example/profile/card#me");
const name = getStringNoLocale(profile, FOAF.name);
console.log(`Hello, ${name}!`);

Creating a resource:

import {
createSolidDataset,
createThing,
setThing,
saveSolidDatasetAt
} from "@inrupt/solid-client";

let note = createThing({ name: "note1" });
note = addStringNoLocale(note, SCHEMA.text, "My first note");

let dataset = createSolidDataset();
dataset = setThing(dataset, note);

await saveSolidDatasetAt("https://alice.pod.example/notes/note1", dataset, { fetch });

Error Handling

Common errors and solutions:

ErrorCauseSolution
401 UnauthorizedNot authenticatedLogin first
403 ForbiddenNo permissionRequest access
404 Not FoundResource doesn't existCheck URL
409 ConflictContainer not emptyDelete contents first

Performance Considerations

Batching Requests

Reduce round trips:

// Inefficient: many requests
for (const url of urls) {
await getSolidDataset(url);
}

// Better: parallel requests
await Promise.all(urls.map(url => getSolidDataset(url)));

Caching

Respect HTTP caching headers:

Cache-Control: max-age=3600
ETag: "abc123"

Getting Started

  1. Get a pod — Run Sandymount locally or use a provider
  2. Get authenticated — Use Solid-OIDC or browser login
  3. Read/write data — Use solid-client or raw HTTP

See Your First Pod for a complete tutorial.

Learn More