Uploads

Anchorify has two multi-file upload surfaces: the web upload page and the CLI upload-folder subcommand. Both let an admin publish a batch of files to a single project with one visibility tier.

Web — /<org>/<project>/upload

Admin-only. The page is a file picker (<input type=file multiple>) plus a visibility radio that applies to the whole batch. Submit POSTs the multipart form to the same path.

Behavior per file:

  • Size limit: 1 MiB (MAX_SHARE_BYTES). Oversize files are rejected with a per-row error; the rest of the batch continues.
  • Slug: kebab-cased basename. Q1 Report.mdq1-report. Slug collisions auto-suffix -2, -3, … up to 50 attempts.
  • Content type: filename extension (see content types).
  • Binary detection: a NUL byte in the first 1KB routes the file to the binary path — bytes go to R2 storage under shares/<share_id>/<filename> and the share's content column gets the sentinel "@@blob". The content type is image, pdf, or binary based on MIME + extension.

The success page lists one row per file with a status (✓ created, ✓ created as <slug> for auto-renames, ✗ <error> for failures) and the new URL.

CLI — anchorify upload-folder <dir>

Recursive: walks the directory tree, flattens nested paths into slugs (docs/intro.mddocs-intro), publishes each text file via POST /.

anchorify upload-folder ./drafts
anchorify upload-folder ./drafts --project q1-reports
anchorify upload-folder ./drafts --visibility members
anchorify upload-folder ./drafts --dry-run    # list slugs, no POST

Flags:

  • --project <slug> — required when the org has 2+ projects. Without it, the server returns a 400 with the list of projects + the exact retry command.
  • --visibility <tier> — applies to every file in the batch.
  • --dry-run — prints <slug>\t<rel-path> per file and exits without hitting the server.

Skipped at walk time: dotfiles (.git, .DS_Store) and node_modules. Binaries are rejected per-file ("not yet supported"); use the web upload page for those.

Exit code is 1 if any file errored, 0 otherwise. The first error is printed; the loop continues so a single broken file doesn't sink the batch.

Moving shares between projects

A share can move to a different project in the same org without re-uploading. Old URLs 301 to the new canonical URL via the K4 redirect chain.

  • Dashboard: open the share's actions menu () → Move to… → pick a project.
  • CLI: anchorify move <slug-or-id> --to <project>.
  • API: POST /api/v1/shares/<id>/move {project_id|project_slug}.

Cross-org moves are blocked — use invites to bring the recipient into your org first.