A production-shaped opt-filemanager reference: complete SDK 3.5 capabilities, a browser-safe client, server-only credentials, API mapping, limits, errors, and legacy fallback.
Try the complete flow
Choose New folder, type a name, and press Create. Double-click a folder or focus it and press Enter to open it.
Use New file for an empty text file, choose Upload for multiple files, drop files or folders onto the browser, or paste a clipboard image.
Select an entry to open its details. Text and code files get a content preview; supported images use their file URL. Rename, move, download, or delete from the detail panel.
Use Cmd/Ctrl-click or Shift-click for multi-select. Batch move and delete operate independently, so partial failures remain visible instead of hiding successful work.
Security boundary
The UI receives a structural client made of same-origin fetch calls. Route Handlers resolve the encrypted connection cookie or server environment, create the SDK client, validate input, apply origin and rate-limit guards, and preserve typed SDK errors.
FileManager
UI and capability gates
Fetch client
No credentials
Route Handler
Validation and guards
sdk.files
Basic Auth server-side
Brandapp API
Files and folders
Capability contract
The Brandapp connector derives capabilities from the methods present on the injected client. A method is never called when its capability is disabled.
| Feature | SDK 3.5 | Connector | Visible behavior |
|---|---|---|---|
| Browse | listFolders + list({ folderId }) | list | Direct children only; breadcrumb navigation keeps folder context. |
| Create folder | createFolder | createFolder | Inline creation in the current folder. |
| Create / upload file | upload | createFile + upload | Text creation and every upload path share one queue. |
| Rename / move file | update | rename + move | folderId: null moves a file back to the root. |
| Rename / move folder | updateFolder | rename + move | The server rejects cycles and duplicate sibling names. |
| Delete | delete + deleteFolder | remove | Two-step confirmation; folders must be empty. |
| Text preview | readContent | readText | Best-effort preview for supported text and code MIME types. |
| Storage meter | usage | getUsage | Disables new uploads when a finite quota is full. |
Server proxy
| Method | Route | Purpose |
|---|---|---|
| GET | /api/files | List files; folderId= means root-only |
| GET | /api/files/:fileId | Read one file record |
| PATCH | /api/files/:fileId | Rename or move a file |
| DELETE | /api/files/:fileId | Delete a file |
| GET | /api/files/:fileId/content | Read a text preview |
| POST | /api/files/upload | Upload into the optional folderId |
| GET | /api/files/usage | Read workspace bytes and app file count |
| GET | /api/files/folders | List direct child folders |
| POST | /api/files/folders | Create a folder |
| PATCH | /api/files/folders/:folderId | Rename or move a folder |
| DELETE | /api/files/folders/:folderId | Delete an empty folder |
Limits and recovery
PLAYGROUND_MAX_UPLOAD_BYTESand can be stricter. The queue supports concurrency, cancel, retry, folder drops, and paste; fetch reports completion rather than byte-by-byte progress.| Code | HTTP | Recovery |
|---|---|---|
| FILE_NOT_FOUND | 404 | The selected file or folder no longer exists. |
| STORAGE_LIMIT | 402 | The workspace storage quota rejects an upload. |
| FILE_TOO_LARGE | 413 | The upload exceeds the 10 MiB Brandapp limit. |
| CONTENT_TOO_LARGE | 413 | A text preview exceeds 1 MiB. |
| UNSUPPORTED_CONTENT_TYPE | 415 | The selected file is not previewable text. |
| FILE_IN_USE | 409 | Another Brandapp surface still references the file. |
| FOLDER_NOT_EMPTY | 409 | Delete or move direct children first. |
| CONFLICT | 409 | A sibling folder already uses the requested name. |
Compatibility and environments
All methods are present, so folders, rename, move, previews, and usage are enabled automatically.
A list/get/delete/upload-only client becomes a flat browser. Unsupported controls disappear instead of failing at runtime.
pnpm dev uses the local SDK server. Use pnpm dev:remotewith .env.local, or connect credentials on /connection, for a hosted Brandapp.
pnpm add @reopt-ai/brandapp-sdk@4.2.0 \
@reopt-ai/opt-filemanager@0.1.0"use client";
import {
FileManager,
createBrandappFilesConnector,
} from "@reopt-ai/opt-filemanager";
import { useState } from "react";
// Import this once from an App Router page or layout.
import "@reopt-ai/opt-filemanager/styles.css";
import { createFileBrowserClient } from "./file-browser-client";
export function BrandappFileBrowser() {
// Keep one connector instance so navigation state and the connector's
// file/folder identity cache survive client re-renders.
const [connector] = useState(() =>
createBrandappFilesConnector({
// This client only knows same-origin routes. BRANDAPP_CLIENT_SECRET
// remains in a server-only SDK factory.
client: createFileBrowserClient(),
}),
);
return (
<FileManager
connector={connector}
locale="en"
initialSort={{ field: "name", order: "asc" }}
initialViewMode="list"
uploadConcurrency={3}
/>
);
}