Skip to main content

Cookbook

Practical recipes for common SolidOS development tasks.

Quick Reference

RecipeDescription
AuthenticationLogin, logout, and session handling
Reading DataFetching and querying RDF
Writing DataCreating and updating resources
Access ControlManaging permissions
File OperationsUpload, download, containers
Type IndexFinding user data locations

Common Patterns

Check if User is Logged In

import { authn } from 'solid-logic'

const user = authn.currentUser()
if (user) {
console.log(`Logged in as ${user.uri}`)
} else {
console.log('Not logged in')
}

Load and Display a Name

import { store, sym } from 'solid-logic'

const FOAF = Namespace('http://xmlns.com/foaf/0.1/')

async function displayName(webId) {
const person = sym(webId)
await store.fetcher.load(person.doc())

const name = store.any(person, FOAF('name'), null, null)
return name?.value || 'Unknown'
}

Create a Simple Form

import * as UI from 'solid-ui'
import { store, sym } from 'solid-logic'

function createNameForm(subject, container) {
const FOAF = Namespace('http://xmlns.com/foaf/0.1/')

const nameField = UI.widgets.field(
document,
store,
subject,
FOAF('name'),
'Name'
)
container.appendChild(nameField)

const saveBtn = UI.widgets.asyncButton(document, 'Save', async () => {
// Changes are auto-saved by the field
UI.widgets.alert('Saved!')
})
container.appendChild(saveBtn)
}

Handle Errors Gracefully

import { store } from 'solid-logic'

async function loadSafely(uri) {
try {
await store.fetcher.load(uri)
return { success: true }
} catch (error) {
if (error.status === 401) {
return { success: false, reason: 'Please log in' }
} else if (error.status === 403) {
return { success: false, reason: 'Access denied' }
} else if (error.status === 404) {
return { success: false, reason: 'Not found' }
} else {
return { success: false, reason: error.message }
}
}
}

Subscribe to Changes

import { store, sym } from 'solid-logic'

function watchResource(uri, callback) {
const doc = sym(uri).doc()

// Reload periodically (simple approach)
const interval = setInterval(async () => {
await store.fetcher.refresh(doc)
callback()
}, 5000)

// Return cleanup function
return () => clearInterval(interval)
}

// Usage
const unsubscribe = watchResource('https://alice.example/data.ttl', () => {
console.log('Data changed!')
})
// Later: unsubscribe()

Create a Linked Resource

import { store, sym, lit, st, blankNode } from 'solid-logic'

async function createNote(containerUri, title, content) {
const noteDoc = sym(`${containerUri}note-${Date.now()}.ttl`)
const note = sym(`${noteDoc.uri}#this`)

const statements = [
st(note, RDF('type'), sym('http://schema.org/Note'), noteDoc),
st(note, RDFS('label'), lit(title), noteDoc),
st(note, sym('http://schema.org/text'), lit(content), noteDoc),
st(note, DCT('created'), lit(new Date().toISOString(), null,
sym('http://www.w3.org/2001/XMLSchema#dateTime')), noteDoc),
st(note, DCT('creator'), authn.currentUser(), noteDoc),
]

await store.updater.update([], statements)
return note
}
// In mashlib context
function navigateTo(uri) {
const subject = panes.UI.store.sym(uri)
panes.runDataBrowser(document, subject)
}

// Or dispatch event
function navigateViaEvent(uri) {
const event = new CustomEvent('solid-navigate', {
detail: { uri }
})
document.dispatchEvent(event)
}

See Also