Mischief

11 / Docs

Copy for AI

Hands the page to an assistant as markdown, by clipboard, by link, or by opening it somewhere that can read it.

Installation

Copy the source into your project, or keep it behind a package.

npx shadcn@latest add Tinkerers-Labs/mischief-ui/copy-for-ai
import { CopyForAi } from "mischief-ui/copy-for-ai"
Also installs
  • lucide-react

Or paste it in yourself. The source imports the shared cn helper from @/lib/utils, so point that at your own copy.

registry/default/copy-for-ai/copy-for-ai.tsx
"use client" import * as React from "react"import { Check, ChevronDown, Copy, FileText } from "lucide-react"import { cn } from "@/lib/utils" export type AiDestination = {  id: string  name: string  /** Builds the address opened for this destination. */  href: (prompt: string) => string  icon?: React.ReactNode} 

Usage

export function PageActions({ markdown }: { markdown: string }) {
  return (
    <CopyForAi
      markdown={markdown}
      markdownUrl="https://example.com/docs/tabs.md"
    />
  )
}

Copying the page, not the address

The main control copies the markdown itself rather than a link to it. That is the difference between an agent having the page and an agent being told where the page is -- one of which works when the model cannot browse, is behind a login, or is reading a build that has not shipped yet.

Generate that markdown from the same source your page renders from. Two hand-written copies of the same documentation disagree within a week.

Sending it somewhere

The menu's destinations each turn a prompt into a URL for a particular assistant. They are ordinary links, opened only when someone chooses one, and you can replace the set entirely to add your own or to remove any you would rather not point at.

<CopyForAi
  markdown={markdown}
  markdownUrl={url}
  destinations={[
    ...defaultDestinations.filter((entry) => entry.id !== "grok"),
    { id: "internal", name: "Our assistant", href: (prompt) =>
      `https://ai.example.com/new?q=${encodeURIComponent(prompt)}` },
  ]}
/>

Whatever the prompt contains ends up in a URL to a third party, and URLs are logged, kept in history, and sent as referrers. Never build one out of a customer's data, an internal document, or anything you would not paste into a public chat.

The view-as-markdown entry is dropped when there is no markdownUrl, so the menu never offers a link to nothing.

API

markdownstringThe page as markdown. This is what the button copies.
markdownUrlstringWhere the same markdown is served. Adds a link and points destinations at it.
promptstringWhat a destination is asked to do. Defaults to reading the markdown address.
destinationsAiDestination[]Where the page can be opened. Defaults to ChatGPT and Claude.
copyLabel, copiedLabel, viewLabel, menuLabelstringCopy for the button and the menu.

AiDestination

idstringUnique within the set.
namestringShown as "Open in {name}".
href(prompt: string) => stringBuilds the URL. Encode the prompt yourself.
iconReactNodeShown beside the name.

Accessibility

Copying is a button and every destination is a link, so each behaves the way its shape promises. The menu closes on Escape and on a click outside it, and the copy is announced through a polite live region rather than only changing an icon. Destinations open in a new tab and are marked so they are not followed.