Published spaces: publish from Space info (web)

Merged
CA
5d ago
+859-11

Stacked on #160 (publishing server), which is stacked on #158. Merge those first.

Phase 2 of published spaces: the web app's Published section in Space info. It's the same page in the Mac app, which opens the server's own.

What

  • Registry: published gets a Section and the same canTurnOn rule as sharing: never the default space, and only its owner once shared.
  • Off (owner): a one-line explanation and Publish. It sends origin = location.origin, then reloads the space list so the trait, its glyph and the lock rules (§7.8) update everywhere. Locked notes refuse with their count: "Unlock its N locked notes to publish it."
  • On (owner):
    • The address as host/@ plus the handle, edited in place, with Open and Copy.
    • Changing the handle asks first, because the old address isn't redirected. Escape puts it back. A taken or invalid handle shows its error under it.
    • Custom CSS in a disclosure: a monospace textarea saved with Save, plus a hint about @layer and the CSS variables.
    • Stop publishing…, with a confirm in place: "The site goes offline. Its address stays this space's."
  • Members see the trait's summary and nothing to change. A trait's problem ("Publishing failed") shows in the section, since it's no longer a row.
  • api/spaces.ts: a publishing client (get, put, remove) and the PublishSettings type.
  • Dev proxy: Vite proxies /@<handle>/ to notesd, like /api, so a site opens from the dev server and preview. The pattern leaves Vite's own /@vite/, /@fs/, /@id/ and /@react-refresh alone.
  • Docs: a new guide, docs/guides/using/publishing.md, linked from the docs index; and an "Apps" bullet in architecture §7.10.

Decisions

  • Origin: it's sent only when publishing is first turned on. The guide says to publish from the address people should use. Custom domains (phase 3) replace this.
  • Old handles: no redirect from an old handle. The confirm warns instead, since a redirect would mean keeping old handles reserved forever.
  • CSS preview: none. You save, then open the site.

Not in this PR

Custom domains (phase 3), and publishing on Android and iOS (phase 4). Both already show the trait and refuse locked notes by it.

Tests

  • Component tests (test/publishing.test.tsx, against a real notesd):
    • publishing sends this app's origin and updates the trait;
    • the locked-notes refusal;
    • the default space isn't offered;
    • changing the handle, confirmed;
    • Escape puts the handle back, and a taken handle shows its error;
    • custom CSS saves only on Save;
    • Stop publishing keeps the handle;
    • a member's view;
    • the section shows what the server answered when the space list can't be refreshed;
    • Stop publishing stays open to retry when it fails.
  • Pinned tests updated: traits.test.tsx (the registry now offers published) and spaces.test.tsx (Published is a section, and its problem shows there).
  • E2E (e2e/publishing.spec.ts, Chromium): publish from Space info, open the site in a browser with no session, follow a post and its tag, stop publishing, and get 404.
  • mise run lint, typecheck, test and test:e2e: all green (web 1135, e2e 10, Go, sync engine).

Summary by cubic

Phase 2 of published spaces: the web app's Published section in Space info, where a space's owner turns it into a public website, same page as the Mac app.

  • Off, publishing sends this app's origin and reloads the space list; locked notes refuse with their count, and the default space isn't offered.
  • On, the address shows with the handle edited in place (asked first, since old addresses aren't redirected), custom CSS saved on Save, and Stop publishing.
  • The section shows what the server answered until the list changes; a failed Stop keeps its confirm open to retry.
  • Members see the address only; a trait's problem shows in its section.
  • Adds a publishing client (get/put/remove), a PublishSettings type, and a Vite dev proxy forwarding /@<handle>/ to notesd.
  • Docs: a Publishing a space guide, and an Apps note in §7.10.