JavaScriptSolidServer/docs/configuration.md at gh-pages · JavaScriptSolidServer/JavaScriptSolidServer

Philosophy: JSON-LD First

This is a JSON-LD native implementation. Unlike traditional Solid servers that treat Turtle as the primary format and convert to/from it, this server:

  • Stores everything as JSON-LD - No RDF parsing overhead for standard operations
  • Serves JSON-LD by default - Modern web applications can consume responses directly
  • Content negotiation is optional - Enable Turtle support with { conneg: true } when needed
  • Fast by design - Skip the RDF parsing tax when you don't need it

Why JSON-LD First?

  1. Performance: JSON parsing is native to JavaScript - no external RDF libraries needed for basic operations
  2. Simplicity: JSON-LD is valid JSON - works with any JSON tooling
  3. Web-native: Browsers and web apps understand JSON natively
  4. Semantic web ready: JSON-LD is a W3C standard RDF serialization

When to Enable Content Negotiation

Enable conneg: true when:

  • Interoperating with Turtle-based Solid apps
  • Serving data to legacy Solid clients
  • Running conformance tests that require Turtle support
import { createServer } from './src/server.js';

// Default: JSON-LD only (fast)
const server = createServer();

// With Turtle support (for interoperability)
const serverWithConneg = createServer({ conneg: true });
createServer({
  logger: true,        // Enable Fastify logging (default: true)
  conneg: false,       // Enable content negotiation (default: false)
  notifications: false, // Enable WebSocket notifications (default: false)
  subdomains: false,   // Enable subdomain-based pods (default: false)
  baseDomain: null,    // Base domain for subdomains (e.g., "example.com")
  mashlib: false,      // Enable Mashlib data browser - local mode (default: false)
  mashlibCdn: false,   // Enable Mashlib data browser - CDN mode (default: false)
  mashlibVersion: '2.0.0', // Mashlib version for CDN mode
});

Mashlib Data Browser

Enable the SolidOS Mashlib data browser for RDF resources. Two modes are available:

CDN Mode (recommended for getting started):

jss start --mashlib-cdn --conneg

Loads mashlib from unpkg.com CDN. Zero footprint - no local files needed.

Local Mode (for production/offline):

jss start --mashlib --conneg

Serves mashlib from src/mashlib-local/dist/. Requires building mashlib locally:

cd src/mashlib-local
npm install && npm run build

ES Module Mode (for custom or next-gen mashlib builds):

jss start --mashlib-module https://example.com/mashlib.js

Loads an ES module-based data browser from any URL. Uses <script type="module"> and <div id="mashlib"> (self-initializing). CSS is auto-derived by replacing .js with .css. Content negotiation is auto-enabled.

How it works:

  1. Browser requests /alice/public/data.ttl with Accept: text/html
  2. Server returns Mashlib HTML wrapper
  3. Mashlib fetches the actual data via content negotiation
  4. Mashlib renders an interactive, editable view

Note: Mashlib works best with --conneg enabled for Turtle support.

Modern UI (SolidOS UI):

jss start --mashlib --solidos-ui --conneg

Serves a modern Nextcloud-style UI shell while reusing mashlib's data layer. The --solidos-ui flag swaps the classic databrowser interface for a cleaner, mobile-friendly design with:

  • Modern file browser with breadcrumb navigation
  • Profile, Contacts, Sharing, and Settings views
  • Path-based URLs (browser URL reflects current resource)
  • Responsive design for mobile devices

Requires solidos-ui dist files in src/mashlib-local/dist/solidos-ui/. See solidos-ui for details.

Profile Pages

Pod profiles (/alice/) use HTML with embedded JSON-LD data islands and are rendered using:

  • mashlib-jss - A fork of mashlib with getPod() fix for path-based pods
  • solidos-lite - Parses JSON-LD data islands into the RDF store

This allows profiles to work without server-side content negotiation while still providing full SolidOS editing capabilities.

WebSocket Notifications

Enable real-time notifications for resource changes:

const server = createServer({ notifications: true });

Clients discover the WebSocket URL via the Updates-Via header:

curl -I http://localhost:3000/alice/public/
# Updates-Via: ws://localhost:3000/.notifications

Protocol (solid-0.1, compatible with SolidOS):

Server: protocol solid-0.1
Client: sub http://localhost:3000/alice/public/data.json
Server: ack http://localhost:3000/alice/public/data.json
Server: pub http://localhost:3000/alice/public/data.json  (on change)

CLI Start Options

Start Options

