---
title: crow.json
description: The reference for crow.json, the file at the root of a published folder that turns on data, files, AI, outside APIs, live updates and server code and sets their rules.
---

# crow.json

`crow.json` sits at the root of the folder you publish. It's optional: an app without it is served as plain web files. Each top-level key turns on one feature and sets its rules. Publishing checks the file and refuses anything invalid, with a message that says what to fix.

## A complete example

```json
{
  "data": {
    "tasks": { "read": "viewers", "write": "creator" },
    "scores": { "read": "public", "write": "public-add", "fields": { "name": "string:30", "score": "integer" }, "dailyLimit": 2000 }
  },
  "files": {
    "receipts": { "read": "creator", "write": "viewers", "maxSize": "10MB", "types": ["image/*", "application/pdf"] }
  },
  "ai": { "who": "viewers", "perViewerPerMinute": 10, "dailyLimit": 500 },
  "apis": {
    "stripe": { "url": "https://api.stripe.com/v1/", "headers": { "authorization": "Bearer {{STRIPE_KEY}}" }, "who": "viewers" }
  },
  "live": { "who": "viewers" },
  "server": {
    "who": "viewers",
    "publicPaths": ["/api/webhooks/stripe"],
    "schedules": [{ "cron": "0 9 * * *", "path": "/api/cron/daily" }]
  }
}
```

## Top-level keys

| Key | Turns on | Details |
| --- | --- | --- |
| `icon` | The app's icon, a path in the folder | [Publishing](/publishing#an-icon-is-required) |
| `data` | Rules for `crow.db` collections | [Data](/data) |
| `files` | `crow.files` buckets | [Files](/files) |
| `ai` | `crow.ai` | [AI calls](/ai) |
| `apis` | `crow.api` with secrets | [Outside APIs and secrets](/apis-and-secrets) |
| `live` | `crow.live` channels | [Live updates](/live) |
| `server` | Settings for `server/index.js` | [Server code](/server-code) |

## icon

```json
{ "icon": "assets/logo.svg" }
```

Optional when the folder has `icon.svg` or a `<link rel="icon">` Crow Nest can find, and wins over both. Needs to be SVG, PNG, ICO or WebP, up to 256 KB. See [Publishing](/publishing#an-icon-is-required) for the rules.

## data

One entry per collection. Collections you don't list get `read: "viewers"` and `write: "creator"`.

| Key | Values |
| --- | --- |
| `read` | `public` (anyone who can open the app, signed out too), `viewers` (signed-in people who can open it), `creator` (each person sees their own), `owner` |
| `write` | `viewers` (anyone signed in adds and changes anything), `creator` (add; change only your own), `owner`, `public` (signed-out visitors add and change their own entry), `public-add` (signed-out visitors can only add) |
| `fields` | Required with `public` or `public-add`. Types: `string`, `string:N` (N up to 10000), `number`, `integer`, `boolean`, `email`, `date`, `datetime`; add `?` for optional |
| `unique` | Up to 3 declared fields whose combined value can't repeat |
| `editFor` | With `public`: how long a visitor can change their entry, like `30m`, `24h`, `7d` (at most `365d`) |
| `dailyLimit` | With `public` or `public-add`: signed-out writes a day for this collection, 1 to 50000 |
| `showCreator` | `none` (default), `name` or `email` (not with `read: "public"`) |

`read: "public"` together with `write: "public"` is refused; use `public-add` for a public board anyone can add to.

## files

One entry per bucket.

| Key | Values |
| --- | --- |
| `read` | `public`, `viewers`, `creator`, `owner` |
| `write` | `viewers`, `creator`, `owner`, `public-add` (signed-out uploads on a public app) |
| `maxSize` | Largest file, like `10MB` (up to 25 MB, 100 MB for companies) |
| `types` | Allowed MIME types, wildcards like `image/*` allowed |

## ai

| Key | Values |
| --- | --- |
| `who` | `owner`, `viewers`, or `public` (public apps only) |
| `perViewerPerMinute` | Calls a minute per person |
| `dailyLimit` | Calls a day for the whole app |

## apis

One entry per API, named by you.

| Key | Values |
| --- | --- |
| `url` | Base URL, `https` and ending in `/` |
| `headers` | Headers to send; `{{NAME}}` is replaced with the secret `NAME` |
| `query` | Query parameters to add; `{{NAME}}` works here too |
| `who` | `owner`, `viewers` or `public` |

## live

| Key | Values |
| --- | --- |
| `who` | Who can join channels: `viewers` (default) or `public` (public apps only) |

## server

Only used when the folder has `server/index.js`.

| Key | Values |
| --- | --- |
| `who` | `viewers` (default: signed in and allowed to open the app) or `public` (anyone; public apps only) |
| `publicPaths` | Up to 20 paths under `/api/` that skip the access check, for webhooks. A path ending in `*` matches everything under it |
| `schedules` | Up to 5 jobs, each `{ "cron": "...", "path": "/api/..." }`. 5-field cron in UTC; personal apps at most every 15 minutes |
