The manifest

Every app has a manifest at .brydio/app.json. It names the app, its screens, the records it keeps, where it may appear, and every grant it asks for. @brydio/manifest exports appManifestSchema, its TypeScript types, and defineManifest(). brydio validate and Brydio use the same rules.

This page is generated by bun run docs:manifest. Its field list comes from the Zod schemas, its limits come from the exported constants, and its worked example is the checked-in Issues manifest. Do not edit it by hand.

Issues, as a complete example

This is packages/manifest/examples/issues.json, the proposal app used to exercise project and workspace placements, two collections, generated tools, two screens, collection grants, tool grants, and host grants.

{
  "name": "issues",
  "version": "0.1.0",
  "displayName": "Issues",
  "placements": [
    { "kind": "project-tab", "screen": "board", "label": "Issues", "icon": "kanban" },
    { "kind": "project-sidebar", "screen": "board", "label": "Issues", "icon": "kanban" },
    { "kind": "workspace-sidebar", "screen": "board", "label": "Issues", "icon": "kanban" }
  ],
  "data": {
    "issues": {
      "schema": {
        "title": "string",
        "status": ["todo", "doing", "done"],
        "assignee": "member?",
        "labels": "string[]",
        "body": "text?",
        "project": "project?"
      },
      "search": ["title", "body"],
      "label": "issue"
    },
    "labels": {
      "schema": { "name": "string", "colour": "token" },
      "label": "label"
    }
  },
  "tools": { "generated": true, "custom": [] },
  "screens": {
    "board": { "entry": "screens/board.js" },
    "issue": { "entry": "screens/issue.js" }
  },
  "grants": { "tools": ["*"], "collections": ["*"], "host": ["navigate", "message"] }
}

Top-level fields

FieldTakesRequiredWhat it does
namekebab-case text, at most 64 charactersyesThe stable app key. A published app keeps this name for every version.
versionsemver text, at most 64 charactersyesThe app version. A published version is immutable.
displayNametext, at most 80 charactersnoThe name people see. Brydio falls back to name when this is absent.
summarytext, at most 240 charactersnoOne sentence shown in the directory and install flow.
descriptiontext, at most 4,000 charactersnoThe longer explanation of what the app does.
author{ name, email?, url? }noThe app author. name is required inside this record.
homepagetextnoThe public page for the app.
repositorytextnoThe source repository for the app.
licensetext, at most 64 charactersnoThe licence identifier or name for this app.
keywordsa list of at most 20 stringsnoWords used to find the app in the directory.
links{ privacy?, terms?, support? }noPublic policy and support links shown with the app.
icontextnoThe app icon reference used by Brydio.
brandColortextnoThe legacy light-theme brand colour.
brandColorDarktextnoThe legacy dark-theme brand colour.
defaultPromptsa list of at most 3 stringsnoPrompts Brydio may offer when the app is installed.
skillsa relative pathnoThe legacy skill declaration path.
serversa relative pathnoThe legacy MCP server declaration path.
integrationsa relative pathnoThe legacy integration declaration path.
requires{ servers?, integrations?, builtin? }noLists extension dependencies. Each inner value is a list of ids.
metadataa record of JSON valuesnoPublisher metadata that Brydio preserves without giving it SDK meaning.
placementsa list of placement offersnoWhere a person may place the app. Each offer names a declared screen.
dataa record of collectionsnoThe records the app keeps. Each collection declares its fields and generated-tool noun.
tools{ generated?, custom? }noGenerated collection tools and custom server-side handlers.
screensa record of { entry } valuesnoThe screen names and their compiled .js or .mjs entries inside the bundle.
grants{ tools?, collections?, host? }noEverything the app asks a workspace to let it read, call, or open.
migrationsan ordered list of versioned migration stepsnoHow existing records move when a later version changes a collection schema.
sdksemver textnoWritten by brydio build. Do not add or edit it in .brydio/app.json.

Unknown top-level fields are rejected. The sections below expand the fields that have their own nested grammar.

Placements and screens

Each placements entry has a kind, a screen, and optional label and icon text. kind is project-tab, project-sidebar, or workspace-sidebar. screen must name a key in screens. Each screen has one entry, a relative .js or .mjs path inside the built bundle.

Collections and schema types

Each key in data is a collection name. A collection has a required schema, an optional singular label used in generated tool names, and an optional search list. Search fields must use string, text, or string[].

Manifest spellingStored value
stringShort text, at most 1,000 characters.
textLong text, at most 100,000 characters.
["todo", "done"]A choice. It may list at most 50 unique values.
memberA Brydio member id.
projectA Brydio project id. One collection may have one project field.
dateAn ISO calendar date in YYYY-MM-DD form.
numberA finite number.
booleantrue or false.
string[]A list of at most 100 short strings.
tokenOne of neutral, brand, success, warn, danger.

Add ? to a named type to make the field optional, such as member?. A field may also use { "type": ..., "optional": true, "default": ..., "labels": ... }`. Only optional choices and booleans may have defaults. Choice labels are 1 to 60 characters and may name only declared values.

Tools

tools.generated defaults to true. Each collection then gets create, update, get, list, search, delete, and batch tools. tools.custom may hold at most 20 handlers. A custom tool has a lower-case name, a description, a built handler path, and optional input, write, and collection. Its input fields use the same schema types as collection fields. A custom tool that writes must set write: true, which makes Brydio ask the person before it runs.

Grants

grants.tools names generated or custom tools, a collection noun, or *. grants.collections names collections or *. grants.host may contain:

A named connection grant is connection:<name>. * never grants a connection. A collection the app keeps must appear in grants.collections, and a custom tool must appear in grants.tools unless that list has *.

Migrations

When a published version changes a collection schema, migrations explains how records from earlier versions become readable by the new one. Each entry has the target version and 1 to 100 steps. Keep every migration in order so a workspace several versions behind can run each one.

OperationWhat it does
addAdd a field. A required field needs a valid default for existing records.
renameMove one field to a new name without losing its values.
dropRemove one field and its stored values.
dropCollectionRemove a collection and all records it kept.
replaceReplace one removed choice value with a value the new schema allows.

Limits

The generator reads these values from FIELD_LIMITS and DOCUMENT_LIMITS. The manifest validator and the fake host use the same exports.

LimitValueWhat it bounds
FIELD_LIMITS.collections20Collections one app may keep
FIELD_LIMITS.fields40Fields one collection may have
FIELD_LIMITS.enumValues50Values one choice may allow
FIELD_LIMITS.enumValueChars64Characters in one of a choice's values
FIELD_LIMITS.stringChars1,000Characters in a string value
FIELD_LIMITS.textChars100,000Characters in a text value
FIELD_LIMITS.listEntries100Entries in a string[] value
FIELD_LIMITS.nameChars40Characters in a collection, label, field or screen name
LimitValueWhat it bounds
DOCUMENT_LIMITS.pageDefault50Records returned when a list or search does not say how many
DOCUMENT_LIMITS.pageMax200Records one list or search page may return
DOCUMENT_LIMITS.bodyBytes262,144Bytes in one stored record
DOCUMENT_LIMITS.pageBytes2,097,152Bytes after which a page stops and returns a cursor
DOCUMENT_LIMITS.recordsPerCollection100,000Live records in one collection of one instance
DOCUMENT_LIMITS.batchChanges50Changes one batch_<plural> call may make

The full validation list, with every problem code and refusal sentence, is in the publish checklist.