Fumadocs Editor

Providers

Where uploads go and which files documents can reference

The editor runs in the browser, so it cannot know where to store a pasted image or which pages exist. Your app tells it through two props:

PropEnablesWithout it
mediapasting and dropping imagesimages are added by URL
filesautocomplete for <include> and [[ linkspaths are typed by hand

Media

providers.tsx
export const media: MediaProvider = {
  async upload(file) {
    const res = await fetch("/api/upload", { method: "POST", body: file });
    if (!res.ok) throw new Error(`upload failed: ${res.status}`);
    const { src } = (await res.json()) as { src: string };
    return src;
  },
  resolve: (src) => (src.startsWith("./") ? `/content/${src.slice(2)}` : src),
};
  • upload stores the file and returns the src written into the document.
  • resolve turns a document src into a URL the browser can display.
  • onError receives the error and the file when upload rejects, so your app can show it.

With sync

The sync server has an upload endpoint, storing files in <root>/assets:

dev-media.tsx
import { ASSET_ENDPOINT, UPLOAD_ENDPOINT } from "@fumadocs-editor/core/sync";
import type { MediaProvider } from "@fumadocs-editor/ui";

export const devMedia: MediaProvider = {
  async upload(file) {
    const res = await fetch(UPLOAD_ENDPOINT, {
      method: "POST",
      body: file,
      headers: { "x-filename": encodeURIComponent(file.name) },
    });
    if (!res.ok) throw new Error(`upload failed: ${res.status}`);
    const { src } = (await res.json()) as { src: string };
    return src;
  },
  resolve: (src) =>
    /^(?:[a-z]+:|\/)/i.test(src) ? src : `${ASSET_ENDPOINT}/${src.replace(/^\.\//, "")}`,
};

It accepts image/* up to 10 MiB by default; change it with the server's upload option. With auth, uploads need write.

Files

providers.tsx
export const files: FileProvider = {
  list: async () => {
    const res = await fetch("/api/pages");
    return (await res.json()) as string[];
  },
};

Return paths exactly as they should be written into the document, relative to the open one (for example ./shared/props.mdx).

With sync, build the list from the pages of useWorkspace().tree.

Last updated on

On this page