Option Description Default
-p, --port <n> Port to listen on 3000
-h, --host <addr> Host to bind to 0.0.0.0
-r, --root <path> Data directory ./data
-c, --config <file> Config file path -
--ssl-key <path> SSL private key (PEM) -
--ssl-cert <path> SSL certificate (PEM) -
--conneg Enable Turtle support false
--notifications Enable WebSocket false
--idp Enable built-in IdP false
--idp-issuer <url> IdP issuer URL (auto)
--subdomains Enable subdomain-based pods false
--base-domain <domain> Base domain for subdomains -
--mashlib Enable Mashlib (local mode) false
--mashlib-cdn Enable Mashlib (CDN mode) false
--mashlib-module <url> Enable ES module data browser from a URL -
--mashlib-version <ver> Mashlib CDN version 2.0.0
--solidos-ui Enable modern SolidOS UI (requires --mashlib) false
--git Enable Git HTTP backend false
--nostr Enable Nostr relay false
--nostr-path <path> Nostr relay WebSocket path /relay
--nostr-max-events <n> Max events in relay memory 1000
--invite-only Require invite code for registration false
--webid-tls Enable WebID-TLS client certificate auth false
--default-quota <size> Default storage quota per pod (e.g., 50MB) 50MB
--activitypub Enable ActivityPub federation false
--ap-username <name> ActivityPub username me
--ap-display-name <name> ActivityPub display name (username)
--ap-summary <text> ActivityPub bio/summary -
--ap-nostr-pubkey <hex> Nostr pubkey for identity linking -
--public Allow unauthenticated access (skip WAC) false
--read-only Disable PUT/DELETE/PATCH methods false
--live-reload Auto-refresh browser on file changes false
--pay Enable HTTP 402 paid access for /pay/* false
--pay-cost <n> Cost per request in satoshis 1
--pay-mempool-url <url> Mempool API URL for deposit verification (testnet4)
--pay-address <addr> Address for receiving deposits -
--pay-token <ticker> Token to sell (enables primary market + withdrawal) -
--pay-rate <n> Sats per token for buy/withdraw 1
--pay-chains <ids> Multi-chain deposits + AMM (e.g. "tbtc3,tbtc4") -
--mongo Enable MongoDB-backed /db/ route false
--mongo-url <url> MongoDB connection URL mongodb://localhost:27017
--mongo-database <name> MongoDB database name solid
--webrtc Enable WebRTC signaling server false
--webrtc-path <path> WebRTC signaling WebSocket path /.webrtc
--tunnel Enable tunnel proxy (decentralized ngrok) false
--tunnel-path <path> Tunnel WebSocket path /.tunnel
--terminal Enable WebSocket shell at /.terminal false
-q, --quiet Suppress logs false

Environment Variables

All options can be set via environment variables with JSS_ prefix:

export JSS_PORT=8443
export JSS_SSL_KEY=/path/to/key.pem
export JSS_SSL_CERT=/path/to/cert.pem
export JSS_CONNEG=true
export JSS_SUBDOMAINS=true
export JSS_BASE_DOMAIN=example.com
export JSS_MASHLIB=true
export JSS_MASHLIB_MODULE=https://example.com/mashlib.js
export JSS_NOSTR=true
export JSS_INVITE_ONLY=true
export JSS_WEBID_TLS=true
export JSS_DEFAULT_QUOTA=100MB
export JSS_ACTIVITYPUB=true
export JSS_AP_USERNAME=alice
export JSS_PUBLIC=true
export JSS_READ_ONLY=true
export JSS_LIVE_RELOAD=true
export JSS_SOLIDOS_UI=true
export JSS_PAY=true
export JSS_PAY_COST=10
export JSS_PAY_ADDRESS=your-address
export JSS_PAY_TOKEN=PODS
export JSS_PAY_RATE=10
export JSS_MONGO=true
export JSS_MONGO_URL=mongodb://localhost:27017
export JSS_MONGO_DATABASE=solid
export JSS_WEBRTC=true
jss start

Config File

Create config.json:

{
  "port": 8443,
  "root": "./data",
  "sslKey": "./ssl/key.pem",
  "sslCert": "./ssl/cert.pem",
  "conneg": true,
  "notifications": true
}

Then: jss start --config config.json

Creating a Pod

curl -X POST http://localhost:3000/.pods \
  -H "Content-Type: application/json" \
  -d '{"name": "alice"}'

Response:

{
  "name": "alice",
  "webId": "http://localhost:3000/alice/#me",
  "podUri": "http://localhost:3000/alice/",
  "token": "eyJ..."
}

Single-User Mode

For personal pod servers where only one user needs access:

# Basic single-user mode (creates pod at /me/)
jss start --single-user --idp

# Custom username
jss start --single-user --single-user-name alice --idp

# Root-level pod (pod at /, WebID at /profile/card#me)
jss start --single-user --single-user-name '' --idp

# Via environment
JSS_SINGLE_USER=true jss start --idp

Features:

  • Pod auto-created on first startup with full structure (inbox, public, private, profile)
  • Registration endpoint disabled (returns 403)
  • Login still works for the single user
  • Proper ACLs generated automatically

Invite-Only Registration

Control who can create accounts by requiring invite codes:

jss start --idp --invite-only

Managing Invite Codes

# Create a single-use invite
jss invite create
# Created invite code: ABCD1234

# Create multi-use invite with note
jss invite create -u 5 -n "For team members"

# List all active invites
jss invite list
#   CODE        USES     CREATED      NOTE
#   -------------------------------------------------------
#   ABCD1234    0/1      2026-01-03
#   EFGH5678    2/5      2026-01-03   For team members

# Revoke an invite
jss invite revoke ABCD1234

How It Works

Mode Registration Pod Creation
Open (default) Anyone can register Anyone can create pods
Invite-only Requires valid invite code Via registration only

When --invite-only is enabled:

  • The registration page shows an "Invite Code" field
  • Invalid or expired codes are rejected with an error
  • Each use decrements the invite's remaining uses
  • Depleted invites are automatically removed

Invite codes are stored in .server/invites.json in your data directory.

Storage Quotas

Limit storage per pod to prevent abuse and manage resources:

jss start --default-quota 50MB

Managing Quotas

# Set quota for a user (overrides default)
jss quota set alice 100MB

# Show quota info
jss quota show alice
#   alice:
#     Used:  12.5 MB
#     Limit: 100 MB
#     Free:  87.5 MB
#     Usage: 12%

# Recalculate from actual disk usage
jss quota reconcile alice

How It Works

  • Quotas are tracked incrementally on PUT, POST, and DELETE operations
  • When quota is exceeded, the server returns HTTP 507 Insufficient Storage
  • Each pod stores its quota in /{pod}/.quota.json
  • Use reconcile to fix quota drift from manual file changes

Size Formats

Supported formats: 50MB, 1GB, 500KB, 1TB

Mashlib Data Browser

Enable the SolidOS Mashlib data browser for RDF resources. Two modes are available:

CDN Mode (recommended for getting started):

jss start --mashlib-cdn --conneg

Loads mashlib from unpkg.com CDN. Zero footprint - no local files needed.

Local Mode (for production/offline):

jss start --mashlib --conneg

Serves mashlib from src/mashlib-local/dist/. Requires building mashlib locally:

cd src/mashlib-local
npm install && npm run build

ES Module Mode (for custom or next-gen mashlib builds):

jss start --mashlib-module https://example.com/mashlib.js

Loads an ES module-based data browser from any URL. Uses <script type="module"> and <div id="mashlib"> (self-initializing). CSS is auto-derived by replacing .js with .css. Content negotiation is auto-enabled.

How it works:

  1. Browser requests /alice/public/data.ttl with Accept: text/html
  2. Server returns Mashlib HTML wrapper
  3. Mashlib fetches the actual data via content negotiation
  4. Mashlib renders an interactive, editable view

Note: Mashlib works best with --conneg enabled for Turtle support.

Modern UI (SolidOS UI):

jss start --mashlib --solidos-ui --conneg

Serves a modern Nextcloud-style UI shell while reusing mashlib's data layer. The --solidos-ui flag swaps the classic databrowser interface for a cleaner, mobile-friendly design with:

  • Modern file browser with breadcrumb navigation
  • Profile, Contacts, Sharing, and Settings views
  • Path-based URLs (browser URL reflects current resource)
  • Responsive design for mobile devices

Requires solidos-ui dist files in src/mashlib-local/dist/solidos-ui/. See solidos-ui for details.

Profile Pages

Pod profiles (/alice/) use HTML with embedded JSON-LD data islands and are rendered using:

  • mashlib-jss - A fork of mashlib with getPod() fix for path-based pods
  • solidos-lite - Parses JSON-LD data islands into the RDF store

This allows profiles to work without server-side content negotiation while still providing full SolidOS editing capabilities.

WebSocket Notifications

Enable real-time notifications for resource changes:

const server = createServer({ notifications: true });

Clients discover the WebSocket URL via the Updates-Via header:

curl -I http://localhost:3000/alice/public/
# Updates-Via: ws://localhost:3000/.notifications

Protocol (solid-0.1, compatible with SolidOS):

Server: protocol solid-0.1
Client: sub http://localhost:3000/alice/public/data.json
Server: ack http://localhost:3000/alice/public/data.json
Server: pub http://localhost:3000/alice/public/data.json  (on change)