Desktop Pricing Docs Blog About GitHub Get started

Add image upload to your TipTap editor in one prompt

TipTap is a rich contenteditable editor, so it uses PixelVault's upload helper rather than the textarea widget. This prompt wires paste + drop to upload images and insert them as image nodes — no upload backend. Copy it into your AI coding agent.

Works with Claude CodeCursorWindsurfCopilot
  1. 1
    Copy the prompt

    The one big button below.

  2. 2
    Paste it into your agent

    In your project — Claude Code, Cursor, etc.

  3. 3
    Drop in your key

    Swap pv_pub_REPLACE_ME for a free key. Done.

Prompt for your coding agent
Add image paste-and-host to my TipTap editor using PixelVault.

Context — read this first and use only the documented API:
- Overview + API: https://pixelvault.dev/llms.txt
- PixelVault upload helper (from @pixelvault-dev/paste):
    import { uploadImage } from "@pixelvault-dev/paste";
    const { url } = await uploadImage(file, { publishableKey: "pv_pub_REPLACE_ME" });
    // returns { id, url, mimeType, size }; throws PixelVaultPasteError on failure

Important: TipTap is a contenteditable/ProseMirror editor, not a <textarea>, so
do NOT use the paste-react/usePaste widget here — use uploadImage() directly.

Do this:
1. Install: npm install @pixelvault-dev/paste
   (and @tiptap/extension-image if my editor doesn't already have an image node)

2. Make sure my editor has the Image extension registered.

3. In my useEditor config, add editorProps.handlePaste and editorProps.handleDrop
   (standard TipTap/ProseMirror hooks). IMPORTANT: these handlers must be
   SYNCHRONOUS — do NOT make them async. In each handler: pull any image File out
   of the event, kick off the upload WITHOUT awaiting it (e.g. call an async
   helper as: void uploadAndInsert(file) ), and return true immediately so
   TipTap skips its default paste. Inside that helper: await
   uploadImage(file, { publishableKey }), then insert a TipTap image node with
   the returned url via the Image extension's setImage command
   (editor.chain().focus().setImage({ src: url }).run()). Show a sensible
   fallback if the upload throws PixelVaultPasteError.

4. Use my publishable key where I wrote pv_pub_REPLACE_ME (I'll paste my own).

Rules:
- For the PixelVault part, use ONLY uploadImage(file, options) as documented above —
  do NOT invent PixelVault endpoints, options, or other packages.
- Use TipTap's own documented handlePaste/handleDrop and Image APIs for the editor side.
- Handle the async upload without blocking the editor, and show a sensible fallback on error.

What the agent will do

  • Install @pixelvault-dev/paste (core) — and TipTap's Image extension if needed
  • Add handlePaste/handleDrop that upload via uploadImage()
  • Insert the returned CDN URL as a TipTap image node
  • No backend changes — uploads go straight to PixelVault with your key

Grab your free key

The one thing the agent can't generate is your publishable key (pv_pub_…) — it's origin-scoped and upload-only, safe to ship in browser code. Create one, add your app's origin, and paste it in.

Get your free key →

Free tier: 200 MB storage, 500 uploads/mo, 1 GB bandwidth. No card.

How this differs from the textarea prompts

The React, Vue, and plain-HTML prompts use our drop-in widget, which attaches to a <textarea>. TipTap renders a contenteditable ProseMirror surface instead, so the widget can't attach to it. The right tool is the lower-level uploadImage() helper: you upload the file yourself inside TipTap's own paste/drop hooks, then insert a native image node with the returned CDN URL.

The PixelVault part, by hand

Everything editor-specific is standard TipTap. The only PixelVault call is one function:

import { uploadImage } from "@pixelvault-dev/paste";

const { url } = await uploadImage(file, {
  publishableKey: "pv_pub_xxxxxxxx",
});
// url → https://img.pixelvault.dev/…  (a permanent CDN URL)
// then: editor.chain().focus().setImage({ src: url }).run();

Wire that into TipTap's editorProps.handlePaste and handleDrop, upload any image file the event carries, and insert it on success. The docs and llms.txt have the full reference.

Why a prompt instead of docs?

Because "add image upload to my TipTap editor" is exactly the kind of thing you'd hand a coding agent — and it needs to know to use uploadImage(), not guess at a nonexistent widget. This prompt grounds the PixelVault call and lets the agent handle TipTap's well-documented paste hooks. Copy, paste, ship.

FAQ

How do I add image upload to a TipTap editor?

Copy the prompt above into your AI coding agent. Because TipTap is contenteditable (not a textarea), it uses PixelVault's uploadImage() helper inside TipTap's handlePaste/handleDrop hooks, then inserts the returned CDN URL as a TipTap image node.

Why doesn't the usePaste widget work with TipTap?

The usePaste / attachPaste widget attaches to a <textarea> or <input>. TipTap renders a contenteditable ProseMirror surface, so you upload with the lower-level uploadImage() function and insert a native TipTap image node instead.

Do I need an upload backend for TipTap image uploads?

No. uploadImage() sends the file straight from the browser to PixelVault with an origin-scoped, upload-only publishable key. There's no server route to build.