| name | copy2llm |
| description | Use when asked to add or manage Copy2LLM, a portable website-to-AI context layer for plain HTML, React, Next.js, Astro, or Framer; configure capture, Context Cart, extraction boundaries, handoff targets, styling, or troubleshoot extraction and display. |
copy2llm — install and manage the "Copy to LLM" button
Overview
copy2llm (copy.computer) is the portable context layer between websites and AI. Readers can capture a page, selection, or section; review multiple sources locally; then copy, download, or send the bundle to ChatGPT, Claude, Perplexity, Grok, or a custom endpoint. Fully client-side: no backend, API key, or account.
Pick an install path
| Situation | Use |
|---|
| Any site, zero build | <script> snippet |
| React / Next.js | copy2llm-react |
| Non-React JS, imperative mount/destroy | copy2llm-widget |
| Framer site | official plugin |
| Markdown extraction only, no UI | copy2llm-core |
Script tag (any stack)
Place before </body> (Next.js: root layout via <Script strategy="lazyOnload">; Astro: base layout):
<script src="https://copy.computer/copy2llm.js" defer
data-position="bottom-right" data-theme="auto"></script>
The hosted snippet is unversioned and always latest (cached ≤ 5 min). Add data-automount="false" to take control and mount yourself via window.copy2llm.mount(options, target).
React
npm i copy2llm-react
import { CopyToLLM } from "copy2llm-react";
<CopyToLLM position="bottom-right" theme="auto" />
Mounts the widget on mount, tears it down on unmount. position="inline" renders an in-flow anchor where placed; any other position mounts onto document.body.
Imperative (non-React)
import { mount } from "copy2llm-widget";
const handle = mount({ position: "bottom-right", theme: "auto" });
handle.destroy();
Framer
Install the official plugin from the Framer marketplace: https://www.framer.com/community/marketplace/plugins/copy-to-llm/. It intentionally remains on the classic single-page copy/handoff flow. Do not promise Context Cart, exclusion selectors, usage events, or the full option table for Framer.
Options
Script data-* attributes, React props, and mount() options share the following configuration unless noted:
| Option | Script attribute | Values | Default |
|---|
position | data-position | bottom-right bottom-left top-right top-left inline | bottom-right |
theme | data-theme | auto light dark — auto matches the host site, falls back to the OS, stays live | auto |
bg | data-bg | any CSS color | from theme |
text | data-text | any CSS color | auto-contrast from bg |
font | data-font | sans serif mono | sans |
radius | data-radius | sharp rounded pill or any CSS length | rounded |
label | data-label | primary button text | Copy as Markdown |
prompt | data-prompt | lead-in text sent to the LLM before the page's Markdown on the Open in… actions (e.g. "Summarize this API reference"); not available in the Framer plugin | Here's a web page as Markdown — help me work with it: |
items | data-items | comma-separated from copy pick context view chatgpt claude perplexity grok; first is primary | all |
header | data-header | true/false — prepend a title + source header to the Markdown | true |
content | data-content | CSS selector for the extraction root | auto (Readability) |
exclude | data-exclude | CSS selectors removed before extraction; [data-copy2llm-ignore] is always removed | none |
endpoints | data-endpoints | JSON array of { "label", "href" } custom LLM targets | none |
onEvent | — | React/widget callback with privacy-safe action metadata; script users observe copy2llm:action | none |
Custom endpoint href is a deep-link template: {q} is replaced with the page's Markdown (appended if the template has none; pages too long to inline fall back to a clipboard paste):
data-endpoints='[{"label":"Open in Acme AI","href":"https://acme.ai/?q={q}"}]'
Manage
- Update: the script tag auto-updates (hosted, unversioned). npm installs update normally (
npm update copy2llm-react).
- Remove: delete the script tag / component; imperative mounts:
handle.destroy().
- Reconfigure: change the attributes/props. Context Cart sources use same-origin
sessionStorage, persist across navigation in the current tab, and clear when the tab session ends.
- Interactive configurator with live preview: https://copy.computer/#install
Verify
Load the page: the button appears at the configured position. Verify Copy as Markdown, then choose Add to AI context and confirm the source appears in the review sheet. Long handoffs must either copy the full Markdown before opening the AI or show the Markdown preview; they must never open an empty prompt silently.
Common mistakes
data-endpoints must be valid JSON — wrap the attribute value in single quotes (JSON needs double quotes inside). Malformed JSON or entries missing string label/href are silently dropped.
- Invalid
position/theme/font/items values are silently dropped and defaults apply — check spelling, nothing is logged.
- Button copies nav/sidebar noise → set
content to the main selector and/or add exclude selectors. Mark a sensitive element with data-copy2llm-ignore to remove it in every extraction.
data-header is falsy only for false/0/off/no; any other value keeps the header on.
- The widget lives in a Shadow DOM — page CSS cannot restyle it; use
bg/text/font/radius instead.