Coline Docs
Sites

Files

Visitor uploads, public and private files, the team's view, and storage limits.

A site can accept files from visitors: avatars, photos, attachments. Files are stored with the site and served from the site's own address.

Accept uploads

permissions: ["site.serve", "storage.app", /* ... */],
surfaces: {
  site: {
    entry: "site/main.tsx",
    uploads: { who: "signedIn", types: ["image/*", "application/pdf"], maxFileBytes: 5_000_000 },
  },
},
FieldMeans
whosignedIn (the default) or visitor, which includes guests
typesContent types the site accepts. image/* matches every image type
maxFileBytesLargest file, up to the plan's limit

Uploads need the storage.app permission and a claimed site. Sites deployed without an account refuse them with SITE_UPLOADS_REQUIRE_CLAIM.

In the page

import { useUpload } from "@colineapp/sdk/site/react";

const { upload, uploading, error } = useUpload();

<input
  type="file"
  accept="image/*"
  onChange={async (event) => {
    const file = event.target.files?.[0];
    if (file) {
      const stored = await upload(file, { public: true });
      // stored: { id, name, size, contentType, public, url, createdAt }
    }
  }}
/>

Without React, site.files has the same calls:

import { site } from "@colineapp/sdk/site";

const stored = await site.files.upload(file, { name: "avatar.png", public: true });
const mine = await site.files.list();   // this visitor's files, newest first
await site.files.delete(stored.id);
site.files.url(stored.id);              // "/_coline/files/<id>"

Keep the id or url in a record to show the file later, for example <img src={profile.data.avatarUrl} />.

Public and private

  • A public file can be read by anyone with its URL. Use it for images other visitors see.
  • A private file (the default) can be read only by the visitor who uploaded it, and by the team.

Files are always served from the site's address with a sandboxed content policy and nosniff, so a file can't run script there. HTML, JavaScript, executables and anything whose bytes look like them are refused, whatever type the upload claims.

When a guest signs in, their files move with them. Deleting a visitor deletes their files.

The team

  • The developer console's Site settings list recent files, download them, and delete them.
  • npx coline-app storage list|put|get|delete does the same from a terminal. put stores a file as the team; --public makes it shareable.
npx coline-app storage put ./hero.jpg --public
npx coline-app storage get sf_... --out ./download.pdf

Limits and billing

Uploads are included in the plan; there's no separate storage charge.

UnclaimedFreeWorkspace Pro
UploadsNo1 GB across the workspace's sites100 GB per site
Largest file10 MB25 MB

A full site refuses new uploads with SITE_STORAGE_FULL until files are deleted or the workspace upgrades.

CodeMeans
SITE_UPLOADS_DISABLEDThe site doesn't declare uploads
SITE_UPLOADS_REQUIRE_CLAIMThe site isn't claimed yet
sign_in_requiredwho: "signedIn" and the visitor is a guest
SITE_FILE_TOO_LARGEOver maxFileBytes or the plan's limit
SITE_FILE_TYPE_NOT_ACCEPTEDNot one of the site's types
SITE_FILE_TYPE_BLOCKEDHTML, script or an executable
SITE_STORAGE_FULLThe plan's storage is used up

On this page