|
2 | 2 |
|
3 | 3 | A minimal, fast, JSON-LD native Solid server. |
4 | 4 |
|
5 | | -## Comparison |
6 | | - |
7 | | -| Server | Size | Deps | Notes | |
8 | | -|--------|------|------|-------| |
9 | | -| [JSS](https://github.com/JavaScriptSolidServer/JavaScriptSolidServer) | 432 KB | 10 | Minimal, JSON-LD native | |
10 | | -| [NSS](https://github.com/nodeSolidServer/node-solid-server) | 777 KB | 58 | Original Solid server | |
11 | | -| [CSS](https://github.com/CommunitySolidServer/CommunitySolidServer) | 5.8 MB | 70 | Modular, configurable | |
12 | | -| [Pivot](https://github.com/solid-contrib/pivot) | ~6 MB | 70+ | Built on CSS | |
13 | | - |
14 | | -## Philosophy: JSON-LD First |
15 | | - |
16 | | -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: |
17 | | - |
18 | | -- **Stores everything as JSON-LD** - No RDF parsing overhead for standard operations |
19 | | -- **Serves JSON-LD by default** - Modern web applications can consume responses directly |
20 | | -- **Content negotiation is optional** - Enable Turtle support with `{ conneg: true }` when needed |
21 | | -- **Fast by design** - Skip the RDF parsing tax when you don't need it |
22 | | - |
23 | | -### Why JSON-LD First? |
24 | | - |
25 | | -1. **Performance**: JSON parsing is native to JavaScript - no external RDF libraries needed for basic operations |
26 | | -2. **Simplicity**: JSON-LD is valid JSON - works with any JSON tooling |
27 | | -3. **Web-native**: Browsers and web apps understand JSON natively |
28 | | -4. **Semantic web ready**: JSON-LD is a W3C standard RDF serialization |
29 | | - |
30 | | -### When to Enable Content Negotiation |
31 | | - |
32 | | -Enable `conneg: true` when: |
33 | | -- Interoperating with Turtle-based Solid apps |
34 | | -- Serving data to legacy Solid clients |
35 | | -- Running conformance tests that require Turtle support |
36 | | - |
37 | | -```javascript |
38 | | -import { createServer } from './src/server.js'; |
39 | | - |
40 | | -// Default: JSON-LD only (fast) |
41 | | -const server = createServer(); |
42 | | - |
43 | | -// With Turtle support (for interoperability) |
44 | | -const serverWithConneg = createServer({ conneg: true }); |
45 | | -``` |
46 | | - |
47 | | -## Performance |
48 | | - |
49 | | -This server is designed for speed. Benchmark results on a typical development machine: |
50 | | - |
51 | | -| Operation | Requests/sec | Avg Latency | p99 Latency | |
52 | | -|-----------|-------------|-------------|-------------| |
53 | | -| GET resource | 5,400+ | 1.2ms | 3ms | |
54 | | -| GET container | 4,700+ | 1.6ms | 3ms | |
55 | | -| PUT (write) | 5,700+ | 1.1ms | 2ms | |
56 | | -| POST (create) | 5,200+ | 1.3ms | 3ms | |
57 | | -| OPTIONS | 10,000+ | 0.4ms | 1ms | |
58 | | - |
59 | | -Run benchmarks yourself: |
60 | | -```bash |
61 | | -npm run benchmark |
62 | | -``` |
63 | | - |
64 | 5 | ## Features |
65 | 6 |
|
66 | 7 | ### Implemented (v0.0.23) |
@@ -270,22 +211,103 @@ curl -X PUT http://localhost:3000/alice/public/new-resource.json \ |
270 | 211 | -d '{"@id": "#new"}' |
271 | 212 | ``` |
272 | 213 |
|
273 | | -## Pod Structure |
| 214 | +## Philosophy: JSON-LD First |
| 215 | + |
| 216 | +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: |
274 | 217 |
|
| 218 | +- **Stores everything as JSON-LD** - No RDF parsing overhead for standard operations |
| 219 | +- **Serves JSON-LD by default** - Modern web applications can consume responses directly |
| 220 | +- **Content negotiation is optional** - Enable Turtle support with `{ conneg: true }` when needed |
| 221 | +- **Fast by design** - Skip the RDF parsing tax when you don't need it |
| 222 | + |
| 223 | +### Why JSON-LD First? |
| 224 | + |
| 225 | +1. **Performance**: JSON parsing is native to JavaScript - no external RDF libraries needed for basic operations |
| 226 | +2. **Simplicity**: JSON-LD is valid JSON - works with any JSON tooling |
| 227 | +3. **Web-native**: Browsers and web apps understand JSON natively |
| 228 | +4. **Semantic web ready**: JSON-LD is a W3C standard RDF serialization |
| 229 | + |
| 230 | +### When to Enable Content Negotiation |
| 231 | + |
| 232 | +Enable `conneg: true` when: |
| 233 | +- Interoperating with Turtle-based Solid apps |
| 234 | +- Serving data to legacy Solid clients |
| 235 | +- Running conformance tests that require Turtle support |
| 236 | + |
| 237 | +```javascript |
| 238 | +import { createServer } from './src/server.js'; |
| 239 | + |
| 240 | +// Default: JSON-LD only (fast) |
| 241 | +const server = createServer(); |
| 242 | + |
| 243 | +// With Turtle support (for interoperability) |
| 244 | +const serverWithConneg = createServer({ conneg: true }); |
275 | 245 | ``` |
276 | | -/alice/ |
277 | | -├── index.html # WebID profile (HTML with JSON-LD) |
278 | | -├── .acl # Root ACL (owner + public read) |
279 | | -├── inbox/ # Notifications (public append) |
280 | | -│ └── .acl |
281 | | -├── public/ # Public files |
282 | | -├── private/ # Private files (owner only) |
283 | | -│ └── .acl |
284 | | -└── settings/ # User preferences (owner only) |
285 | | - ├── .acl |
286 | | - ├── prefs |
287 | | - ├── publicTypeIndex |
288 | | - └── privateTypeIndex |
| 246 | + |
| 247 | +## Configuration |
| 248 | + |
| 249 | +```javascript |
| 250 | +createServer({ |
| 251 | + logger: true, // Enable Fastify logging (default: true) |
| 252 | + conneg: false, // Enable content negotiation (default: false) |
| 253 | + notifications: false, // Enable WebSocket notifications (default: false) |
| 254 | + subdomains: false, // Enable subdomain-based pods (default: false) |
| 255 | + baseDomain: null, // Base domain for subdomains (e.g., "example.com") |
| 256 | + mashlib: false, // Enable Mashlib data browser - local mode (default: false) |
| 257 | + mashlibCdn: false, // Enable Mashlib data browser - CDN mode (default: false) |
| 258 | + mashlibVersion: '2.0.0', // Mashlib version for CDN mode |
| 259 | +}); |
| 260 | +``` |
| 261 | + |
| 262 | +### Mashlib Data Browser |
| 263 | + |
| 264 | +Enable the [SolidOS Mashlib](https://github.com/SolidOS/mashlib) data browser for RDF resources. Two modes are available: |
| 265 | + |
| 266 | +**CDN Mode** (recommended for getting started): |
| 267 | +```bash |
| 268 | +jss start --mashlib-cdn --conneg |
| 269 | +``` |
| 270 | +Loads mashlib from unpkg.com CDN. Zero footprint - no local files needed. |
| 271 | + |
| 272 | +**Local Mode** (for production/offline): |
| 273 | +```bash |
| 274 | +jss start --mashlib --conneg |
| 275 | +``` |
| 276 | +Serves mashlib from `src/mashlib-local/dist/`. Requires building mashlib locally: |
| 277 | +```bash |
| 278 | +cd src/mashlib-local |
| 279 | +npm install && npm run build |
| 280 | +``` |
| 281 | + |
| 282 | +**How it works:** |
| 283 | +1. Browser requests `/alice/public/data.ttl` with `Accept: text/html` |
| 284 | +2. Server returns Mashlib HTML wrapper |
| 285 | +3. Mashlib fetches the actual data via content negotiation |
| 286 | +4. Mashlib renders an interactive, editable view |
| 287 | + |
| 288 | +**Note:** Mashlib works best with `--conneg` enabled for Turtle support. Pod profiles (`/alice/`) continue to serve our JSON-LD-in-HTML format. |
| 289 | + |
| 290 | +### WebSocket Notifications |
| 291 | + |
| 292 | +Enable real-time notifications for resource changes: |
| 293 | + |
| 294 | +```javascript |
| 295 | +const server = createServer({ notifications: true }); |
| 296 | +``` |
| 297 | + |
| 298 | +Clients discover the WebSocket URL via the `Updates-Via` header: |
| 299 | + |
| 300 | +```bash |
| 301 | +curl -I http://localhost:3000/alice/public/ |
| 302 | +# Updates-Via: ws://localhost:3000/.notifications |
| 303 | +``` |
| 304 | + |
| 305 | +Protocol (solid-0.1, compatible with SolidOS): |
| 306 | +``` |
| 307 | +Server: protocol solid-0.1 |
| 308 | +Client: sub http://localhost:3000/alice/public/data.json |
| 309 | +Server: ack http://localhost:3000/alice/public/data.json |
| 310 | +Server: pub http://localhost:3000/alice/public/data.json (on change) |
289 | 311 | ``` |
290 | 312 |
|
291 | 313 | ## Authentication |
@@ -359,6 +381,24 @@ curl -H "Authorization: DPoP ACCESS_TOKEN" \ |
359 | 381 | http://localhost:3000/alice/private/ |
360 | 382 | ``` |
361 | 383 |
|
| 384 | +## Pod Structure |
| 385 | + |
| 386 | +``` |
| 387 | +/alice/ |
| 388 | +├── index.html # WebID profile (HTML with JSON-LD) |
| 389 | +├── .acl # Root ACL (owner + public read) |
| 390 | +├── inbox/ # Notifications (public append) |
| 391 | +│ └── .acl |
| 392 | +├── public/ # Public files |
| 393 | +├── private/ # Private files (owner only) |
| 394 | +│ └── .acl |
| 395 | +└── settings/ # User preferences (owner only) |
| 396 | + ├── .acl |
| 397 | + ├── prefs |
| 398 | + ├── publicTypeIndex |
| 399 | + └── privateTypeIndex |
| 400 | +``` |
| 401 | + |
362 | 402 | ## Subdomain Mode (XSS Protection) |
363 | 403 |
|
364 | 404 | By default, JSS uses **path-based pods** (`/alice/`, `/bob/`). This is simple but has a security limitation: all pods share the same origin, making cross-site scripting (XSS) attacks possible between pods. |
@@ -410,70 +450,30 @@ curl -X POST https://example.com/.pods \ |
410 | 450 | -d '{"name": "alice"}' |
411 | 451 | ``` |
412 | 452 |
|
413 | | -## Configuration |
414 | | - |
415 | | -```javascript |
416 | | -createServer({ |
417 | | - logger: true, // Enable Fastify logging (default: true) |
418 | | - conneg: false, // Enable content negotiation (default: false) |
419 | | - notifications: false, // Enable WebSocket notifications (default: false) |
420 | | - subdomains: false, // Enable subdomain-based pods (default: false) |
421 | | - baseDomain: null, // Base domain for subdomains (e.g., "example.com") |
422 | | - mashlib: false, // Enable Mashlib data browser - local mode (default: false) |
423 | | - mashlibCdn: false, // Enable Mashlib data browser - CDN mode (default: false) |
424 | | - mashlibVersion: '2.0.0', // Mashlib version for CDN mode |
425 | | -}); |
426 | | -``` |
427 | | - |
428 | | -### Mashlib Data Browser |
429 | | - |
430 | | -Enable the [SolidOS Mashlib](https://github.com/SolidOS/mashlib) data browser for RDF resources. Two modes are available: |
431 | | - |
432 | | -**CDN Mode** (recommended for getting started): |
433 | | -```bash |
434 | | -jss start --mashlib-cdn --conneg |
435 | | -``` |
436 | | -Loads mashlib from unpkg.com CDN. Zero footprint - no local files needed. |
437 | | - |
438 | | -**Local Mode** (for production/offline): |
439 | | -```bash |
440 | | -jss start --mashlib --conneg |
441 | | -``` |
442 | | -Serves mashlib from `src/mashlib-local/dist/`. Requires building mashlib locally: |
443 | | -```bash |
444 | | -cd src/mashlib-local |
445 | | -npm install && npm run build |
446 | | -``` |
447 | | - |
448 | | -**How it works:** |
449 | | -1. Browser requests `/alice/public/data.ttl` with `Accept: text/html` |
450 | | -2. Server returns Mashlib HTML wrapper |
451 | | -3. Mashlib fetches the actual data via content negotiation |
452 | | -4. Mashlib renders an interactive, editable view |
453 | | - |
454 | | -**Note:** Mashlib works best with `--conneg` enabled for Turtle support. Pod profiles (`/alice/`) continue to serve our JSON-LD-in-HTML format. |
| 453 | +## Comparison |
455 | 454 |
|
456 | | -### WebSocket Notifications |
| 455 | +| Server | Size | Deps | Notes | |
| 456 | +|--------|------|------|-------| |
| 457 | +| [JSS](https://github.com/JavaScriptSolidServer/JavaScriptSolidServer) | 432 KB | 10 | Minimal, JSON-LD native | |
| 458 | +| [NSS](https://github.com/nodeSolidServer/node-solid-server) | 777 KB | 58 | Original Solid server | |
| 459 | +| [CSS](https://github.com/CommunitySolidServer/CommunitySolidServer) | 5.8 MB | 70 | Modular, configurable | |
| 460 | +| [Pivot](https://github.com/solid-contrib/pivot) | ~6 MB | 70+ | Built on CSS | |
457 | 461 |
|
458 | | -Enable real-time notifications for resource changes: |
| 462 | +## Performance |
459 | 463 |
|
460 | | -```javascript |
461 | | -const server = createServer({ notifications: true }); |
462 | | -``` |
| 464 | +This server is designed for speed. Benchmark results on a typical development machine: |
463 | 465 |
|
464 | | -Clients discover the WebSocket URL via the `Updates-Via` header: |
| 466 | +| Operation | Requests/sec | Avg Latency | p99 Latency | |
| 467 | +|-----------|-------------|-------------|-------------| |
| 468 | +| GET resource | 5,400+ | 1.2ms | 3ms | |
| 469 | +| GET container | 4,700+ | 1.6ms | 3ms | |
| 470 | +| PUT (write) | 5,700+ | 1.1ms | 2ms | |
| 471 | +| POST (create) | 5,200+ | 1.3ms | 3ms | |
| 472 | +| OPTIONS | 10,000+ | 0.4ms | 1ms | |
465 | 473 |
|
| 474 | +Run benchmarks yourself: |
466 | 475 | ```bash |
467 | | -curl -I http://localhost:3000/alice/public/ |
468 | | -# Updates-Via: ws://localhost:3000/.notifications |
469 | | -``` |
470 | | - |
471 | | -Protocol (solid-0.1, compatible with SolidOS): |
472 | | -``` |
473 | | -Server: protocol solid-0.1 |
474 | | -Client: sub http://localhost:3000/alice/public/data.json |
475 | | -Server: ack http://localhost:3000/alice/public/data.json |
476 | | -Server: pub http://localhost:3000/alice/public/data.json (on change) |
| 476 | +npm run benchmark |
477 | 477 | ``` |
478 | 478 |
|
479 | 479 | ## Running Tests |
|
0 commit comments