Handling Image Uploads
Use remote URLs for production. Avoid persisting Base64 image payloads in your document JSON.Why default Base64 flow is risky
- Large payloads and slow save requests.
- Higher database cost and poor caching behavior.
- Harder image lifecycle management.
Upload then insert URL
import type { Editor } from '@tiptap/core'
import type { EditorProps } from '@tiptap/pm/view'
import { HybricEditor } from 'hybricmark'
async function uploadToCloudinary(file: File): Promise<string> {
const form = new FormData()
form.append('file', file)
form.append('upload_preset', '<your-preset>')
const res = await fetch('https://api.cloudinary.com/v1_1/<cloud-name>/image/upload', {
method: 'POST',
body: form,
})
if (!res.ok) throw new Error('Image upload failed')
const data = (await res.json()) as { secure_url: string }
return data.secure_url
}
const isImageFile = (file: File) => file.type.startsWith('image/')
async function uploadAndInsertImage(editor: Editor, file: File) {
const url = await uploadToCloudinary(file)
editor.chain().focus().setImage({ src: url }).run()
}
const editorProps: EditorProps = {
handlePaste(view, event) {
const files = Array.from(event.clipboardData?.files ?? []).filter(isImageFile)
if (!files.length) return false
event.preventDefault()
const editor = (view as unknown as { editor?: Editor }).editor
if (!editor) return true
void Promise.all(files.map((file) => uploadAndInsertImage(editor, file)))
return true
},
handleDrop(view, event) {
const files = Array.from(event.dataTransfer?.files ?? []).filter(isImageFile)
if (!files.length) return false
event.preventDefault()
const editor = (view as unknown as { editor?: Editor }).editor
if (!editor) return true
void Promise.all(files.map((file) => uploadAndInsertImage(editor, file)))
return true
},
}
export default function EditorWithUpload() {
return <HybricEditor content="# Image Demo" editorProps={editorProps} />
}UX tips
- Show `Uploading...` placeholder near cursor while request is pending.
- Show actionable error UI, not only console logs.
- Apply server-side file validation (type/size/security scan).