Package Exports
- javascript-solid-server
- javascript-solid-server/src/index.js
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (javascript-solid-server) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
JavaScript Solid Server
A minimal, fast, JSON-LD native Solid server.
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?
- Performance: JSON parsing is native to JavaScript - no external RDF libraries needed for basic operations
- Simplicity: JSON-LD is valid JSON - works with any JSON tooling
- Web-native: Browsers and web apps understand JSON natively
- 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 });Performance
This server is designed for speed. Benchmark results on a typical development machine:
| Operation | Requests/sec | Avg Latency | p99 Latency |
|---|---|---|---|
| GET resource | 5,400+ | 1.2ms | 3ms |
| GET container | 4,700+ | 1.6ms | 3ms |
| PUT (write) | 5,700+ | 1.1ms | 2ms |
| POST (create) | 5,200+ | 1.3ms | 3ms |
| OPTIONS | 10,000+ | 0.4ms | 1ms |
Run benchmarks yourself:
npm run benchmarkFeatures
Implemented (v0.0.12)
- LDP CRUD Operations - GET, PUT, POST, DELETE, HEAD
- N3 Patch - Solid's native patch format for RDF updates
- SPARQL Update - Standard SPARQL UPDATE protocol for PATCH
- Conditional Requests - If-Match/If-None-Match headers (304, 412)
- CLI & Config -
jsscommand with config file/env var support - SSL/TLS - HTTPS support with certificate configuration
- WebSocket Notifications - Real-time updates via solid-0.1 protocol (SolidOS compatible)
- Container Management - Create, list, and manage containers
- Multi-user Pods - Create pods at
/<username>/ - WebID Profiles - JSON-LD structured data in HTML at pod root
- Web Access Control (WAC) -
.aclfile-based authorization - Solid-OIDC Identity Provider - Built-in IdP with DPoP, dynamic registration
- Solid-OIDC Resource Server - Accept DPoP-bound access tokens from external IdPs
- Simple Auth Tokens - Built-in token authentication for development
- Content Negotiation - Optional Turtle <-> JSON-LD conversion
- CORS Support - Full cross-origin resource sharing
HTTP Methods
| Method | Support |
|---|---|
| GET | Full - Resources and containers |
| HEAD | Full |
| PUT | Full - Create/update resources |
| POST | Full - Create in containers |
| DELETE | Full |
| PATCH | N3 Patch format |
| OPTIONS | Full with CORS |
Getting Started
Prerequisites
- Node.js 18+
Installation
npm install
# Or install globally
npm install -g javascript-solid-serverQuick Start
# Initialize configuration (interactive)
jss init
# Start server
jss start
# Or with options
jss start --port 8443 --ssl-key ./key.pem --ssl-cert ./cert.pemCLI Commands
jss start [options] # Start the server
jss init [options] # Initialize configuration
jss --help # Show helpStart 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) |
-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
jss startConfig 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..."
}Using the Pod
# Read public profile
curl http://localhost:3000/alice/
# Write to pod (with token)
curl -X PUT http://localhost:3000/alice/public/data.json \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/ld+json" \
-d '{"@id": "#data", "http://example.org/value": 42}'
# Read back
curl http://localhost:3000/alice/public/data.jsonPATCH with N3
curl -X PATCH http://localhost:3000/alice/public/data.json \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: text/n3" \
-d '@prefix solid: <http://www.w3.org/ns/solid/terms#>.
_:patch a solid:InsertDeletePatch;
solid:inserts { <#data> <http://example.org/name> "Updated" }.'PATCH with SPARQL Update
curl -X PATCH http://localhost:3000/alice/public/data.json \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/sparql-update" \
-d 'PREFIX ex: <http://example.org/>
DELETE DATA { <#data> ex:value 42 } ;
INSERT DATA { <#data> ex:value 43 }'Conditional Requests
Use If-Match for safe updates (optimistic concurrency):
# Get current ETag
ETAG=$(curl -sI http://localhost:3000/alice/public/data.json | grep -i etag | awk '{print $2}')
# Update only if ETag matches
curl -X PUT http://localhost:3000/alice/public/data.json \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/ld+json" \
-H "If-Match: $ETAG" \
-d '{"@id": "#data", "http://example.org/value": 100}'Use If-None-Match: * for create-only semantics:
# Create only if resource doesn't exist (returns 412 if it does)
curl -X PUT http://localhost:3000/alice/public/new-resource.json \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/ld+json" \
-H "If-None-Match: *" \
-d '{"@id": "#new"}'Pod Structure
/alice/
├── index.html # WebID profile (HTML with JSON-LD)
├── .acl # Root ACL (owner + public read)
├── inbox/ # Notifications (public append)
│ └── .acl
├── public/ # Public files
├── private/ # Private files (owner only)
│ └── .acl
└── settings/ # User preferences (owner only)
├── .acl
├── prefs
├── publicTypeIndex
└── privateTypeIndexAuthentication
Simple Tokens (Development)
Use the token returned from pod creation:
curl -H "Authorization: Bearer YOUR_TOKEN" http://localhost:3000/alice/private/Built-in Identity Provider (v0.0.12+)
Enable the built-in Solid-OIDC Identity Provider:
jss start --idpWith IdP enabled, pod creation requires email and password:
curl -X POST http://localhost:3000/.pods \
-H "Content-Type: application/json" \
-d '{"name": "alice", "email": "alice@example.com", "password": "secret123"}'Response:
{
"name": "alice",
"webId": "http://localhost:3000/alice/#me",
"podUri": "http://localhost:3000/alice/",
"idpIssuer": "http://localhost:3000",
"loginUrl": "http://localhost:3000/idp/auth"
}OIDC Discovery: /.well-known/openid-configuration
Solid-OIDC (External IdP)
The server also accepts DPoP-bound access tokens from external Solid identity providers:
curl -H "Authorization: DPoP ACCESS_TOKEN" \
-H "DPoP: DPOP_PROOF" \
http://localhost:3000/alice/private/Configuration
createServer({
logger: true, // Enable Fastify logging (default: true)
conneg: false, // Enable content negotiation (default: false)
notifications: false // Enable WebSocket notifications (default: false)
});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/.notificationsProtocol (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)Running Tests
npm testCurrently passing: 174 tests (including 27 conformance tests)
Project Structure
src/
├── index.js # Entry point
├── server.js # Fastify setup
├── handlers/
│ ├── resource.js # GET, PUT, DELETE, HEAD, PATCH
│ └── container.js # POST, pod creation
├── storage/
│ └── filesystem.js # File operations
├── auth/
│ ├── middleware.js # Auth hook
│ ├── token.js # Simple token auth
│ └── solid-oidc.js # DPoP verification
├── wac/
│ ├── parser.js # ACL parsing
│ └── checker.js # Permission checking
├── ldp/
│ ├── headers.js # LDP Link headers
│ └── container.js # Container JSON-LD
├── webid/
│ └── profile.js # WebID generation
├── patch/
│ ├── n3-patch.js # N3 Patch support
│ └── sparql-update.js # SPARQL Update support
├── notifications/
│ ├── index.js # WebSocket plugin
│ ├── events.js # Event emitter
│ └── websocket.js # solid-0.1 protocol
├── idp/
│ ├── index.js # Identity Provider plugin
│ ├── provider.js # oidc-provider config
│ ├── adapter.js # Filesystem adapter
│ ├── accounts.js # User account management
│ ├── keys.js # JWKS key management
│ ├── interactions.js # Login/consent handlers
│ └── views.js # HTML templates
├── rdf/
│ ├── turtle.js # Turtle <-> JSON-LD
│ └── conneg.js # Content negotiation
└── utils/
├── url.js # URL utilities
└── conditional.js # If-Match/If-None-MatchDependencies
Minimal dependencies for a fast, secure server:
- fastify - High-performance HTTP server
- @fastify/websocket - WebSocket support for notifications
- fs-extra - Enhanced file operations
- jose - JWT/JWK handling for Solid-OIDC
- n3 - Turtle parsing (only used when conneg enabled)
- oidc-provider - OpenID Connect Identity Provider (only when IdP enabled)
- bcrypt - Password hashing (only when IdP enabled)
License
MIT