feat(sirius-x): Sirius Studio web-builder + signed site uploads; shorter dashboard menu
Owners had no way to put a real page behind a name without running Sia
tooling themselves. Sirius Studio (studio.html, js/studio.js) embeds
GrapesJS (BSD-3, vendored under vendor/grapesjs so nothing loads from a
third party) with three starter templates; Publish exports one
self-contained index.html plus the editor project, uploads both to the
name's own folder bns/<name>/ on Sia, and sets the s3 record on chain if
the name does not point there yet. Drafts save to the same folder.
Gateway: /api/site/<name>[/<path>] — list, read-through, PUT and DELETE.
Every write carries a wallet signature over (name, path, body hash,
timestamp) that must recover to the current NFT owner, and writes are
confined to bns/<name>/ so no name can touch another name's bucket.
Dashboard menu is now Web-Builder, Domain names, My TLDs, Settings, Sign
out; Overview and Wallet folded into Domain names and Settings, Docs is a
link in Settings.
2026-09-17 01:35:21 +02:00
<!doctype html>
< html lang = "en" >
< head >
< meta charset = "utf-8" >
< meta name = "viewport" content = "width=device-width, initial-scale=1" >
< title > Sirius Studio — build the site for your name< / title >
< meta name = "description" content = "Sirius Studio: a drag-and-drop site builder for BCNR names. Pages live on Sia, the name on the chain — your keys, your site." >
< link rel = "icon" href = "./assets/favicon.svg" type = "image/svg+xml" >
< link href = "https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,400;9..144,600&family=DM+Sans:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel = "stylesheet" >
< link rel = "stylesheet" href = "./vendor/grapesjs/grapes.min.css?v=0.23.6" >
< style >
:root{
--bg:#050810; --panel:#141a24; --panel2:#0a0f1c; --line:rgba(255,255,255,.08);
--ink:#f1f4fa; --mut:#b8c2d4; --dim:#6a7488; --acid:#d6ff3d; --ok:#4fd1a5; --taken:#f6768a; --warn:#ffc75f;
--serif:'Fraunces',Georgia,serif; --sans:'DM Sans',system-ui,sans-serif; --mono:'JetBrains Mono',ui-monospace,monospace;
/* GrapesJS theme hooks */
--gjs-primary-color:#0e131b; --gjs-secondary-color:#b8c2d4; --gjs-tertiary-color:#d6ff3d; --gjs-quaternary-color:#d6ff3d;
--gjs-font-color:#f1f4fa; --gjs-main-dark-color:#0a0f1c; --gjs-main-light-color:#141a24;
}
*{box-sizing:border-box}
html,body{height:100%;margin:0}
body{background:var(--bg);color:var(--ink);font:14px/1.5 var(--sans);display:flex;flex-direction:column;overflow:hidden}
a{color:var(--acid)}
.bar{display:flex;align-items:center;gap:10px;padding:8px 14px;background:rgba(11,14,20,.95);border-bottom:1px solid var(--line);flex:none;flex-wrap:wrap}
.bar .brand{font-weight:600;color:var(--ink);text-decoration:none;font-size:15px;display:flex;align-items:center;gap:6px}
.bar .brand .g{color:var(--acid)}
.bar .name{font-family:var(--mono);font-size:14px;color:var(--ink);background:var(--panel);border:1px solid var(--line);padding:5px 10px;border-radius:8px}
.bar .name .tld{color:var(--acid)}
.bar .sp{flex:1}
.bar .st{font-size:12.5px;color:var(--dim);max-width:360px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.bar .st.ok{color:var(--ok)} .bar .st.err{color:var(--taken)} .bar .st.busy{color:var(--warn)}
fix(studio): open the page the name actually serves, not an empty folder
Sirius Studio only looked in its own folder, bns/<name>/. Every site
published the conventional way lives at bns/<label>/ (the s3 record),
or inline in the h record, so the editor opened those names as "new
site" with a template picker instead of the current build.
The gateway's site read gains a read-only ?src=live view that follows
the on-chain record: list and fetch from whatever bucket s3 points at,
or serve the h HTML as index.html. Writes are unchanged and still
confined to bns/<name>/.
The editor now starts from the live page when there is no draft:
relative image and link URLs are resolved against the public site URL,
stylesheets are inlined (cross-origin ones such as font CDNs are kept
as links and re-emitted on export), scripts dropped. When a draft
exists but the name serves something else, or index.html on Sia is
newer than the draft, a notice says so with a one-click import. An
"Import live site" button is always available. Verified with
aloevera.test, which is hosted at bns/aloevera/.
2026-09-20 01:22:21 +02:00
.notice{display:flex;align-items:center;gap:10px;flex-wrap:wrap;padding:8px 14px;font-size:13px;color:var(--ink);
background:rgba(255,199,95,.10);border-bottom:1px solid rgba(255,199,95,.35);flex:none}
.notice[hidden]{display:none}
.notice .x{margin-left:auto;background:none;border:0;color:var(--dim);font-size:18px;cursor:pointer;line-height:1}
feat(sirius-x): Sirius Studio web-builder + signed site uploads; shorter dashboard menu
Owners had no way to put a real page behind a name without running Sia
tooling themselves. Sirius Studio (studio.html, js/studio.js) embeds
GrapesJS (BSD-3, vendored under vendor/grapesjs so nothing loads from a
third party) with three starter templates; Publish exports one
self-contained index.html plus the editor project, uploads both to the
name's own folder bns/<name>/ on Sia, and sets the s3 record on chain if
the name does not point there yet. Drafts save to the same folder.
Gateway: /api/site/<name>[/<path>] — list, read-through, PUT and DELETE.
Every write carries a wallet signature over (name, path, body hash,
timestamp) that must recover to the current NFT owner, and writes are
confined to bns/<name>/ so no name can touch another name's bucket.
Dashboard menu is now Web-Builder, Domain names, My TLDs, Settings, Sign
out; Overview and Wallet folded into Domain names and Settings, Docs is a
link in Settings.
2026-09-17 01:35:21 +02:00
.btn{display:inline-flex;align-items:center;gap:6px;padding:7px 13px;border-radius:9px;background:#4b7bec;color:#fff;font:inherit;font-size:13px;border:none;cursor:pointer;text-decoration:none;line-height:1.2}
.btn.ghost{background:transparent;border:1px solid var(--line);color:var(--ink)}
.btn.acid{background:var(--acid);color:#0b0e14;font-weight:600}
.btn.small{padding:5px 10px;font-size:12px}
.btn:disabled{opacity:.45;cursor:not-allowed}
select.sel{padding:6px 28px 6px 10px;border-radius:9px;background:var(--panel);color:var(--ink);border:1px solid var(--line);font:inherit;font-size:13px}
feat(studio): AI assistant that runs on the user's own device
An Assistant drawer in Sirius Studio with two providers and no key, no
server and no spend. "This browser" runs an open model on the user's
GPU through WebGPU with WebLLM (vendored, Apache-2.0); weights download
once from the MLC mirror and stay in the browser cache. "Local
endpoint" talks to an OpenAI-compatible runtime on the user's machine
(Ollama, LM Studio), which unlocks larger models on a real GPU. Nothing
the user writes or builds leaves their device in either mode.
Three verbs: make a section, rewrite the selected text, restyle the
selection. The model returns HTML and CSS as data; Studio sanitises it
(no scripts, frames, handlers or imports) and inserts it through the
editor, with Undo. Model output is never executed.
The quantisation is chosen per GPU: q4f16 when the adapter exposes
shader-f16, q4f32 otherwise (Pascal-era cards lack it). Small models
often answer with bare HTML instead of JSON, so the parser accepts
both, prompts avoid literal placeholders one model echoed back, and an
out-of-memory or disposed runtime is reported as "pick a smaller
model" with the engine reset. Switching models starts a fresh worker.
Verified on an NVIDIA Pascal card: SmolLM2 360M rewrites text, Qwen2.5
Coder 0.5B builds a section; the 1.5B f32 build exceeded that card's
memory and now fails gracefully.
2026-09-20 15:22:34 +02:00
#editor{flex:1;min-height:0;display:flex;min-width:0}
#gjs{height:100%;flex:1;min-width:0}
/* assistant drawer */
.ai{width:340px;flex:none;display:flex;flex-direction:column;gap:8px;padding:12px 14px;background:#0e131b;border-left:1px solid var(--line);overflow:auto;font-size:13px}
.ai[hidden]{display:none}
.ai-head{display:flex;align-items:center;justify-content:space-between}
.ai-head b{font-size:14px}
.ai .x{background:none;border:0;color:var(--dim);font-size:20px;cursor:pointer;line-height:1}
.ai label{display:block;font-size:11px;letter-spacing:.08em;text-transform:uppercase;color:var(--dim);margin:6px 0 3px}
.ai select,.ai input,.ai textarea{width:100%;padding:8px 10px;border-radius:8px;border:1px solid rgba(255,255,255,.12);background:#070a12;color:var(--ink);font:inherit;font-size:13px}
.ai textarea{resize:vertical;min-height:72px}
.ai-hint{color:var(--dim);font-size:11.5px;line-height:1.4}
.ai-hint code{font-size:11px}
.ai-status{font-size:12px;color:var(--mut);padding:7px 10px;border-radius:8px;background:rgba(255,255,255,.04);border-left:3px solid rgba(255,255,255,.12);min-height:30px}
.ai-status.ok{border-left-color:var(--ok);color:var(--ok)} .ai-status.err{border-left-color:var(--taken);color:var(--taken)} .ai-status.busy{border-left-color:var(--warn)} .ai-status.warn{border-left-color:var(--warn);color:var(--warn)}
.ai-verbs{display:flex;flex-wrap:wrap;gap:6px}
.ai-target{font-size:11.5px;color:var(--dim);font-family:var(--mono);word-break:break-word}
.ai-out{flex:1;min-height:80px;max-height:40vh;margin:0;padding:8px 10px;background:#070a12;border:1px solid rgba(255,255,255,.08);border-radius:8px;font-family:var(--mono);font-size:11px;color:var(--mut);white-space:pre-wrap;word-break:break-word;overflow:auto}
.ai-actions{display:flex;gap:6px}
.bar .btn.on{background:rgba(214,255,61,.14);border-color:rgba(214,255,61,.4);color:var(--acid)}
@media (max-width:900px){.ai{position:fixed;right:0;top:0;bottom:0;width:min(340px,92vw);z-index:60;box-shadow:-12px 0 30px rgba(0,0,0,.5)}}
feat(studio): readable dark theme, resize handles, richer text tools, ready-made sections, more blocks
The editor panels were a muddy grey with pinkish text (4.7:1) because
the webpage preset injects its own demo palette after ours. That theme
is now switched off and the editor is themed through GrapesJS's CSS
variables: dark panels, near-white text (15:1 and better), acid accents,
readable inputs and toolbars.
Editing is closer to what people expect from Tilda: every box has drag
handles for width and height, the text toolbar gains size, colour,
highlight, alignment and heading controls, the font list has the site
families, and selecting anything opens the style panel. Nine ready-made
sections (hero, features, image+text, gallery, testimonial, pricing,
call to action, contact form, footer) drop in with their own styles.
Plugins vendored from npm (no CDN): forms, navbar, tabs, tooltip,
custom code, countdown, background styles, touch support; GrapesJS
itself is already current at 0.23.6. The basic blocks (columns, text,
image, video, map) had never loaded: the bundle registers itself as
gjs-blocks-basic, not grapesjs-blocks-basic. VERSIONS.txt records what
is vendored and how to update it.
2026-09-20 14:46:22 +02:00
/* Editor theme: GrapesJS 0.23 is themed through CSS variables. Dark panels,
near-white text (>= 12:1), acid accents. The preset's own mauve palette is
switched off in studio.js (useCustomTheme:false). */
:root{
--gjs-primary-color:#0e131b; /* panel backgrounds */
--gjs-secondary-color:#e7ebf2; /* panel text */
--gjs-tertiary-color:#d6ff3d; /* active buttons */
--gjs-quaternary-color:#d6ff3d; /* highlights, selection badge */
--gjs-main-color:#0e131b;
--gjs-main-dark-color:rgba(0,0,0,.35); /* inputs */
--gjs-main-light-color:rgba(255,255,255,.07);
--gjs-secondary-light-color:rgba(255,255,255,.82);
--gjs-secondary-dark-color:rgba(0,0,0,.3);
--gjs-font-color:#e7ebf2;
--gjs-font-color-active:#ffffff;
--gjs-light-border:rgba(255,255,255,.09);
--gjs-arrow-color:rgba(255,255,255,.8);
--gjs-color-highlight:#d6ff3d;
--gjs-font-size:.8rem;
--gjs-main-font:'DM Sans',system-ui,sans-serif;
}
.gjs-three-bg,.gjs-pn-btn.gjs-pn-active{color:#0b0e14 !important}
.gjs-pn-btn.gjs-pn-active{background:var(--acid);border-radius:6px}
feat(sirius-x): Sirius Studio web-builder + signed site uploads; shorter dashboard menu
Owners had no way to put a real page behind a name without running Sia
tooling themselves. Sirius Studio (studio.html, js/studio.js) embeds
GrapesJS (BSD-3, vendored under vendor/grapesjs so nothing loads from a
third party) with three starter templates; Publish exports one
self-contained index.html plus the editor project, uploads both to the
name's own folder bns/<name>/ on Sia, and sets the s3 record on chain if
the name does not point there yet. Drafts save to the same folder.
Gateway: /api/site/<name>[/<path>] — list, read-through, PUT and DELETE.
Every write carries a wallet signature over (name, path, body hash,
timestamp) that must recover to the current NFT owner, and writes are
confined to bns/<name>/ so no name can touch another name's bucket.
Dashboard menu is now Web-Builder, Domain names, My TLDs, Settings, Sign
out; Overview and Wallet folded into Domain names and Settings, Docs is a
link in Settings.
2026-09-17 01:35:21 +02:00
.gjs-pn-panel{border-color:var(--line)}
feat(studio): readable dark theme, resize handles, richer text tools, ready-made sections, more blocks
The editor panels were a muddy grey with pinkish text (4.7:1) because
the webpage preset injects its own demo palette after ours. That theme
is now switched off and the editor is themed through GrapesJS's CSS
variables: dark panels, near-white text (15:1 and better), acid accents,
readable inputs and toolbars.
Editing is closer to what people expect from Tilda: every box has drag
handles for width and height, the text toolbar gains size, colour,
highlight, alignment and heading controls, the font list has the site
families, and selecting anything opens the style panel. Nine ready-made
sections (hero, features, image+text, gallery, testimonial, pricing,
call to action, contact form, footer) drop in with their own styles.
Plugins vendored from npm (no CDN): forms, navbar, tabs, tooltip,
custom code, countdown, background styles, touch support; GrapesJS
itself is already current at 0.23.6. The basic blocks (columns, text,
image, video, map) had never loaded: the bundle registers itself as
gjs-blocks-basic, not grapesjs-blocks-basic. VERSIONS.txt records what
is vendored and how to update it.
2026-09-20 14:46:22 +02:00
.gjs-pn-views-container{box-shadow:none;border-left:1px solid var(--line)}
.gjs-block{min-height:78px;border:1px solid rgba(255,255,255,.08);border-radius:10px;margin:6px;padding:10px 6px;transition:border-color .12s,background .12s}
.gjs-block:hover{border-color:rgba(214,255,61,.45);background:rgba(214,255,61,.06)}
.gjs-block-label{font-size:11.5px;line-height:1.25;margin-top:6px}
.gjs-block svg{fill:#e7ebf2}
.gjs-block-category .gjs-title,.gjs-sm-sector-title,.gjs-layer-title{font-weight:600;letter-spacing:.02em}
.gjs-sm-sector .gjs-sm-property .gjs-sm-label,.gjs-trt-trait .gjs-label,.gjs-layer-name{color:#e7ebf2}
.gjs-field{border:1px solid rgba(255,255,255,.1);border-radius:6px}
.gjs-field:focus-within{border-color:rgba(214,255,61,.6)}
.gjs-field input,.gjs-field select,.gjs-field textarea{color:#fff}
.gjs-radio-item-label,.gjs-sm-btn{color:#e7ebf2}
.gjs-sm-btn{background:rgba(255,255,255,.08);border-radius:6px}
.gjs-clm-tag{background:rgba(214,255,61,.14);color:#d6ff3d}
.gjs-selected{outline:2px solid #d6ff3d !important}
.gjs-badge{background:#d6ff3d;color:#0b0e14}
.gjs-toolbar{background:#0e131b;border:1px solid rgba(255,255,255,.12);border-radius:8px}
.gjs-toolbar-item{color:#fff}
.gjs-rte-toolbar{background:#0e131b;border:1px solid rgba(255,255,255,.12);border-radius:8px}
.gjs-rte-action{color:#fff;border-right-color:rgba(255,255,255,.08)}
.gjs-rte-action select,.gjs-rte-action input[type=color]{background:#0e131b;color:#fff;border:1px solid rgba(255,255,255,.15);border-radius:4px;font:inherit;font-size:12px;cursor:pointer}
.gjs-rte-action input[type=color]{width:24px;height:22px;padding:0}
.gjs-resizer-h{border-color:#d6ff3d;background:#0b0e14;width:10px;height:10px}
.gjs-mdl-dialog{background:#141a24;color:#e7ebf2;border:1px solid var(--line)}
.gjs-mdl-header{border-bottom-color:var(--line)}
feat(sirius-x): Sirius Studio web-builder + signed site uploads; shorter dashboard menu
Owners had no way to put a real page behind a name without running Sia
tooling themselves. Sirius Studio (studio.html, js/studio.js) embeds
GrapesJS (BSD-3, vendored under vendor/grapesjs so nothing loads from a
third party) with three starter templates; Publish exports one
self-contained index.html plus the editor project, uploads both to the
name's own folder bns/<name>/ on Sia, and sets the s3 record on chain if
the name does not point there yet. Drafts save to the same folder.
Gateway: /api/site/<name>[/<path>] — list, read-through, PUT and DELETE.
Every write carries a wallet signature over (name, path, body hash,
timestamp) that must recover to the current NFT owner, and writes are
confined to bns/<name>/ so no name can touch another name's bucket.
Dashboard menu is now Web-Builder, Domain names, My TLDs, Settings, Sign
out; Overview and Wallet folded into Domain names and Settings, Docs is a
link in Settings.
2026-09-17 01:35:21 +02:00
.gjs-cv-canvas{background:#fff}
/* gate / picker overlays */
.overlay{position:fixed;inset:0;background:rgba(5,8,16,.92);backdrop-filter:blur(4px);z-index:100;display:flex;align-items:center;justify-content:center;padding:20px;overflow:auto}
.overlay[hidden]{display:none}
.sheet{background:var(--panel);border:1px solid var(--line);border-radius:16px;max-width:860px;width:100%;padding:26px 28px}
.sheet h2{font-family:var(--serif);margin:0 0 .3rem;font-size:1.5rem}
.sheet p{color:var(--mut);margin:.2rem 0 1rem}
.tpls{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:12px;margin-top:10px}
.tpl{background:var(--panel2);border:1px solid var(--line);border-radius:12px;padding:0;overflow:hidden;cursor:pointer;text-align:left;color:inherit;font:inherit;transition:border-color .12s}
.tpl:hover{border-color:rgba(214,255,61,.4)}
.tpl .prev{height:110px;background:#fff;display:flex;align-items:center;justify-content:center;font-family:var(--serif);color:#111;font-size:22px}
.tpl .prev.dark{background:#0b0e14;color:#d6ff3d}
.tpl .prev.warm{background:#fff4e6;color:#7a3b00}
.tpl .prev.blue{background:#0f2a4a;color:#e6f0ff}
.tpl b{display:block;padding:10px 12px 2px;font-size:14px}
.tpl span{display:block;padding:0 12px 12px;color:var(--dim);font-size:12px}
.steps{margin-top:12px;font-family:var(--mono);font-size:12px;color:var(--mut);background:#0e131b;border:1px solid var(--line);border-radius:8px;padding:10px 12px;max-height:160px;overflow:auto}
.steps div::before{content:"› ";color:var(--acid)}
.row{display:flex;gap:10px;flex-wrap:wrap;align-items:center;margin-top:14px}
.row.end{justify-content:flex-end}
.muted{color:var(--mut);font-size:13px}
code{font-family:var(--mono);background:#0e131b;border:1px solid var(--line);border-radius:6px;padding:1px 6px;font-size:12px}
< / style >
feat(studio): AI assistant that runs on the user's own device
An Assistant drawer in Sirius Studio with two providers and no key, no
server and no spend. "This browser" runs an open model on the user's
GPU through WebGPU with WebLLM (vendored, Apache-2.0); weights download
once from the MLC mirror and stay in the browser cache. "Local
endpoint" talks to an OpenAI-compatible runtime on the user's machine
(Ollama, LM Studio), which unlocks larger models on a real GPU. Nothing
the user writes or builds leaves their device in either mode.
Three verbs: make a section, rewrite the selected text, restyle the
selection. The model returns HTML and CSS as data; Studio sanitises it
(no scripts, frames, handlers or imports) and inserts it through the
editor, with Undo. Model output is never executed.
The quantisation is chosen per GPU: q4f16 when the adapter exposes
shader-f16, q4f32 otherwise (Pascal-era cards lack it). Small models
often answer with bare HTML instead of JSON, so the parser accepts
both, prompts avoid literal placeholders one model echoed back, and an
out-of-memory or disposed runtime is reported as "pick a smaller
model" with the engine reset. Switching models starts a fresh worker.
Verified on an NVIDIA Pascal card: SmolLM2 360M rewrites text, Qwen2.5
Coder 0.5B builds a section; the 1.5B f32 build exceeded that card's
memory and now fails gracefully.
2026-09-20 15:22:34 +02:00
< script src = "./js/i18n.js?v=20260920c" > < / script >
feat(sirius-x): Sirius Studio web-builder + signed site uploads; shorter dashboard menu
Owners had no way to put a real page behind a name without running Sia
tooling themselves. Sirius Studio (studio.html, js/studio.js) embeds
GrapesJS (BSD-3, vendored under vendor/grapesjs so nothing loads from a
third party) with three starter templates; Publish exports one
self-contained index.html plus the editor project, uploads both to the
name's own folder bns/<name>/ on Sia, and sets the s3 record on chain if
the name does not point there yet. Drafts save to the same folder.
Gateway: /api/site/<name>[/<path>] — list, read-through, PUT and DELETE.
Every write carries a wallet signature over (name, path, body hash,
timestamp) that must recover to the current NFT owner, and writes are
confined to bns/<name>/ so no name can touch another name's bucket.
Dashboard menu is now Web-Builder, Domain names, My TLDs, Settings, Sign
out; Overview and Wallet folded into Domain names and Settings, Docs is a
link in Settings.
2026-09-17 01:35:21 +02:00
< / head >
< body >
< div class = "bar" >
< a class = "brand" href = "./portal.html#studio" > ⭐ < span class = "g" > Sirius< / span > Studio< / a >
< span class = "name" id = "site-name" > —< / span >
< select class = "sel" id = "tpl-select" title = "Start from a template" >
< option value = "" > Templates…< / option >
< option value = "landing" > Landing page< / option >
< option value = "profile" > Profile / link hub< / option >
< option value = "business" > Business one-pager< / option >
< option value = "blank" > Blank page< / option >
< / select >
< button class = "btn ghost small" id = "btn-preview" title = "Preview the exported page in a new tab" > Preview< / button >
fix(studio): open the page the name actually serves, not an empty folder
Sirius Studio only looked in its own folder, bns/<name>/. Every site
published the conventional way lives at bns/<label>/ (the s3 record),
or inline in the h record, so the editor opened those names as "new
site" with a template picker instead of the current build.
The gateway's site read gains a read-only ?src=live view that follows
the on-chain record: list and fetch from whatever bucket s3 points at,
or serve the h HTML as index.html. Writes are unchanged and still
confined to bns/<name>/.
The editor now starts from the live page when there is no draft:
relative image and link URLs are resolved against the public site URL,
stylesheets are inlined (cross-origin ones such as font CDNs are kept
as links and re-emitted on export), scripts dropped. When a draft
exists but the name serves something else, or index.html on Sia is
newer than the draft, a notice says so with a one-click import. An
"Import live site" button is always available. Verified with
aloevera.test, which is hosted at bns/aloevera/.
2026-09-20 01:22:21 +02:00
< button class = "btn ghost small" id = "btn-import" title = "Replace the editor contents with the page the name serves right now" hidden > ↓ Import live site< / button >
feat(studio): AI assistant that runs on the user's own device
An Assistant drawer in Sirius Studio with two providers and no key, no
server and no spend. "This browser" runs an open model on the user's
GPU through WebGPU with WebLLM (vendored, Apache-2.0); weights download
once from the MLC mirror and stay in the browser cache. "Local
endpoint" talks to an OpenAI-compatible runtime on the user's machine
(Ollama, LM Studio), which unlocks larger models on a real GPU. Nothing
the user writes or builds leaves their device in either mode.
Three verbs: make a section, rewrite the selected text, restyle the
selection. The model returns HTML and CSS as data; Studio sanitises it
(no scripts, frames, handlers or imports) and inserts it through the
editor, with Undo. Model output is never executed.
The quantisation is chosen per GPU: q4f16 when the adapter exposes
shader-f16, q4f32 otherwise (Pascal-era cards lack it). Small models
often answer with bare HTML instead of JSON, so the parser accepts
both, prompts avoid literal placeholders one model echoed back, and an
out-of-memory or disposed runtime is reported as "pick a smaller
model" with the engine reset. Switching models starts a fresh worker.
Verified on an NVIDIA Pascal card: SmolLM2 360M rewrites text, Qwen2.5
Coder 0.5B builds a section; the 1.5B f32 build exceeded that card's
memory and now fails gracefully.
2026-09-20 15:22:34 +02:00
< button class = "btn ghost small" id = "btn-ai" title = "AI assistant — runs on your own device" > ✨ Assistant< / button >
feat(sirius-x): Sirius Studio web-builder + signed site uploads; shorter dashboard menu
Owners had no way to put a real page behind a name without running Sia
tooling themselves. Sirius Studio (studio.html, js/studio.js) embeds
GrapesJS (BSD-3, vendored under vendor/grapesjs so nothing loads from a
third party) with three starter templates; Publish exports one
self-contained index.html plus the editor project, uploads both to the
name's own folder bns/<name>/ on Sia, and sets the s3 record on chain if
the name does not point there yet. Drafts save to the same folder.
Gateway: /api/site/<name>[/<path>] — list, read-through, PUT and DELETE.
Every write carries a wallet signature over (name, path, body hash,
timestamp) that must recover to the current NFT owner, and writes are
confined to bns/<name>/ so no name can touch another name's bucket.
Dashboard menu is now Web-Builder, Domain names, My TLDs, Settings, Sign
out; Overview and Wallet folded into Domain names and Settings, Docs is a
link in Settings.
2026-09-17 01:35:21 +02:00
< span class = "sp" > < / span >
< span class = "st" id = "status" > Loading…< / span >
< button class = "btn ghost small" id = "btn-draft" disabled > Save draft< / button >
< button class = "btn acid small" id = "btn-publish" disabled > Publish to Sia →< / button >
< a class = "btn ghost small" id = "btn-view" href = "#" target = "_blank" rel = "noopener" hidden > View site →< / a >
< / div >
fix(studio): open the page the name actually serves, not an empty folder
Sirius Studio only looked in its own folder, bns/<name>/. Every site
published the conventional way lives at bns/<label>/ (the s3 record),
or inline in the h record, so the editor opened those names as "new
site" with a template picker instead of the current build.
The gateway's site read gains a read-only ?src=live view that follows
the on-chain record: list and fetch from whatever bucket s3 points at,
or serve the h HTML as index.html. Writes are unchanged and still
confined to bns/<name>/.
The editor now starts from the live page when there is no draft:
relative image and link URLs are resolved against the public site URL,
stylesheets are inlined (cross-origin ones such as font CDNs are kept
as links and re-emitted on export), scripts dropped. When a draft
exists but the name serves something else, or index.html on Sia is
newer than the draft, a notice says so with a one-click import. An
"Import live site" button is always available. Verified with
aloevera.test, which is hosted at bns/aloevera/.
2026-09-20 01:22:21 +02:00
< div class = "notice" id = "notice" hidden > < span id = "notice-text" > < / span > < button class = "btn ghost small" id = "notice-import" > Import the live site< / button > < button class = "x" id = "notice-close" title = "dismiss" > × < / button > < / div >
feat(studio): AI assistant that runs on the user's own device
An Assistant drawer in Sirius Studio with two providers and no key, no
server and no spend. "This browser" runs an open model on the user's
GPU through WebGPU with WebLLM (vendored, Apache-2.0); weights download
once from the MLC mirror and stay in the browser cache. "Local
endpoint" talks to an OpenAI-compatible runtime on the user's machine
(Ollama, LM Studio), which unlocks larger models on a real GPU. Nothing
the user writes or builds leaves their device in either mode.
Three verbs: make a section, rewrite the selected text, restyle the
selection. The model returns HTML and CSS as data; Studio sanitises it
(no scripts, frames, handlers or imports) and inserts it through the
editor, with Undo. Model output is never executed.
The quantisation is chosen per GPU: q4f16 when the adapter exposes
shader-f16, q4f32 otherwise (Pascal-era cards lack it). Small models
often answer with bare HTML instead of JSON, so the parser accepts
both, prompts avoid literal placeholders one model echoed back, and an
out-of-memory or disposed runtime is reported as "pick a smaller
model" with the engine reset. Switching models starts a fresh worker.
Verified on an NVIDIA Pascal card: SmolLM2 360M rewrites text, Qwen2.5
Coder 0.5B builds a section; the 1.5B f32 build exceeded that card's
memory and now fails gracefully.
2026-09-20 15:22:34 +02:00
< div id = "editor" > < div id = "gjs" > < / div >
< aside class = "ai" id = "ai" hidden >
< div class = "ai-head" > < b > ✨ Assistant< / b > < button class = "x" id = "ai-close" title = "close" > × < / button > < / div >
< p class = "ai-hint" style = "margin:0" > Runs on your own device. Nothing you write or build is sent to Sirius.X or to any AI vendor.< / p >
< label > Runs on< / label >
< select id = "ai-provider" >
< option value = "webllm" > This browser — your GPU, private< / option >
< option value = "local" > Local endpoint — Ollama, LM Studio< / option >
< / select >
< div id = "ai-webllm" >
< label > Model< / label >
< select id = "ai-model" > < / select >
< div class = "ai-hint" > Downloads once, then stays in the browser cache. Needs WebGPU (current Chrome, Edge, Firefox, Safari).< / div >
< div class = "ai-actions" style = "margin-top:6px" > < button class = "btn ghost small" id = "ai-load" > Load model< / button > < / div >
< / div >
< div id = "ai-local" hidden >
< label > Endpoint< / label >
< input type = "text" id = "ai-url" value = "http://localhost:11434/v1" spellcheck = "false" >
< label > Model< / label >
< input type = "text" id = "ai-lmodel" list = "ai-lmodels" placeholder = "qwen2.5-coder:7b" spellcheck = "false" > < datalist id = "ai-lmodels" > < / datalist >
< div class = "ai-hint" > Allow this site in your runtime first, e.g. < code > OLLAMA_ORIGINS=https://silentmode.st ollama serve< / code > . LM Studio: enable CORS in its server settings (port 1234).< / div >
< div class = "ai-actions" style = "margin-top:6px" > < button class = "btn ghost small" id = "ai-connect" > Connect< / button > < / div >
< / div >
< div class = "ai-status" id = "ai-status" > —< / div >
< label > What do you want?< / label >
< textarea id = "ai-prompt" placeholder = "A hero section for a bakery in Athens, warm colours, one button that says Order" > < / textarea >
< div class = "ai-verbs" >
< button class = "btn acid small" data-verb = "section" > Make a section< / button >
< button class = "btn ghost small" data-verb = "text" > Rewrite selected text< / button >
< button class = "btn ghost small" data-verb = "style" > Restyle selection< / button >
< / div >
< div class = "ai-target" id = "ai-target" > Nothing selected< / div >
< pre class = "ai-out" id = "ai-out" > < / pre >
< div class = "ai-actions" > < button class = "btn ghost small" id = "ai-undo" hidden > Undo last change< / button > < button class = "btn ghost small" id = "ai-stop" hidden > Stop< / button > < / div >
< / aside > < / div >
feat(sirius-x): Sirius Studio web-builder + signed site uploads; shorter dashboard menu
Owners had no way to put a real page behind a name without running Sia
tooling themselves. Sirius Studio (studio.html, js/studio.js) embeds
GrapesJS (BSD-3, vendored under vendor/grapesjs so nothing loads from a
third party) with three starter templates; Publish exports one
self-contained index.html plus the editor project, uploads both to the
name's own folder bns/<name>/ on Sia, and sets the s3 record on chain if
the name does not point there yet. Drafts save to the same folder.
Gateway: /api/site/<name>[/<path>] — list, read-through, PUT and DELETE.
Every write carries a wallet signature over (name, path, body hash,
timestamp) that must recover to the current NFT owner, and writes are
confined to bns/<name>/ so no name can touch another name's bucket.
Dashboard menu is now Web-Builder, Domain names, My TLDs, Settings, Sign
out; Overview and Wallet folded into Domain names and Settings, Docs is a
link in Settings.
2026-09-17 01:35:21 +02:00
<!-- sign - in gate -->
< div class = "overlay" id = "gate" hidden >
< div class = "sheet" style = "max-width:520px" >
< h2 > Sign in first< / h2 >
< p > Sirius Studio publishes with your wallet's key. Sign in on the dashboard, then come back to this name.< / p >
< div class = "row end" > < a class = "btn acid" id = "gate-link" href = "./portal.html" > Open the dashboard →< / a > < / div >
< / div >
< / div >
<!-- template picker for a fresh site -->
< div class = "overlay" id = "picker" hidden >
< div class = "sheet" >
< h2 > Build the site for < span id = "picker-name" style = "font-family:var(--mono);color:var(--acid)" > —< / span > < / h2 >
< p > Pick a starting point. Everything is editable — drag blocks in from the right, click any text to change it. Nothing leaves your browser until you press Publish; then the page is stored on Sia and the name points at it.< / p >
< div class = "tpls" >
< button class = "tpl" data-tpl = "landing" > < div class = "prev" > Hello, world< / div > < b > Landing page< / b > < span > Hero, three features, call to action.< / span > < / button >
< button class = "tpl" data-tpl = "profile" > < div class = "prev dark" > @you< / div > < b > Profile / link hub< / b > < span > Avatar, bio and a stack of links.< / span > < / button >
< button class = "tpl" data-tpl = "business" > < div class = "prev warm" > Open today< / div > < b > Business one-pager< / b > < span > About, services, hours, contact.< / span > < / button >
< button class = "tpl" data-tpl = "blank" > < div class = "prev blue" > —< / div > < b > Blank page< / b > < span > Start from nothing.< / span > < / button >
< / div >
< div class = "row end" > < a class = "btn ghost" href = "./portal.html#studio" > Back to dashboard< / a > < / div >
< / div >
< / div >
<!-- publish dialog -->
< div class = "overlay" id = "pub" hidden >
< div class = "sheet" style = "max-width:620px" >
< h2 > Publish < span id = "pub-name" style = "font-family:var(--mono);color:var(--acid)" > —< / span > < / h2 >
< p id = "pub-intro" > The page and its assets are uploaded to the name's folder on Sia, signed with your key. If the name does not point at that folder yet, one on-chain update sets it (a few cents of chain dust).< / p >
< div class = "steps" id = "pub-steps" > < / div >
< div class = "row end" >
< button class = "btn ghost" id = "pub-close" > Close< / button >
< a class = "btn acid" id = "pub-view" href = "#" target = "_blank" rel = "noopener" hidden > View site →< / a >
< / div >
< / div >
< / div >
< script type = "importmap" >
{ "imports": { "@bitauth/libauth": "https://silentmode.st/js/libauth.js" } }
< / script >
< script src = "./js/session.js?v=20260917dash" > < / script >
< script src = "./vendor/grapesjs/grapes.min.js?v=0.23.6" > < / script >
feat(studio): readable dark theme, resize handles, richer text tools, ready-made sections, more blocks
The editor panels were a muddy grey with pinkish text (4.7:1) because
the webpage preset injects its own demo palette after ours. That theme
is now switched off and the editor is themed through GrapesJS's CSS
variables: dark panels, near-white text (15:1 and better), acid accents,
readable inputs and toolbars.
Editing is closer to what people expect from Tilda: every box has drag
handles for width and height, the text toolbar gains size, colour,
highlight, alignment and heading controls, the font list has the site
families, and selecting anything opens the style panel. Nine ready-made
sections (hero, features, image+text, gallery, testimonial, pricing,
call to action, contact form, footer) drop in with their own styles.
Plugins vendored from npm (no CDN): forms, navbar, tabs, tooltip,
custom code, countdown, background styles, touch support; GrapesJS
itself is already current at 0.23.6. The basic blocks (columns, text,
image, video, map) had never loaded: the bundle registers itself as
gjs-blocks-basic, not grapesjs-blocks-basic. VERSIONS.txt records what
is vendored and how to update it.
2026-09-20 14:46:22 +02:00
< script src = "./vendor/grapesjs/blocks-basic.js?v=1.0.2b" > < / script >
< script src = "./vendor/grapesjs/preset-webpage.js?v=1.0.3b" > < / script >
< script src = "./vendor/grapesjs/plugin-forms.js?v=2.0.6" > < / script >
< script src = "./vendor/grapesjs/navbar.js?v=1.0.2" > < / script >
< script src = "./vendor/grapesjs/tabs.js?v=1.0.6" > < / script >
< script src = "./vendor/grapesjs/tooltip.js?v=0.1.8" > < / script >
< script src = "./vendor/grapesjs/custom-code.js?v=1.0.2" > < / script >
< script src = "./vendor/grapesjs/countdown.js?v=1.0.2" > < / script >
< script src = "./vendor/grapesjs/style-bg.js?v=2.0.2" > < / script >
< script src = "./vendor/grapesjs/touch.js?v=0.1.1" > < / script >
feat(studio): AI assistant that runs on the user's own device
An Assistant drawer in Sirius Studio with two providers and no key, no
server and no spend. "This browser" runs an open model on the user's
GPU through WebGPU with WebLLM (vendored, Apache-2.0); weights download
once from the MLC mirror and stay in the browser cache. "Local
endpoint" talks to an OpenAI-compatible runtime on the user's machine
(Ollama, LM Studio), which unlocks larger models on a real GPU. Nothing
the user writes or builds leaves their device in either mode.
Three verbs: make a section, rewrite the selected text, restyle the
selection. The model returns HTML and CSS as data; Studio sanitises it
(no scripts, frames, handlers or imports) and inserts it through the
editor, with Undo. Model output is never executed.
The quantisation is chosen per GPU: q4f16 when the adapter exposes
shader-f16, q4f32 otherwise (Pascal-era cards lack it). Small models
often answer with bare HTML instead of JSON, so the parser accepts
both, prompts avoid literal placeholders one model echoed back, and an
out-of-memory or disposed runtime is reported as "pick a smaller
model" with the engine reset. Switching models starts a fresh worker.
Verified on an NVIDIA Pascal card: SmolLM2 360M rewrites text, Qwen2.5
Coder 0.5B builds a section; the 1.5B f32 build exceeded that card's
memory and now fails gracefully.
2026-09-20 15:22:34 +02:00
< script type = "module" src = "./js/studio.js?v=20260920ai" > < / script >
feat(sirius-x): Sirius Studio web-builder + signed site uploads; shorter dashboard menu
Owners had no way to put a real page behind a name without running Sia
tooling themselves. Sirius Studio (studio.html, js/studio.js) embeds
GrapesJS (BSD-3, vendored under vendor/grapesjs so nothing loads from a
third party) with three starter templates; Publish exports one
self-contained index.html plus the editor project, uploads both to the
name's own folder bns/<name>/ on Sia, and sets the s3 record on chain if
the name does not point there yet. Drafts save to the same folder.
Gateway: /api/site/<name>[/<path>] — list, read-through, PUT and DELETE.
Every write carries a wallet signature over (name, path, body hash,
timestamp) that must recover to the current NFT owner, and writes are
confined to bns/<name>/ so no name can touch another name's bucket.
Dashboard menu is now Web-Builder, Domain names, My TLDs, Settings, Sign
out; Overview and Wallet folded into Domain names and Settings, Docs is a
link in Settings.
2026-09-17 01:35:21 +02:00
< / body >
< / html >