mashlib
mashlib is the complete SolidOS data browser bundle — it combines all libraries and panes into a single distributable package.
Try the Live Browser Demo → | Custom Pane Demo →
What's New in mashlib 2.0
Released: November 29, 2025 (v2.0.0)
mashlib 2.0 is a major release with breaking API changes. See PR #220 for full details.
Breaking Changes
New SolidLogic Global
The way you access core functionality has changed:
| v1.x (Old) | v2.0 (New) |
|---|---|
panes.UI | UI |
store / UI.store / panes.UI.store | SolidLogic.store |
authSession / UI.authn.authSession | SolidLogic.authSession |
UI.rdf / panes.UI.rdf | $rdf |
authn.currentUser() / UI.authn.currentUser() | SolidLogic.authn.currentUser() |
Node.js Requirements
- Dropped: Node 18
- Required: Node 20.x or 22.x
New Features
SolidLogicglobal — consolidated access to store, authentication, and sessionmashlib.versionInfo— runtime version information- Dual bundles — both
mashlib.js(development) andmashlib.min.js(production) - rdflib 2.3.0 — updated RDF library
Migration Example
Before (v1.x):
// Accessing the store
const store = panes.UI.store
// Or
const store = UI.store
// Authentication
const user = panes.UI.authn.currentUser()
// RDF operations
const sym = panes.UI.rdf.sym('https://example.org/')
After (v2.0):
// Accessing the store
const store = SolidLogic.store
// Authentication
const user = SolidLogic.authn.currentUser()
// RDF operations
const sym = $rdf.sym('https://example.org/')
Quick Check
Verify your mashlib version at runtime:
console.log(mashlib.versionInfo)
// { version: '2.0.0', ... }
Installation
npm
npm install mashlib
CDN
<script src="https://cdn.jsdelivr.net/npm/mashlib/dist/mashlib.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/mashlib/dist/mash.css" rel="stylesheet">
Quick Start
The simplest way to run SolidOS:
<!DOCTYPE html>
<html>
<head>
<title>SolidOS Data Browser</title>
<script src="https://cdn.jsdelivr.net/npm/mashlib/dist/mashlib.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/mashlib/dist/mash.css" rel="stylesheet">
</head>
<body>
<div id="PageBody"></div>
<script>
document.addEventListener('DOMContentLoaded', () => {
panes.runDataBrowser(document)
})
</script>
</body>
</html>
Complete Working Example
A full standalone HTML file with login, URI navigation, and the data browser. Save this as browse.html and open in a browser:
<!DOCTYPE html>
<html id="docHTML">
<head>
<meta charset="UTF-8">
<title>SolidOS Data Browser</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/mashlib/dist/mash.css" />
<script src="https://cdn.jsdelivr.net/npm/mashlib/dist/mashlib.min.js"></script>
<style>
#inputArea {
width: 100%;
padding: 0.5em;
background-color: #d0d0d0;
}
#uriField {
width: 70%;
font-size: 100%;
min-width: 25em;
padding: 0.5em;
}
#loginButtonArea { display: inline-block; }
#loginButtonArea input { margin: 0.25em !important; padding: 0.25em !important; }
</style>
</head>
<body>
<!-- Navigation Bar -->
<div id="inputArea">
<div style="margin-bottom:0.6em"><strong>SolidOS Data Browser</strong></div>
<div style="margin-left:1em">
Viewing
<input id="uriField" type="text" placeholder="Enter a pod URL, e.g. https://you.solidcommunity.net/" />
<input type="button" id="goButton" value="Go" />
</div>
<div style="margin-top:0.5em; margin-left:1em">
As user <span id="webId"><public user></span>
<span id="loginButtonArea"></span>
</div>
</div>
<!-- Data Browser Container -->
<div class="TabulatorOutline" id="DummyUUID" role="main">
<table id="outline"></table>
<div id="GlobalDashboard"></div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const authn = SolidLogic.authn
const authSession = SolidLogic.authSession
const store = SolidLogic.store
const dom = document
const uriField = dom.getElementById('uriField')
const goButton = dom.getElementById('goButton')
const loginButtonArea = dom.getElementById('loginButtonArea')
const webIdArea = dom.getElementById('webId')
const banner = dom.getElementById('inputArea')
const outliner = panes.getOutliner(dom)
// Navigate to a URI
function go() {
const uri = $rdf.uri.join(uriField.value, window.location.href)
console.log('Navigating to:', uri)
// Update URL bar
const params = new URLSearchParams(location.search)
params.set('uri', uri)
window.history.replaceState({}, '', `${location.origin}${location.pathname}?${params}`)
// Load the resource
const subject = $rdf.sym(uri)
outliner.GotoSubject(subject, true, undefined, true, undefined)
updateLoginArea()
}
// Update login status display
async function updateLoginArea() {
loginButtonArea.innerHTML = ''
if (uriField.value) {
loginButtonArea.appendChild(UI.login.loginStatusBox(document, null, {}))
}
const me = authn.currentUser()
if (me) {
webIdArea.innerHTML = ``
banner.style.backgroundColor = '#bbccbb'
} else {
webIdArea.innerHTML = '<public user>'
banner.style.backgroundColor = '#ccbbbb'
}
}
// Event listeners
uriField.addEventListener('keyup', (e) => { if (e.keyCode === 13) go() })
goButton.addEventListener('click', go)
// Handle auth events
if (authSession) {
authSession.events.on('login', () => { updateLoginArea(); go() })
authSession.events.on('logout', () => { updateLoginArea(); go() })
authSession.events.on('sessionRestore', () => { updateLoginArea(); go() })
}
// Check for URI in query string
const initial = new URLSearchParams(location.search).get('uri')
if (initial) {
uriField.value = initial
go()
}
updateLoginArea()
})
</script>
</body>
</html>
Try it: Live demo on GitHub Pages
Usage:
- Save the HTML file locally
- Open in a browser
- Enter a Solid pod URL (e.g.,
https://solidcommunity.net/) - Click "Go" to browse
- Click the login button to authenticate with your WebID
Global Objects
mashlib 2.0 exposes several global objects:
// The main entry point
panes.runDataBrowser(document)
// Access to solid-ui (v2.0: use UI directly, not panes.UI)
UI.widgets.button(...)
UI.forms.buildForm(...)
UI.style.styleElement(...)
// Access to the store (v2.0: use SolidLogic)
SolidLogic.store // The rdflib store
SolidLogic.store.fetcher // Fetcher
SolidLogic.store.updater // UpdateManager
// Authentication (v2.0: use SolidLogic.authn)
SolidLogic.authn.currentUser()
SolidLogic.authn.login()
SolidLogic.authn.logout()
// RDF operations (v2.0: use $rdf directly)
$rdf.sym('https://example.org/')
$rdf.lit('Hello')
$rdf.Namespace('http://xmlns.com/foaf/0.1/')
// Pane registry
panes.paneRegistry.register(myPane)
panes.paneRegistry.byName('folder')
// Version info (new in v2.0)
console.log(mashlib.versionInfo)
Configuration
Starting URL
Open a specific resource on load:
const subject = $rdf.sym('https://alice.example/profile/card#me')
panes.runDataBrowser(document, subject)
URL Parameters
mashlib reads URL parameters:
https://example.org/browse?uri=https://alice.example/profile/card
// Or set programmatically
const params = new URLSearchParams(window.location.search)
const uri = params.get('uri')
if (uri) {
panes.runDataBrowser(document, $rdf.sym(uri))
}
DOM Structure
mashlib creates this DOM structure:
<body>
<header id="PageHeader">
<!-- Login status, navigation -->
</header>
<div id="PageBody">
<div id="outline">
<!-- Breadcrumb, tabs -->
</div>
<div id="main">
<!-- Pane content -->
</div>
</div>
<footer id="PageFooter">
<!-- Footer links -->
</footer>
</body>
Required Elements
At minimum, you need:
<div id="PageBody"></div>
mashlib will create other elements as needed.
Custom Integration
With React
import { useEffect, useRef } from 'react'
function SolidOSBrowser({ uri }) {
const containerRef = useRef(null)
useEffect(() => {
if (containerRef.current && window.panes) {
const subject = window.$rdf.sym(uri)
window.panes.runDataBrowser(document, subject)
}
}, [uri])
return <div id="PageBody" ref={containerRef} />
}
With Vue
<template>
<div id="PageBody" ref="container"></div>
</template>
<script>
export default {
props: ['uri'],
mounted() {
if (window.panes) {
const subject = window.$rdf.sym(this.uri)
window.panes.runDataBrowser(document, subject)
}
}
}
</script>
Registering Custom Panes
One of mashlib's most powerful features is the ability to register custom panes with plain JavaScript — no build step, no transpiler, no npm required. Just edit and refresh!
Basic Registration
// Define your pane - pure JavaScript!
const myPane = {
name: 'my-custom-pane',
icon: 'https://example.org/icon.svg',
// When should this pane be shown? Return a label or null
label: function(subject, context) {
return "My Custom View"
},
// Render the pane content
render: function(subject, context) {
const div = context.dom.createElement('div')
div.innerHTML = '<h2>Hello from my pane!</h2>'
div.innerHTML += '<p>Viewing: ' + subject.value + '</p>'
return div
}
}
// Register it - that's it!
panes.register(myPane)
Conditional Display
Show your pane only for specific resource types:
const photoPane = {
name: 'photo-pane',
label: function(subject, context) {
// Only show for image files
const uri = subject.value
if (uri.match(/\.(jpg|jpeg|png|gif|webp)$/i)) {
return "Photo View"
}
return null // Don't show for other resources
},
render: function(subject, context) {
const img = context.dom.createElement('img')
img.src = subject.value
img.style.maxWidth = '100%'
return img
}
}
panes.register(photoPane)
Dynamic Pane Loading
Load panes from external URLs — perfect for hosting panes on your Pod or GitHub Pages:
// Load a pane from an external ES module
async function loadExternalPane(url) {
const module = await import(url)
panes.register(module.default)
}
// Load from your Pod
loadExternalPane('https://you.solidcommunity.net/public/panes/weather-pane.js')
// Or from GitHub Pages
loadExternalPane('https://your-org.github.io/panes/chart-pane.js')
The external pane file (weather-pane.js):
// weather-pane.js - an ES module
export default {
name: 'weather-pane',
label: function(subject, context) {
// Check if subject has weather data
const store = SolidLogic.store
const WEATHER = $rdf.Namespace('http://example.org/weather#')
if (store.any(subject, WEATHER('temperature'))) {
return "Weather"
}
return null
},
render: function(subject, context) {
// Render weather data...
}
}
Accessing RDF Data in Panes
Use the RDF store to read data about the subject:
const profilePane = {
name: 'profile-summary',
label: function(subject, context) {
const store = SolidLogic.store
const FOAF = $rdf.Namespace('http://xmlns.com/foaf/0.1/')
// Only show for resources with a name
if (store.any(subject, FOAF('name'))) {
return "Profile Summary"
}
return null
},
render: function(subject, context) {
const store = SolidLogic.store
const FOAF = $rdf.Namespace('http://xmlns.com/foaf/0.1/')
const name = store.any(subject, FOAF('name'))
const img = store.any(subject, FOAF('img'))
const div = context.dom.createElement('div')
div.innerHTML = '<h2>' + (name ? name.value : 'Unknown') + '</h2>'
if (img) {
div.innerHTML += '<img src="' + img.value + '" style="max-width: 200px">'
}
return div
}
}
panes.register(profilePane)
Styling
CSS Variables
Customize appearance with CSS variables:
:root {
--solid-primary-color: #7C4DFF;
--solid-secondary-color: #536DFE;
--solid-background-color: #FAFAFA;
--solid-text-color: #212121;
--solid-border-radius: 4px;
--solid-font-family: system-ui, sans-serif;
}
Custom Stylesheet
Override specific elements:
/* Custom header styling */
#PageHeader {
background: linear-gradient(135deg, #667eea, #764ba2);
}
/* Custom pane cards */
.solid-panel {
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
border-radius: 8px;
}
/* Custom buttons */
.solid-button {
border-radius: 20px;
}
Events
mashlib emits events you can listen for:
// Navigation events
document.addEventListener('solid-navigate', (event) => {
console.log('Navigated to:', event.detail.uri)
})
// Login/logout events (v2.0: use SolidLogic.authn)
SolidLogic.authn.onLogin((webId) => {
console.log('User logged in:', webId)
})
SolidLogic.authn.onLogout(() => {
console.log('User logged out')
})
Building from Source
# Clone the monorepo
git clone https://github.com/SolidOS/solidos.git
cd solidos
# Install and build
npm install
npm run setup
npm run build
# The bundle is in packages/mashlib/dist/
Development Mode
# Watch for changes
npm run watch
# Start dev server
npm start
Bundle Contents
mashlib includes:
- rdflib.js — RDF operations
- solid-logic — authentication, ACL, utilities
- solid-ui — UI components
- solid-panes — all built-in panes
- pane-registry — pane management
Bundle Size
| File | Size (gzipped) |
|---|---|
| mashlib.min.js | ~400 KB |
| mash.css | ~50 KB |
Server Integration
Node Solid Server (NSS)
NSS includes mashlib by default. It serves the data browser for HTML requests.
Community Solid Server (CSS)
Configure CSS to serve mashlib:
{
"@context": "https://linkedsoftwaredependencies.org/bundles/npm/@solid/community-server/^7.0.0/components/context.jsonld",
"import": [
"css:config/app/main/default.json",
"css:config/app/init/static-root.json"
],
"staticPath": "./node_modules/mashlib/dist/"
}
Troubleshooting
"panes is not defined"
Ensure mashlib is loaded before your script:
<script src="mashlib.min.js"></script>
<script>
// panes is now available
</script>
CORS Errors
When accessing remote pods, ensure CORS is configured. For development, use a local Solid server.
Styling Issues
Make sure mash.css is loaded:
<link href="mash.css" rel="stylesheet">
See Also
- mashlib GitHub
- SolidOS Monorepo
- Deployment Guide — hosting options
- Theming — customization