The website had one control that wrote to the server: an Appearance panel for editing your theme. Nothing else about a profile is editable there — links, exposures and sharing are all `devsite` commands — so the panel was the odd one out, and a theme is no more a browser concern than an exposure is. Removed. `devsite theme set|show|clear|properties` was always the other half of this and is now the whole of it. The website reads; the CLI writes. The one exception stays where it has to: claiming a handle happens in the browser, because that is where signing in finishes. /api/theme keeps its GET and PUT — they are what the CLI talks to. Their auth is unchanged, and deliberately: /api/resources accepts a session cookie too, so "CLI only" is a statement about where the controls live, not a new restriction on who may call what. `is_owner` goes with it. It existed to decide whether to draw the panel, and nothing reads it now — what an owner sees that others do not is already carried by the entries themselves, and by the "shared with me" list that is populated for them alone.
- commit
- 06bd0da6292b57ea10a00e9128d0685f4673403e
- parent
- cb8d53952fb75bcb4a503f83344fd78406c364b0
- author
- Dami <dami.etoile@gmail.com>
| M | crates/ | 6 | ++- |
| M | docs/ | 9 | +++-- |
| M | web/ | 57 | +++--------------------------- |
@@ -163,7 +163,6 @@ pub struct ProfileEntry {
163163 164164 pub struct ProfileResponse {165165 pub handle: String,166- pub is_owner: bool,167166 pub entries: Vec<ProfileEntry>,168167 pub shared_with_me: Vec<ProfileEntry>,169168 /// The owner's theme: validated `--pico-*` assignments, in the order they@@ -523,9 +522,12 @@ async fn profile(
523522 None => Vec::new(),524523 };525524 525+ // No `is_owner`: it existed to decide whether to draw the theme editor, and526+ // the website no longer writes anything. What the owner sees that others do527+ // not is already expressed by the entries themselves — private resources,528+ // and the "shared with me" list, which is populated for the owner alone.526529 Ok(Json(ProfileResponse {527530 handle,528- is_owner: viewer == Some(owner.id),529531 entries,530532 shared_with_me,531533 theme,@@ -61,9 +61,6 @@ changes here and changes to the whitelist belong in the same commit.
6161 </section>6262 <!-- data-visibility is one of: public · private · shared · shared-with-me -->6363 </article>64-65- <!-- owner only -->66- <details class="appearance">…theme editor…</details>6764 </main>6865 6966 <dialog id="viewer">…the service, in a sandboxed iframe…</dialog>@@ -130,7 +127,11 @@ you visit cannot use its theme to disguise itself as another part of the site.
130127 131128 ## Setting one132129 133-From the website, on your own profile, under **Appearance**. Or:130+From the CLI, and only from the CLI. The website is where a profile is read, not131+where it is written — links, exposures, sharing and themes are all set with132+`devsite`, and a theme is no more a browser concern than an exposure is. The one133+exception is claiming a handle, which has to happen in the browser because that134+is where signing in finishes.134135 135136 ```bash136137 devsite theme properties # what you may set@@ -1,5 +1,11 @@
11 // dev.site — profile rendering, Shoo sign-in, and opening a local service over Iroh.22 //3+// The website reads; `devsite` writes. Links, exposures, sharing and themes are4+// all set from the CLI, so the only thing here that changes server state is5+// claiming a handle — which has to happen in the browser because that is where6+// you finish signing in. Anything else that mutates a profile belongs in the7+// CLI, next to the rest of it.8+//39 // The markup this file produces is a contract, not an implementation detail: a410 // profile's theme is a list of --pico-* assignments that only mean anything511 // against the elements below. Keep it semantic, keep it documented, and change@@ -263,57 +269,6 @@ function renderProfile(profile) {
263269 }264270 265271 main.append(article);266- if (profile.is_owner) main.append(appearanceEditor(profile));267-}268-269-/// The theme editor, on your own profile only.270-///271-/// It deliberately shows the stored text rather than a set of colour pickers:272-/// the thing being edited really is CSS, and the server's refusals are specific273-/// enough to be worth reading.274-function appearanceEditor(profile) {275- const details = document.createElement('details');276- details.className = 'appearance';277- details.innerHTML = `278- <summary>Appearance</summary>279- <form>280- <label for="theme-css">281- Pico variables, as declarations. Everything else is refused.282- <textarea id="theme-css" name="css" rows="8" spellcheck="false"283- placeholder="--devsite-scheme: dark; --pico-primary: #7b3fe4; --pico-border-radius: 0.5rem;"></textarea>284- </label>285- <small id="theme-note">286- <a href="/api/theme/properties" target="_blank" rel="noopener">What you may set</a>287- </small>288- <fieldset role="group">289- <button type="submit">Save</button>290- <button type="button" class="secondary outline" id="theme-clear">Clear</button>291- </fieldset>292- </form>`;293-294- const form = details.querySelector('form');295- const field = details.querySelector('#theme-css');296- const note = details.querySelector('#theme-note');297- field.value = profile.theme298- .map((d) => `${d.property}: ${d.value};`)299- .join('\n');300-301- const save = async (css) => {302- try {303- const saved = await api('/api/theme', { method: 'PUT', body: JSON.stringify({ css }) });304- field.value = saved.css.trimEnd();305- field.removeAttribute('aria-invalid');306- note.innerHTML = '<span class="ok">Saved.</span>';307- applyTheme(profile.handle, saved.theme);308- } catch (err) {309- field.setAttribute('aria-invalid', 'true');310- note.innerHTML = `<span class="error">${esc(err.message)}</span>`;311- }312- };313-314- form.addEventListener('submit', (e) => { e.preventDefault(); save(field.value); });315- details.querySelector('#theme-clear').addEventListener('click', () => save(''));316- return details;317272 }318273 319274 // -- opening a service ---------------------------------------------------------