A browser-based editor and server for managing WBOL (Webbase Ontology Language) based portals—the content model used by Spin the Web sites.
| Component | File | Role |
|---|---|---|
| Server | wbol-server.ts |
Deno HTTP + WebSocket backend |
| WBOL parser/serializer | wbol.ts |
In-memory model, parse/stringify WBOL XML |
| Studio UI | public/scripts/wbol-studio.js |
Custom element <wbol-studio> |
| Stylesheet | public/scripts/wbol-studio.css |
UI styles |
| Entry point | public/index.html |
Hosts the custom element |
The server is the single source of truth. All communication between clients and server goes over a persistent WebSocket connection using a request/response protocol with correlation IDs. Static files under public/ are served directly.
| File | Description |
|---|---|
webbase.wbol |
The WBOL XML document (loaded at startup, persisted on every mutation) |
webbase.log |
Append-only JSONL change log (one event per line) |
Hidden paths (starting with .) are blocked from static serving.
deno run --allow-net --allow-read --allow-write wbol-server.tsThe server listens on port 8000 by default (Deno.serve). Open http://localhost:8000 to access the Studio UI.
For debug mode with the VS Code task:
Run WBOL Studio Server (Debug) # file server on port 8080
Run WBOL Server (Debug) # wbol-server.ts with --inspect-brk
All WBOL operations are sent as JSON messages over ws://<host>/ws.
Request shape:
{ "id": "<uuid>", "action": "GET|POST|PUT|DELETE|HEAD", "urn": "/wbol/...", "data": {}, "clientId": "<uuid>", "ts": 1234567890 }Response shape:
{ "id": "<uuid>", "status": 200, "data": {}, "ts": 1234567890 }| Method | URN | Description |
|---|---|---|
| GET | /wbol/node |
Get a node by GUID or slug |
| POST | /wbol/node |
Create a child node |
| PUT | /wbol/node |
Update (patch) a node |
| DELETE | /wbol/node |
Delete a node |
| PUT | /wbol/node/move |
Move a node to a new parent |
| POST | /wbol/node/paste |
Deep-clone a node into a parent |
| HEAD | /wbol/search |
Search nodes |
| POST | /wbol/search/replace |
Search and replace across nodes |
| GET | /wbol/roles |
List roles |
| POST | /wbol/role |
Add a role |
| PUT | /wbol/role |
Rename a role |
| DELETE | /wbol/role |
Delete a role |
| GET | /wbol/datasources |
List datasources |
| POST | /wbol/datasource |
Add a datasource |
| PUT | /wbol/datasource |
Edit a datasource |
| DELETE | /wbol/datasource |
Delete a datasource |
| GET | /wbol/node/locks |
Get active editing locks snapshot |
| POST | /wbol/node/lock |
Acquire an editing lock |
| DELETE | /wbol/node/lock |
Release an editing lock |
| GET | /wbol/log |
Query the change log |
| GET | /wbol/fs/tree |
List the public file tree |
| GET | /wbol/fs/file |
Read an editable file |
| POST | /wbol/fs/file |
Create a new file |
| PUT | /wbol/fs/file |
Write/save a file |
| POST | /wbol/fs/directory |
Create a directory |
| PUT | /wbol/fs/move |
Rename/move a path |
| DELETE | /wbol/fs/path |
Delete a file or directory |
Editable file extensions: .html, .css, .js.
The server broadcasts JSON messages to all connected clients:
type |
Trigger | Payload |
|---|---|---|
wbol-update |
Any WBOL model mutation | { guids, changes, actorClientId } |
wbol-locks |
Lock acquired/released/snapshot | { action, guid, clientId, locks? } |
fs-update |
File system change | { action, path, ... } |
wbol-log-append |
Any successful mutation | { event } (full LogEvent object) |
- Each client generates a random UUID as its
clientId. - Before opening a node editor dialog the client acquires a node lock via
POST /wbol/node/lock. - Lock state is broadcast to all clients as
wbol-locksmessages and shown as lock badges in the tree. - When a WebSocket connection closes, all locks held by that socket are automatically released.
- Remote structural changes (move, delete) surface as inline alerts in the tree so other clients are notified.
Every successful mutation appends a JSONL event to public/.data/webbase.log:
{ "id": "<uuid>", "ts": 1746000000000, "clientId": "...", "scope": "node|role|datasource", "action": "create|update|delete|move|paste|rename|replace", "target": { "guid": "p1", "kind": "page" }, "parent": { "from": "a1", "to": "a2" }, "summary": "Moved page p1", "changedFields": ["sequence","parentGuid"] }Query via GET /wbol/log with optional filters: limit, sinceTs, scope, targetId, clientId.
The Source Control panel in the Studio UI (code-branch icon) loads and live-updates the log, grouped with scope icons, relative timestamps, and "you" labelling for the current client's own edits.
| Toolbar icon | Panel |
|---|---|
| Sitemap | Webbase tree + role simulation |
| Search | Full-text search and replace across nodes |
| Code-branch | Source Control — change log history |
| Folder | File Explorer — browse and edit public files in-browser |
| Bug | Debug (placeholder) |
| Cubes | Webbaselets (placeholder) |
| Cog | Settings — roles and datasources |
webbase → area / webbaselet / page → content / shortcut
Each node carries localized entries for name, description, documentation, keywords, and layout, plus per-role visibility settings.