Providers
Where uploads go and which files documents can reference
There is no file system in the browser. The editor does not know where a
pasted image should be stored, or which documents exist for <include> and
page links. Both are small interfaces your host implements and passes as
props:
| Prop | Without it |
|---|---|
media | paste and drop upload are off; images are added by URL |
files | the include picker and [[ page-link autocomplete are plain text inputs |
Everything else works either way.
Media
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;
},
// turn document srcs (often relative) into displayable URLs
resolve: (src) => (src.startsWith("./") ? `/content/${src.slice(2)}` : src),
};uploadstores the file and returns thesrcwritten into the document. Keep it relative if that is what your site expects.resolvemaps a documentsrcto a display URL, so relative paths still preview.
On the dev server
The sync dev server has an upload endpoint, so the provider only needs to call it:
import { ASSET_ENDPOINT, UPLOAD_ENDPOINT } from "@fumadocs-editor/core/sync";
import type { MediaProvider } from "@fumadocs-editor/ui";
// uploads land in <root>/assets on the dev server; relative srcs display
// through the asset endpoint
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(/^\.\//, "")}`,
};
Uploads land in <root>/assets. The server checks the content type against
upload.types (default image/*) and the size against upload.maxBytes
(default 10 MiB) before storing anything. With auth
enabled, the upload also needs write on the stored path.
Files
export const files: FileProvider = {
// the exact relative paths to write into the document
list: async () => {
const res = await fetch("/api/pages");
return (await res.json()) as string[];
},
};Return the relative paths exactly as they should be written into the
document, relative to the open one (for example ./shared/props.mdx). They
power:
- in-place autocomplete of the
<include>path - page-link suggestions when you type
[[
On the dev server, transport.list() minus the open document is usually
enough.
Last updated on