Studio
Edit a folder of MDX files without writing a host app
Studio is the editor as a command. Run it in your Fumadocs app:
npx @fumadocs-editor/studioIt opens a browser with your documents and a file list:
- edits save to disk, and changes on disk merge in (Sync)
- the file tree creates, deletes and reorders pages
?collabin the URL turns on collaboration for that tab
Keyboard
| Keys | Does |
|---|---|
⌘K | search files and actions (theme, collab, MDX source) |
⌘S | save now |
Esc | close the file list, when focused |
The file list has its own shortcuts.
Flags
| Flag | Default |
|---|---|
--root <dir> | content/docs, content, then the cwd |
--config <file> | fumadocs-studio.config.ts |
--port <n> | 5180 |
--host | listen on all addresses |
--no-open | do not open the browser |
Configuration
Create a fumadocs-studio.config.ts where you run Studio. Flags override it.
import { defineConfig } from "@fumadocs-editor/studio";
import { admonitionSpec, fumadocsUiComponents } from "@fumadocs-editor/ui";
export default defineConfig({
root: "content/docs",
port: 5180,
components: [...fumadocsUiComponents, admonitionSpec],
syntax: { math: true },
theme: "system",
// stylesheets for your own renderers
styles: ["./studio.css"],
// node-only options live in their own module
server: "./studio.server.ts",
});
Prop
Type
components, syntax, theme and media work like the
MdxEditor props. Your own components follow the
authoring guide, and their styles load through styles.
Server options
The config also runs in the browser, so anything Node-only (a JWT library,
a Vite plugin) goes in a separate file referenced by server:
import { defineServerConfig } from "@fumadocs-editor/studio";
import tailwindcss from "@tailwindcss/vite";
export default defineServerConfig({
// same hook as the sync server: ?token=… reaches `payload`
authenticate: ({ payload }) => (payload === process.env.STUDIO_TOKEN ? { write: true } : null),
upload: { maxBytes: 5 * 1024 * 1024 },
vite: { plugins: [tailwindcss()] },
});
Prop
Type
Auth
Without authenticate, anyone who can reach the port can edit. With it,
the credential comes from ?token= in the URL by default; override it with
auth. See Auth for writing the hook.
Last updated on