FabricFabric
Features

Design Collaboration

Share a design with stakeholders by clicking Publish — they get a public URL, leave pin-style comments without an account, and your chat auto-syncs them as amber pins so the agent can iterate.

The design workflow is built around a review loop: designer iterates locally → publishes a temporary public URL → reviewers leave pin-style comments in their browser → comments sync back into the chat → agent acts on them. No accounts, no plug-ins, no mailing list.

This page covers the collaborative side. For the local design loop see Design Workflow.

End-to-end flow

graph LR
  D[Designer] -->|build| Bundle[Bundle on disk]
  Bundle -->|Publish button| W[(Cloudflare Worker /d/<id>)]
  W -->|public URL| R[Reviewer's browser]
  R -->|💬 Comment| W
  W -->|auto-poll 30s| Block[site-preview block]
  Block -->|→ chat| Chat[Designer's chat]
  Chat --> A[Agent edits bundle]
  A --> Bundle

Publishing

Click Publish in the site-preview header. ~1–3 seconds later:

  • The button turns into a green 🟢 Live chip that opens the public URL.
  • The URL is copied to your clipboard.
  • A green banner shows the URL with an open action.

The published bundle:

  • Lives at https://agents.fabric.pro/d/<id>/ (or <id>/<some-asset> for nested assets).
  • Has a default 7-day TTL (configurable up to 30 days via the publish_design agent tool).
  • Is served with a strict CSP (default-src 'self', no third-party scripts, no framing from outside *.fabric.pro).
  • Auto-injects two scripts before </body>: a subtle scrollbar style and the public comment bridge (see below).

Limits enforced by the worker:

  • 25 MiB total bundle size
  • 30 days max TTL
  • 4 KB per comment
  • 256 KB per bundle worth of comments (≈ 64 typical comments)

What reviewers see

The reviewer opens the URL in any browser. The design renders normally, plus a floating button bottom-right:

┌─────────────────────────────┐
│                             │
│  [Your design]              │
│                             │
│                             │
│                             │
│                  [💬 Comment]│
└─────────────────────────────┘

Click 💬 Comment → cursor becomes a crosshair → hover any element shows a purple outline → click → modal opens:

┌──────────────────────────────────┐
│ Leave a comment                  │
│ on .hero h1 — "Welcome to..."    │
│                                  │
│ [ Your name (optional)         ] │
│ ┌──────────────────────────────┐ │
│ │ What would you change?       │ │
│ │ More breathing room around   │ │
│ │ the headline                 │ │
│ │                              │ │
│ └──────────────────────────────┘ │
│         [ Cancel ]  [ Send ]     │
└──────────────────────────────────┘

After Send:

  • Their pin (numbered, amber) appears immediately on the live page.
  • Anyone else viewing the URL sees it on their next 30-second poll.
  • A POST /d/api/<id>/comments is appended to the bundle's _comments.jsonl in R2.

No account, no auth, no email. The point is to remove every barrier between "someone has feedback" and "the feedback is captured at the right pixel."

What the designer sees

The site-preview block in the desktop chat auto-polls /d/api/<id>/comments every 30 seconds (first poll fires 5 seconds after the published block mounts). New comments appear as:

  • Amber pins overlaid on the local preview at the click point.
  • Side-panel rows with the comment text, the reviewer's name (if given), and quick actions.

Manual sync: click Sync now in the panel header to pull immediately. The "Ns ago" timestamp shows how stale the local view is.

Acting on a reviewer's comment

Click → chat on any pin row. The block:

  1. Builds a chat-ready quote like Design comment on `<h1>` (`.hero h1`) containing "Welcome": More breathing room around the headline.
  2. Copies it to your clipboard.
  3. Dispatches a fabric-design-comment CustomEvent for any host integration to consume.

Paste in the chat composer, optionally extend with your own direction ("…and shrink the subhead by 2px"), send. Agent edits the bundle in place; the iframe reloads.

The full review loop in practice

A typical 30-minute review session:

0:00   Designer:  "Mock me a launch landing for Mesh, premium dark."
       Agent:     [emits site-preview block]
       Designer:  Comment → click hero → "Make this 50% bigger and warmer"
       Agent:     [edits bundle, re-emits block, iframe reloads]

0:08   Designer:  "Looks good. Publish."
       Agent:     [calls publish_design] → re-emits block with publishedId/Url
       Designer:  Copies URL from the green chip, sends to reviewers

0:12   Reviewer1: Opens URL, leaves 3 pins (hero copy, button colour, footer link)
0:14   Reviewer2: Opens URL, leaves 2 pins (CTA hierarchy, mobile breakpoint)

0:15   Block auto-syncs → 5 amber pins appear in the designer's preview
       Designer:  → chat on hero copy pin → "fix"
       Agent:     [edits bundle]
       Designer:  → chat on button colour pin → "swap to accent"
       Agent:     [edits bundle]
       ...continues iterating...

The published URL keeps serving the latest local bundle the designer has on disk — but only after they re-publish. The publish button is one-click; many designers re-publish after every iteration so reviewers are always looking at current work.

Revoking a publish

Two ways:

  1. Wait for TTL — default 7 days, no action needed.
  2. Revoke immediatelyDELETE https://agents.fabric.pro/d/api/<id> (with the X-Fabric-Publish-Token header if PUBLISH_TOKEN is configured on the worker).

Revoking removes the bundle, all its assets, and all collected comments from R2. The URL returns 404 thereafter.

Privacy & security

ConcernWhat we do
Reviewers don't have to identify themselvesComments are anonymous by default; the Your name field is optional.
Spam / abusePer-comment cap (4 KB), per-bundle cap (256 KB), and an optional PUBLISH_TOKEN shared secret on writes.
PhishingStrict CSP — published designs can't load third-party scripts or be framed from outside *.fabric.pro.
Data residencyAll bundles + comments live in R2 in the Cloudflare account that owns the worker.
Forensic trailComments persist as JSONL in R2 with createdAt timestamps. The daily cron purges expired bundles + their comments together.

Operational reference

EndpointMethodAuthPurpose
/d/apiPOSToptional secretPublish a bundle
/d/api/<id>GETnoneFetch bundle metadata
/d/api/<id>DELETEoptional secretRevoke + delete bundle
/d/api/<id>/commentsGETnoneList all comments
/d/api/<id>/commentsPOSTnoneAppend a comment
/d/<id>/[path]GETnonePublic viewer (entry HTML or specific asset)

See Share Links & Design Publishing for the full ops doc.

See also

On this page