A Variant Fund open source project
Publish the Claude artifact you're looking at to a live URL — in two clicks.
A minimalist Chrome extension (Manifest V3) that takes the artifact open in your Claude conversation and publishes it to here.now as a real, shareable website.
No copy-paste. No downloading files. No build step.
Claude conversation ──▶ [right here.now] ──▶ https://your-site.here.now
- Why
- Install
- Usage
- What gets published
- Privacy and security
- Permissions
- How it works
- Development
- Contributing
- License
Claude writes a working dashboard, a landing page, a diagram — and it lives inside a chat panel. Sharing it means copying source into a file, finding somewhere to host it, and wiring up a URL.
This extension collapses that into one click. The artifact becomes a live page you can send to anyone.
Not yet published. Until then, use one of the options below.
- Download
right-here-now-<version>.zipfrom Releases. - Unzip it.
- Open
chrome://extensions. - Enable Developer mode (top right).
- Click Load unpacked and select the unzipped folder.
- Pin right here.now to your toolbar.
Clone the repository and load the folder itself at step 5 — there is no build step and no dependencies, so the source runs as-is. This also picks up the tests and the diagnostic probe, which the release ZIP omits.
- Chrome shows a "Disable developer mode extensions" warning on some startups. That is Chrome's standard notice for any unpacked extension, not a problem with this one.
- No automatic updates. To upgrade, download the new release and reload it.
- Installing a
.crxfile directly is not offered, because Chrome blocks self-hosted.crxinstalls on Windows and macOS. A signed store listing is the only path to one-click install and auto-updates.
- Click the toolbar icon and Connect to here.now. Sign-in opens in a tab: enter your email, here.now sends a one-time code, paste it. No password to create.
- Open a Claude conversation containing an artifact.
- Click the toolbar icon, pick your options, hit Publish artifact.
- Copy the URL.
Publishing continues even if you close the popup.
| Option | What it does |
|---|---|
| Artifact | Which file to publish. A conversation often contains several written files; the most likely one is preselected. |
| Publish to | Your personal account, or a here.now workspace you belong to. Defaults to a workspace when you have one. |
| Label | Workspace only. Sets the URL: {label}.{workspace}.here.now. |
| Who can see it | Public · Team only (workspaces) · Private (password). |
On personal URLs: here.now assigns the slug (e.g. bright-canvas-a7k2.here.now) and its
API has no field to request a custom one, so the Label input is disabled for personal
publishes rather than pretending otherwise. Custom names are a workspace feature.
| Artifact type | Files published |
|---|---|
| HTML | index.html, verbatim |
| React / JSX / TSX | index.html (React 18.3.1 + Babel shell) + source.jsx |
| Mermaid | index.html (render shell) + source.mmd |
| Markdown | index.html (rendered) + source.md |
| SVG | index.html (viewer) + image.svg |
| Other code | index.html (formatted view) + raw source |
here.now imposes no file-type restriction, so the wrapper exists for a different reason: a
raw .jsx served on its own never executes — a visitor gets a download instead of the
artifact. The shell makes it render, and the original source ships alongside so nothing is
lost.
React is pinned to 18.3.1 rather than the newer 19.x on purpose: that is the runtime Claude artifacts are authored against.
Rendered artifacts load React, Babel, Tailwind and Mermaid from public CDNs (jsdelivr, esm.sh) in the published page — never in the extension. Every dependency is pinned to an exact version, and classic
<script>tags carry Subresource Integrity. ES module imports cannot carry SRI (import attributes accept onlytype), so those are version-pinned only. The generated page also sets a CSP restricting where scripts may load from, while leaving fetch, fonts, media and embeds open — artifacts routinely need them, and Babel requiresunsafe-evalregardless, so a tighter policy would break real pages without being a meaningful boundary.
Only the source of the single artifact you selected, plus the title derived from its filename. Your conversation, other artifacts, and your Claude account details are never transmitted.
While the popup is open, the extension holds every file from that conversation in memory-backed session storage so the picker and the publish step share one read. That cache is discarded when the tab navigates or closes, when you disconnect, and when the browser closes. It is never written to disk and never sent anywhere.
- Stored in
chrome.storage.local, read only by the extension's service worker. - Never passed to the content script, injected into the Claude page, or included in any message a content script could receive.
- Sign-in happens in the service worker, so the key never enters the sign-in page or popup.
- Presigned uploads are sent without the
Authorizationheader — the key never reaches the storage host. - Every request that carries the key is origin-checked against
here.now, including the finalize call whose URL the server supplies, and redirects are refused. The upload host is separately pinned, so artifact bodies go only to the verified here.now storage bucket. A tampered API response cannot redirect either the key or your content elsewhere. - No analytics, no telemetry, no third-party servers. The extension talks to
here.now, its storage host, andclaude.ai— nothing else.
chrome.storage.local is not encrypted. Anyone with read access to your browser profile
directory, or a sufficiently privileged extension, can read the key. This is a Chrome
platform limitation that no extension can engineer around. Treat the key like a saved
password.
here.now necessarily receives the key on every publish. If a key is exposed, revoke it at here.now; Disconnect removes it from your browser.
Extraction reads Claude's conversation data directly. There is deliberately no DOM-scraping fallback: the largest readable element on a chat page is the whole conversation, so a fallback would risk publishing your entire chat to a public URL. When extraction fails, it fails loudly instead.
| Permission | Why it is needed |
|---|---|
storage |
Stores your here.now API key and in-progress publish state locally. |
activeTab |
Reads the artifact from the Claude tab you are on, only when you click Publish. |
scripting |
Injects the extraction script into that tab on demand. |
https://claude.ai/* |
Reads the artifact source from your open conversation. |
https://here.now/* |
Creates the site, finalizes it, and applies access settings. |
https://<id>.r2.cloudflarestorage.com/* |
here.now returns presigned upload URLs on Cloudflare R2; artifact files upload directly there. Pinned to here.now's specific bucket host, not a wildcard. |
Not requested: tabs (the broad permission). Tab URLs are available for Claude tabs via
the host permission alone. No wildcard storage permission is requested either — if here.now
ever migrates buckets, uploads fail loudly rather than trusting an unexpected host.
The extraction script is injected on demand rather than declared as a static content
script, so nothing runs on claude.ai until you click Publish.
manifest.json Manifest V3
background.js Service worker — sole API-key custodian, publish orchestration
content.js Artifact extraction on claude.ai (never sees the key)
popup.{html,js,css} Toolbar UI
signin.{html,js} Full-tab sign-in
lib/herenow.js here.now API client
lib/wrap.js Artifact type -> publishable file set
spikes/ One console probe for diagnosing extraction against live claude.ai
tests/ Node test scripts
POST /api/v1/publish (file manifest → presigned URLs) → PUT each URL → POST {finalizeUrl}.
A site is not live until finalize succeeds.
Behaviours below look arbitrary but are load-bearing. Each was established by testing against the live sites, not assumed:
- Artifact source comes from
input.file_text. The neighbouringdisplay_content.json_blockis capped at exactly 65536 bytes and silently truncates. A source arriving at exactly 64KB is rejected rather than published. - A conversation contains several written files — the artifact plus scratch scripts.
Selection ranks:
?artifactId=in the URL → files passed topresent_files→ files under/outputs/→ renderable type → most recent.?artifactId=is usually absent. - File-creation calls carry no type or title, only
description,pathandfile_text. Type is inferred from the file extension; without that a.jsxpublishes as a blank page. - Accounts may span several organizations. Each is tried until one owns the conversation.
- Passwords use a different endpoint than other access modes:
PATCH /publish/{slug}/metadata. The/accessendpoint returns 409 for password mode. - Workspace labels use
PATCH .../site-labels/{label}(rename), notPOST—POSTis admin-only, whereas rename is permitted for the site's original publisher, so ordinary members can name their own sites. - Sign-in must not live in the popup. Chrome popups close on blur, so switching to your inbox for the code would destroy the flow.
Sign-in happens in a tab for exactly that reason. here.now has no OAuth flow — its only auth
scheme is a bearer API key obtained via email code — so chrome.identity is not an option
today.
No dependencies. Requires Node 18+ to run the tests.
node tests/extraction.test.mjs # artifact selection and ranking (offline)
node tests/dom-ids.test.mjs # UI wiring: DOM ids and view initialization
node tests/publish.test.mjs # publishes anonymously to LIVE here.now (24h expiry)publish.test.mjs makes real network calls and creates a temporary public site that expires
in 24 hours. It needs no API key.
spikes/inspect-claude.js is a console snippet for re-verifying extraction against live
claude.ai and here.now when either changes. Paste one into DevTools on the relevant page.
- Popup: right-click the popup → Inspect.
- Service worker:
chrome://extensions→ service worker link under this extension. - Extraction: run
spikes/inspect-claude.jsin the console on a Claude conversation.
Issues and pull requests are welcome.
- Keep the extension dependency-free and buildless.
- Run all three test scripts before opening a PR.
- Anything that touches key handling, the content-script boundary, or the pinned upload origin should explain the security reasoning in the PR description.
- claude.ai and here.now are unversioned moving targets. If you change extraction or the API
client, re-run
spikes/inspect-claude.jsand say what you observed.
See PRIVACY.md for the full policy, including exactly what is read locally versus what is transmitted.
MIT — see LICENSE.
An independent, unofficial project. Not affiliated with, endorsed by, or sponsored by Anthropic or here.now. "Claude" is a trademark of Anthropic, PBC.
Use of here.now is subject to its own terms of service and privacy policy.