# Davflare [English](README.md) | [中文](README.zh-CN.md) [![Deploy to Cloudflare Pages](https://img.shields.io/badge/Deploy%20to%20Cloudflare-Pages-F38020?logo=cloudflare&logoColor=white)](https://dash.cloudflare.com/?to=/:account/workers-and-pages/create) · [Deploy guide](docs/deploy.md) [![WebDAV litmus](https://img.shields.io/github/actions/workflow/status/fanchenggang/Davflare/ci.yml?branch=main&label=WebDAV%20litmus)](https://github.com/fanchenggang/Davflare/actions/workflows/ci.yml) Cloudflare R2 file manager on **Cloudflare Pages** (API via Pages Functions) — free 10 GB storage and 100,000 invocations per day. [R2 pricing](https://developers.cloudflare.com/r2/platform/pricing/) > **Pages, not Workers.** This repo sets `pages_build_output_dir` in `wrangler.toml` and has no Worker `main`. Do **not** use the [Workers Deploy to Cloudflare](https://deploy.workers.cloudflare.com/) button or `wrangler deploy` — that looks for a Worker entry point and fails with «entry point not configured». ## Screenshots Grid light: ![Grid light](docs/screenshots/grid-light.png) Grid dark: ![Grid dark](docs/screenshots/grid-dark.png) Image preview: ![Image preview](docs/screenshots/preview.png) Share (expiry + extract code): ![Share (expiry + extract code)](docs/screenshots/share.png) ## Features - Chunked web uploads, folders, search, drag-and-drop, image/video/PDF thumbnails - Share links with expiry or forever, extract code, folder zip; zero-JS preview for media/PDF, monospace preview + copy for `text/plain` - **Quick paste**: toolbar paste → `.txt` + existing shares (expiry / extract code) — a self-hosted Pastebin - **Paste screenshot → CDN**: Ctrl/Cmd+V in the file manager, Image host page, or Settings — uploads via `POST /api/images`, toast copies `https:///i/{id}` - **PDF library / bookshelf**: publish a PDF/EPUB folder to `sites/{slug}/` with open/download + optional covers - **Podcast / RSS**: publish an audio/video folder to `sites/{slug}/` with `feed.xml` + a simple player page — subscribe in any podcast app - **Download page / Releases on R2**: publish an installer/zip folder to `sites/{slug}/` with name, size, SHA-256 (optional README notes) - **Scheduled backup**: Settings card copies safe `davflare sync` crontab lines; examples + GitHub Actions - Recycle bin with configurable retention (`TRASH_RETENTION_DAYS`) - WebDAV Class 1/2 at `/webdav` (toggleable without affecting the web UI) - API keys for scripted upload / download / sync, plus remote MCP at `/mcp` (25 tools) - Static sites and image host on a separate hostname (`SITES_HOST`), plus a GitHub Action to deploy from CI - Owner Settings with five persistent feature switches - `davflare-cli`, optional Chrome MV3 extension, agent layouts on R2, and an **official Agent Skill** (`skills/davflare/`) - Chinese / English UI ## Quick start 1. Open [Workers & Pages → Create](https://dash.cloudflare.com/?to=/:account/workers-and-pages/create) → **Pages** → **Connect to Git**, pick this repo (needs a Cloudflare account with R2 activated and a payment method on file). 2. Framework preset **None**, build `npm run build`, output directory `build` (or rely on `wrangler.toml`'s `pages_build_output_dir`). 3. Bind your R2 bucket to `BUCKET`, set `WEBDAV_USERNAME` and `WEBDAV_PASSWORD`, then retry deploy. 4. Optional: `WEBDAV_PUBLIC_READ=1`, `TRASH_RETENTION_DAYS` (default `30`, `-1` disables), and for public sites/images bind `sites.` and set `SITES_HOST=sites.`. On that zone set **Caching → Browser Cache TTL** to **Respect Existing Headers** (the 4-hour default rewrites site css/images/fonts to `max-age=14400`); see [docs/sites.md#caching](docs/sites.md#caching). 5. Optional: add a custom domain for the drive UI. Full Pages / Wrangler steps and the five feature switches: [docs/deploy.md](docs/deploy.md). ## Free Obsidian sync in 10 minutes Sync an Obsidian vault to Davflare's WebDAV (`/webdav`) with the community plugin [Remotely Save](https://github.com/remotely-save/remotely-save). Every device shares one copy, no extra server. 1. Deploy Davflare (see Quick start above) and keep the WebDAV switch on in `#/settings` (on by default). 2. Open the drive → **WebDAV** in the top bar → **Obsidian sync** card, then click "Copy server address" (looks like `https:///webdav/`) and "Copy username". The password is `WEBDAV_PASSWORD` (your web sign-in password); the card never shows it. 3. Obsidian → Settings → Community plugins. In a new vault, first click **Exit Restricted mode** (turns on community plugins); only then does **Browse** appear. Browse, install and enable **Remotely Save**. 4. In Remotely Save settings: - Choose A Remote Service: **Webdav** - Server Address / Username / Password: from step 2 - Auth Type: **basic** - Depth Header Sent To Servers: keep the default **only supports depth='1'** - Remote Base Directory: leave empty (defaults to the vault name, created at the WebDAV root); if your devices use different vault names, set the same single-level name on all of them (no `/`), then click **Confirm** next to the field and **Confirm To Change** in the dialog that follows — the change is not saved otherwise 5. Click "Check Connectivity" → "Check" and wait for the success notice. 6. Click the Remotely Save icon in the left ribbon to sync once. Before the first sync the plugin shows "**HUGE updates on the sync algorithm**": tick both checkboxes and click **Agree** (**Do Not Agree** disables the plugin). 7. Second device: create an **empty vault with the same name** first, configure it with steps 3–5, then sync once to pull down the same content. Tested (local `wrangler pages dev` plus the same `webdav` client the plugin uses, replaying Remotely Save 0.5.25's request sequence as two devices syncing both ways): Chinese file names, spaces, special characters such as `+ & ' % #`, nested folders, empty folders, PNG / PDF attachments, 5MB / 12MB files, deletes, file renames, folder renames, and both depth='1' and depth='infinity' listing. Limits: each file must be under 100MB (Cloudflare's request body limit). Requests over 100MB are stopped by Cloudflare with its generic 413 page, so set Remotely Save's **Skip Large Files** threshold below 100MB. Remotely Save syncs a rename as "delete old file + upload new file". ## Connect Claude / Cursor MCP in 2 minutes Point Cursor or Claude Desktop at the same-origin `POST /mcp` with an API key. No new APIs. 1. Deploy Davflare, open `#/settings`, leave **API Key** and **MCP** on, create a key. 2. On the **Connect Claude / Cursor MCP** card, copy or download: - **Cursor** → `mcp.json` (`url` + `Authorization: Bearer ${env:DAVFLARE_API_KEY}`) - **Claude Desktop** → `claude_desktop_config.json` (`mcp-remote` bridge; set `DAVFLARE_API_KEY` in the environment before launch) 3. Restart the client and ask it to call `tools/list`. Details and samples: [docs/agents.md#2-minutes-connect-davflare-to-an-ai-assistant](docs/agents.md#2-minutes-connect-davflare-to-an-ai-assistant) · [`agents/examples/mcp-export/`](agents/examples/mcp-export/). ## Free R2 AI workspace in 2 minutes (official skill) Point Cursor / Claude / Codex at your Davflare drive so the agent can store files, create share links, and `publish_site` to `sites/{slug}/` — same-origin `/mcp` (~25 tools) + Open API, **no new APIs**. 1. Deploy Davflare; `#/settings` → leave **API Key** + **MCP** on; create a key. 2. Wire the client: Settings → **Connect Claude / Cursor MCP** (or [`agents/examples/mcp-export/`](agents/examples/mcp-export/)). Set `DAVFLARE_API_KEY` — never paste a raw `fd_…` into files. 3. Install the skill: ```bash npx skills add fanchenggang/Davflare --skill davflare -g -a cursor ``` Or Settings → **Agents skill (official)** → Copy / Download `SKILL.md` into `~/.cursor/skills/davflare/`. 4. Ask the agent to `tools/list`, then try `list` / `publish_site` (see [`agents/examples/hello-site/`](agents/examples/hello-site/)). **Agents skill** teaches the agent how to use Davflare; **Connect Claude / Cursor MCP** only exports `mcp.json`. Details: [docs/agents.md#official-skill](docs/agents.md#official-skill) · [`agents/examples/davflare-skill/`](agents/examples/davflare-skill/) · [`skills/davflare/`](skills/davflare/). ## 10-minute self-hosted Pastebin (Quick paste) In the web UI, open **Quick paste** from the toolbar (or the mobile Create menu): paste text → pick expiry and an optional extract code → get a share link. Davflare writes a `.txt` in the current folder and reuses `POST /api/shares` — **no new API**. The landing page shows a monospace preview with one-click copy, plus `.txt` download. Extract codes work like any other share. Handy for code snippets, logs, or notes when people search for a private Pastebin on Cloudflare R2. From scripts: `PUT /webdav/.../note.txt` then `POST /api/shares`; `Content-Type: text/plain` shares get the paste landing automatically. ## Free R2 backup in 10 minutes (scheduled sync) Use existing `davflare-cli` sync — no new APIs. 1. `npm i -g davflare-cli` then `davflare login --server https://` (or set secrets `DAVFLARE_SERVER` / `DAVFLARE_KEY` in CI). 2. Open `#/settings` → **Scheduled backup** → copy a **push** or **pull** crontab line (keys stay in `~/.config/davflare`, never in the line). 3. `crontab -e` and paste; or copy [`agents/examples/backup-cron/github-actions-backup.yml`](agents/examples/backup-cron/github-actions-backup.yml) into your repo workflows. Samples: [`agents/examples/backup-cron/`](agents/examples/backup-cron/). Sync semantics: [cli/README.md](cli/README.md). ## Software download page in 10 minutes (“Releases on R2”) Select a folder of installers / zips → **Publish as download page**. Davflare copies files into `sites/{slug}/`, writes a page with **filename, size, SHA-256**, and optionally renders a sibling `README.md` as release notes. Copy `https:///{slug}/`. Reuses the existing static-site publish flow — **no new API**. 1. Deploy with `SITES_HOST`, leave **Sites** on. 2. In the file manager, open a folder of `.zip` / `.exe` / `.dmg` / … (or select the folder) → **Publish as download page**. 3. Copy `https:///{slug}/` and share it. Distinct from public directory, album, docs, podcast RSS, and nav site. Sample: [`agents/examples/folder-downloads/`](agents/examples/folder-downloads/). ## PDF library / ebook bookshelf in 10 minutes Select a folder of PDFs (optional EPUBs) → **Publish as PDF library**. Davflare copies files into `sites/{slug}/`, builds a bookshelf page with **filename, size, open-in-browser / download**; existing thumbnails become covers. Copy `https:///{slug}/`. Reuses the existing static-site publish flow — **no new API**. 1. Deploy with `SITES_HOST` and keep **Sites** enabled. 2. In the file manager, open a folder of `.pdf` / `.epub` (or select the folder) → **Publish as PDF library**. 3. Copy `https:///{slug}/` and share it. Distinct from download page, docs site, album, podcast RSS, public directory, and nav site. Sample: [`agents/examples/folder-bookshelf/`](agents/examples/folder-bookshelf/). ## Podcast RSS in 10 minutes Select a folder of audio/video files → **Publish as podcast / RSS**. Davflare copies media into `sites/{slug}/`, writes **RSS 2.0** `feed.xml` (enclosures on `SITES_HOST`), and a simple list player page. Reuses the existing static-site publish flow — **no new API**. 1. Deploy with `SITES_HOST`, leave **Sites** on. 2. In the file manager, open a folder of `.mp3` / `.m4a` / `.mp4` / … (or select the folder) → **Publish as podcast / RSS**. 3. Copy `https:///{slug}/feed.xml` into Apple Podcasts / AntennaPod / Overcast / … Distinct from album, docs site, public directory, and nav site. Sample: [`agents/examples/podcast-rss/`](agents/examples/podcast-rss/). ## Phone upload in 30 seconds (iOS Shortcuts / Android) From the Share Sheet, drop a photo or file into free R2. Open `#/settings` → **Phone upload (iOS Shortcuts / Android)**: copy the filled-in upload URL / auth headers, build one iOS Shortcut (or paste curl into Android HTTP Shortcuts). Reuses existing `POST /api/upload` (drive folder) and `POST /api/images` (public CDN) — **no new API / MCP**. Distinct from WebDAV mount, PicGo/ShareX, paste-screenshot image host, and file-request collect links. Sample: [`agents/examples/mobile-upload/`](agents/examples/mobile-upload/). ## Paste a screenshot, get a CDN link in two seconds In the **file manager**, **`#/images`**, or **`#/settings`** (Image host clients card), press **Ctrl/Cmd+V** with a screenshot on the clipboard. Davflare uploads via existing `POST /api/images` — **no new API** — then toasts a one-click copy of `https:///i/{id}`. In the file manager the same paste also queues the file into the current folder. Text Quick paste stays on the toolbar button (clipboard text → share). Image paste never opens the text Paste dialog. Sample notes: [`agents/examples/paste-image-host/`](agents/examples/paste-image-host/). ## Markdown image host in 10 minutes Turn your R2 bucket into a private Markdown image host (PicGo / ShareX / Typora). Reuses `POST /api/images` — **no new APIs**. 1. Deploy with `SITES_HOST`, leave **API Key** and **Image host** on, create a key (`fd_…`). 2. Open `#/settings` → **Image host clients**: - **ShareX** — download `.sxcu`, replace `YOUR_API_KEY`, import. - **Typora** — copy the one-line Custom Command curl (replace the key; `$1` is the file). - **PicGo / PicList** — install [`picgo-plugin-davflare`](picgo-plugin-davflare/) (local folder, or `picgo install picgo-plugin-davflare` after the owner publishes to npm). 3. Upload a test image (or **Ctrl/Cmd+V** a screenshot in the file manager / `#/images` / Settings); public URL is `https:///i/{id}`. Details: [docs/sites.md#markdown-image-host-in-10-minutes](docs/sites.md#markdown-image-host-in-10-minutes) · [`agents/examples/image-host-export/`](agents/examples/image-host-export/) · [`picgo-plugin-davflare/`](picgo-plugin-davflare/). ## Documentation | Topic | Link | | --- | --- | | Deploy, env vars, feature switches, post-deploy `#/setup` checklist; MCP playground `#/mcp` | [docs/deploy.md](docs/deploy.md) · [docs/API.md](docs/API.md) | | WebDAV clients & limits; **compatibility matrix + litmus** | [docs/webdav.md](docs/webdav.md) · [docs/webdav-clients.md](docs/webdav-clients.md) | | Open API & MCP (incl. chat share / zip folder examples) | [docs/API.md](docs/API.md) | | Static sites & image host; **podcast RSS / download page / paste screenshot / PicGo / phone upload** | [docs/sites.md](docs/sites.md) · [agents/examples/podcast-rss/](agents/examples/podcast-rss/) · [agents/examples/folder-downloads/](agents/examples/folder-downloads/) · [agents/examples/folder-bookshelf/](agents/examples/folder-bookshelf/) · [agents/examples/paste-image-host/](agents/examples/paste-image-host/) · [picgo-plugin-davflare/](picgo-plugin-davflare/) · [agents/examples/image-host-export/](agents/examples/image-host-export/) · [agents/examples/mobile-upload/](agents/examples/mobile-upload/) | | GitHub Action — deploy a build dir to a site (`uses: fanchenggang/Davflare@main`) | [docs/sites.md#github-action-deploy-to-davflare-site](docs/sites.md#github-action-deploy-to-davflare-site) | | Agent layouts (`pull` / `push`); MCP one-click export; **official Agents skill** | [docs/agents.md](docs/agents.md) · [skills/davflare/](skills/davflare/) · [agents/examples/davflare-skill/](agents/examples/davflare-skill/) · [agents/examples/mcp-export/](agents/examples/mcp-export/) | | CLI (`davflare-cli`); scheduled backup (crontab + Actions) | [cli/README.md](cli/README.md) · [agents/examples/backup-cron/](agents/examples/backup-cron/) | | Chrome extension (install + bookmarks) | [extension/README.md](extension/README.md) | | Bookmark portability | [docs/bookmarks-portability.md](docs/bookmarks-portability.md) | | Testing | [TESTING.md](TESTING.md) · [TEST_CASES.md](TEST_CASES.md) | ## Acknowledgments - [longern/FlareDrive](https://github.com/longern/FlareDrive) by [longern](https://github.com/longern) — original fork; this project has been fully rewritten since. Internal object prefix is still `_$flaredrive$/`. - [r2-webdav](https://github.com/abersheeran/r2-webdav) by [abersheeran](https://github.com/abersheeran) — WebDAV implementation. - [HamHome](https://github.com/bingoYB/ham_home) by [bingoYB](https://github.com/bingoYB) — bookmark library UX was inspired by this open-source reference. ## License [MIT](./LICENSE)