mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-28 12:04:41 +01:00
The exposure lifecycle was covered end to end, but nothing asserted the two surfaces a user actually sees: what the API serializes as a runtime service's canonical `url`, and what the control bar renders as a launch link. Both are where a regression would silently reintroduce `http://paperclip-dev:<port>`. Serialization (`svc.list` and `svc.listOverview`, the workspace overview that feeds the launch links): a `ready` exposure serializes the tailnet HTTPS URL on both the runtime service and the overview's `primaryService`, and a `pending` one serializes `url: null` even though the row still records its loopback `backendUrl` — the HTTP backend must never appear in a serialized DTO. Also asserts the server-private lease handle is not serialized. UI: a ready managed runtime renders every anchor at the tailnet HTTPS URL with the port still visible (the port is what makes a preview reachable), copies that same URL to the clipboard, and advertises no `http://` URL in any href, title, or visible text; a pending exposure renders no anchor at all. Negative-controlled by swapping in `http://paperclip-dev:45439`, which the guard catches. The `http://` guard is scoped to hrefs, titles, and text rather than raw innerHTML, because every inline SVG carries an `xmlns="http://www.w3.org/2000/svg"`.
@paperclipai/ui
Published static assets for the Paperclip board UI.
What gets published
The npm package contains the production build under dist/. It does not ship the UI source tree or workspace-only dependencies.
Storybook
Storybook config, stories, and fixtures live under ui/storybook/.
pnpm --filter @paperclipai/ui storybook
pnpm --filter @paperclipai/ui build-storybook
Typical use
Install the package, then serve or copy the built files from node_modules/@paperclipai/ui/dist.