Comprehensive Guide for Developers: UI & SDK Integration, Configuration, and API Reference
OptionalaccountStable id of the account this source is currently serving, when it has accounts at all. It scopes the recents history: entries recorded under one account are not listed while another is connected. Supply it if your source can switch accounts (or tenants) within a session and their item ids are not interchangeable.
OptionalaccountAccount shown next to the name in the breadcrumb root (e.g. an email), when known.
Inline <svg> markup for the icon — your own logo, since a host source has no glyph
in the viewer's icon font. Sanitized before inlining (<script>, <foreignObject>,
on* handlers and javascript: hrefs are stripped), same as brandingConfig.logoSvg.
Rendered at the same box as the built-in drives' glyphs, in its own colours —
give it a viewBox. Markup with no fill of its own follows the surrounding
text colour; to sit visually in line with the built-ins' grey glyphs, supply
the mark in a matching grey.
Stable id, unique across providers. Keys the tab and the remembered folder
path, so it must not change between renders and must not collide with the
built-ins ('onedrive', 'googledrive', 'dropbox', 'netexplorer', 'recents', 'device').
OptionalisWhether the source can serve requests right now. Define it as a getter over your
app's own auth state; omitted means always connected. While it reads false the
source's tab and Save-as target are withdrawn, and its recents rows show greyed as
"Disconnected" instead of failing to open — signing back in brings everything
straight back. Pair it with connect to let the user sign in from the
viewer's own + Connect menu, like a built-in drive.
Display name for the tab and the breadcrumb root. Shown as-is, not localized.
OptionalconnectStart your app's sign-in — implementing this (with isConnected) makes the
source behave like a built-in drive: while disconnected it is offered under
+ Connect, and choosing it calls here. The call happens synchronously inside
the click, so a window.open to your auth page is not popup-blocked. Return a
promise that resolves once sign-in completes (or fails): the viewer re-reads
isConnected at that moment and, when it is now true, opens the source's
fresh tab. Resolving immediately is allowed — the tab then appears on the next
re-render instead.
OptionalcreateCreate an empty folder under folder (your root when null) — the Create folder
action on the home screen's browser bar, which only appears when you implement this.
Return the folder you created (isFolder: true) or null on failure; a user cancel
is an AbortError, same as saveInto.
OptionaldisconnectSign the source out in your app — implementing it puts a Disconnect action on the source's browser bar, same as a drive's, and the viewer re-reads isConnected once the call settles. Omit it and no Disconnect is shown: sign-out then stays entirely in your app's own UI.
OptionalgetDownload an item's bytes as a File, reporting progress when possible.
Return null on failure. The File's name drives the viewer's tab title.
Omit it alongside listFolder for a write-only target.
When your backend says the file no longer exists (deleted, moved, unshared),
throw a DOMException named NotFoundError instead of returning null: the
viewer then drops the file's recents entry, while a null (or any other throw)
keeps it so a transient failure can be retried.
OptionalonProgress: CloudDownloadProgressOptionalgetOptional thumbnail URL for a file tile. Omit the method (or return null)
to fall back to the generic file icon.
OptionallistChildren of folder, or of the source's root when called without one:
navigable folders plus openable files. Return null to signal failure —
the viewer then shows a "couldn't load" placeholder instead of "empty".
Omit it for a write-only target such as a desktop shell, where nothing can be enumerated: the source then gets no home-screen tab and appears only as a "Save as" destination, which hands the file to saveInto and lets you show your own save dialog.
Optionalfolder: IFileItemOptionalsaveWrite a new file into folder (your root when null) — the Save as action, once
the user picked this cloud and a folder. Return the item you created (its id is what
the next Save overwrites, its path becomes the document's path) or null on
failure; a user cancel is an AbortError, and progress reporting and claims work the
same as in saveOver. Omit this to accept Save but not Save as.
OptionalsaveOverwrite an item the user opened from here — the Save action. Implementing it (with or without saveInto) makes this cloud a save target: the main menu then offers Save / Save as, and Ctrl+S writes back here.
Return the item as it now stands — item itself is fine — or null for a failure,
which the viewer reports (any throw other than an AbortError counts as null).
When the save runs through a dialog of your own, signal a user cancel by throwing a
DOMException named AbortError: the viewer then reports nothing.
While the write runs the viewer shows a "Saving to …" notice; report onProgress
(a fraction in [0, 1], or null for indeterminate) and it gains a percentage.
Ignoring the callback is fine — the notice simply stays indeterminate.
claims lists every operation the saved contents went through — the document's own plus
the ones inherited from the data it was made from, so a merge of an OCR'd file reports
both. Empty for a build whose core reports none.
Both trailing arguments are always passed; declare only the ones you use.
A host-owned file source: the integrator's own cloud, or the user's machine in a desktop shell. Everything the viewer can do with it follows from the methods you implement — list to get a home-screen tab, save to become a Save / Save as target — so a browsable cloud and a write-only desktop target use the same shape.
Unlike the built-in drives there is no sign-in flow: the tab is always present ("sticky", like "Recents") because the host app already knows who the user is. Unlike "Recents" — a flat list — the body is a folder browser, so listFolder is the required entry point and folders come with a breadcrumb for free.
Every method may reject or resolve
null; the viewer treats that as "failed" and shows an error placeholder rather than propagating the error.Example