Docs
Home

Creating a database

Create a workspace Canvas database with typed records and views.

A Canvas database is a workspace structured table of records with its own entry under Canvas. Each row is a record with typed cells, and the same data can be saved through multiple views (table, board, list, gallery, feed) — see Database views.

Use a database for anything you'd otherwise track in a spreadsheet: projects, customer accounts, bug reports, content pipelines, OKRs, release checklists.

Creating a database

  1. Open Canvas at the bottom of the sidebar, below Direct messages, and choose New canvas.
  2. Pick Database.
  3. Give it a name. Monad creates the database and opens its direct Canvas page.

A new database starts with no columns and one default Table view.

Naming, icon, and description

At the top of every database — just like a document — you can set:

  • An icon. Click Add icon on the toolbar row above the title and pick an emoji. The icon then shows at full size above the title and helps the database stand out. Click an existing icon to change or remove it.
  • A title. Click the large title and type. The name updates in the Canvas directory/sidebar and on mention chips.
  • A description. Click Add a description… under the title to add a short line about what the database is for. Everyone with Canvas access sees it.

The live indicator and the menu sit in the top-right corner above the title. All three edits save automatically and sync to authorized viewers in real time.

Column types

Every column has a kind that controls how the cell renders, what you can type into it, and how filters and sorts behave. There are 16 column kinds; the most common are listed first.

KindWhat it stores
StringFree-form text. Optionally rich-text (Markdown). Capped at 256 KiB per cell.
IntegerWhole numbers. Sortable as numbers.
DecimalFixed-point numbers with declared precision and scale.
BooleanA checkbox — on or off.
TimestamptzAn instant in time, stored with time-zone awareness.
Date range tzA start/end timestamp pair (e.g. an event window or a sprint).
Enum (single)One of a fixed list of options, each with a label and color.
Enum (multi)Any number of options from a fixed list.
URLA link. Renders as a clickable URL.
EmailAn email address. Click to open in your mail client.
UserA workspace member. Shows their avatar and name; click a cell to pick a member from a searchable list.
AttachmentA file uploaded to the workspace, referenced by ID.
Canvas object refA pointer to another canvas (document or database).
Database relationA typed link to another canvas database. Cardinality is one or many per column.
FormulaA computed value derived from other columns. See Formulas below.
DynamicA column whose payload type isn't known yet — useful during import. Narrow later.

Enum (select) columns

Enum is the most common column for kanban-style workflows. Each option has a label and a color, picked from a 9-entry palette (blue, green, yellow, purple, pink, orange, cyan, red, gray) that matches the rest of Monad. Single-select lets a row hold one option; multi-select lets it hold many.

A new Select or Multi-select column starts with no options — cells show an empty dash until options exist. To add your first option, click any cell in the column: the option picker opens, and you can type a name and press Enter to create an option inline. Options you create this way are immediately available to every cell in that column.

Cells whose stored option ID no longer exists in the column's option list (for example, after an option is deleted) also display rather than a raw identifier.

User columns

Add one from the + menu at the right edge of the column headers — name it and pick Person. Click a User cell (or start typing on it) to open a searchable member picker — the same kind of list you get from an @ mention. Type to filter by name or handle, then pick a member to assign them. Choose Unassigned to clear the cell. Each cell holds one member, shown as their avatar and name.

Dynamic columns

When you import data and Monad can't infer a type (mixed strings and numbers, mostly), the column lands as Dynamic. Each cell stores its own scalar value plus a tag describing what it is. When you're ready to commit to a type, the column can be narrowed to a strict kind with one of three policies:

  • Strict — fail the narrowing if any cell can't be coerced cleanly.
  • Coerce best-effort — coerce what you can; the rest stay as-is.
  • Coerce or null — coerce what you can; clear the rest to empty.

The narrowing keeps an audit trail so you can see what changed and why.

Reserved column names

Date-range columns expose two hidden sub-columns (<name>__start and <name>__end) under the hood, so you can't name another column with the __start / __end suffix.

Filters and sorts

Each view stores its own filter and sort configuration so that "open bugs", "this sprint", and "by owner" can each save their own query against the same rows.

Operators

The filter grammar is a closed catalog with the same semantics on the server (SQL) and on the client (offline replay):

  • Equality: eq, neq
  • Ordering: gt, gte, lt, lte, between (with from/to)
  • Set membership: in, not_in
  • Containment (lists / multi-select): contains, not_contains, has_member, not_has_member, set_eq
  • Text: starts_with, ends_with, contains, not_contains
  • Nullness: is_null, is_not_null

Filters compose with AND / OR groups; there's no top-level NOT — negate at the operator instead (e.g. not_contains). Cursor-based pagination keeps long lists responsive.

What the UI exposes today

The structured filter editor is the building block for every view — a visual builder that produces a schema-valid filter for the operator catalog above. The data model, the API, and the agent surface expose every operator today; saved filters round-trip correctly whether they're set by the visual builder, the agent's select_rows tool, or a direct API call.

Rows and cells

  • Add a row — click + Row in the toolbar above the grid.
  • Focus a cell — click it. Arrow keys move the focus.
  • Edit a cell — start typing on a focused cell, press Enter, press F2, or double-click. Enter commits, Escape cancels, Tab commits and moves right.
  • Select a range — Shift+click another cell, or hold Shift while pressing the arrow keys.
  • Select a whole row — click the row number on the left gutter. Shift-click another row number to extend.
  • Select a whole column — click the column header.
  • Reorder columns — drag a column header sideways and drop it on another header. A thin vertical bar shows where the column will land (left edge = before, right edge = after). The new order applies immediately on screen and saves in the background; other viewers see the new order once their browser receives the update. If you're offline, the reorder is queued and replays when you reconnect.
  • CopyCmd+C (macOS) / Ctrl+C (other) copies the selection. A single cell copies as plain text; a range copies as TSV (tab- separated values with newline row separators), ready to paste into another database, a spreadsheet, or any text input. Tabs and newlines embedded inside a cell value are escaped (\t / \n) so the format round-trips.
  • PasteCmd+V / Ctrl+V pastes from the clipboard. A single pasted value drops into the focused cell. A TSV block fans out starting at the focused cell, expanding rightward across columns and downward across rows. If the paste lands past the existing row count, new empty rows are inserted to receive the block. Pasting into a multi-cell selection repeats the block to fill the selection. Values are coerced to each column's kind (number, date, enum-by-label, etc.) — cells that can't be coerced are skipped and logged.
  • Clear cells — select cells (or a range) and press Delete or Backspace. Formula columns are skipped (they aren't writable).
  • Delete rows — select one or more whole rows (click the row gutter), then press Delete. Rows are soft-deleted; restore via version history.
  • Open the full record — click the chevron at the start of any row to open the row detail dialog. Every column appears as a labelled field, which is the easiest way to fill out a row with many columns or to edit kinds the grid can't inline-edit (date-range, attachment, canvas-object reference, database relation).

Every row tracks who last modified it and when, so you can always tell who owns a recent change.

Comments on a database

Every database has page comments — the same kind of page-level discussion a canvas document has, sitting just below the database's title and description and above the view tabs. Use them for questions and decisions about the database as a whole: "How do we want to use this?", "Which view is the source of truth?", "Who owns keeping this current?".

  • Click Add comment at the top of the page; a small composer opens. Type your note and post — it appears in the comment stream for everyone who can open the database. Once the first comment exists, add more from the Add a comment… box at the bottom of the stream.
  • @mention a teammate to pull them in (they're notified and start following the thread), or #mention a space to link it.
  • React with an emoji, and edit or delete your own comments.
  • Resolve a comment when it's handled — it moves into the Resolved list at the top of the page. Archive hides noisy or obsolete threads into the Archived list. Both lists open from the buttons in the database's header, and both actions are reversible.

It's the same thread experience as canvas-document page comments — see Canvas documents → Editor for the full thread UX.

Agents can join in too. An agent that follows a database can post a page comment and reply in a thread, just like a teammate — for example to flag that a column looks out of date or to answer a question you left on the database. Their comments appear in the same stream and notify whoever is following.

Cross-posting a comment to a space

When you post a page comment, you can cross-post it into one or more spaces with the Also post to #channel option. The cross-posted message looks like a normal channel message in each target space, with a link back to the database. Resolve and unresolve stay scoped to the thread itself — they don't fan out to the cross-post targets.

Use cross-posting when you want a fast "heads-up, take a look at this database" in the channel without forcing everyone to open the database tab. If you only need the comment on the database itself, leave the cross-post option off.

Following a database

The Subscribe button (the bell, next to the page menu above the title) turns on notifications for this database — the same control canvas documents have. While subscribed you're notified when the database is updated and when someone posts a new comment on it, even if you've muted the space or set it to mentions-only. Click it again to unsubscribe. Anyone who can open the database can follow it.

Real-time collaboration

Everyone with access sees edits as they happen. Each edit is recorded as a revision on the database; the live view applies them in order. If two people edit the same row at the same time, the second edit lands as a new revision and the first author sees the update.

Unlike a shared spreadsheet, the database is generation-aware: when you revert a revision range (see below) the database's generation bumps, and any in-flight edits made against the old generation are flagged so you can resolve them through a dialog instead of silently losing or duplicating work.

Database page menu

The "…" menu at the top-right of every database carries the page-level actions:

  • Version history — opens the revision side panel (see below).
  • Copy share link — copies a link to this database to your clipboard. It opens the database for anyone who already has Canvas access. See Sharing a database for the details.
  • Export to CSV — downloads the current table as a CSV file. When you have a view selected, the export matches that view: only the columns visible in the view, in the view's order, with the view's filter and sort applied. With no view selected, you get the raw full table. Cell values starting with =, +, -, or @ are prefixed with a leading apostrophe so Excel / Sheets won't interpret them as formulas when the file is opened.
  • Archive — hides the Canvas from normal lists without deleting rows, views, comments, or revision history. See Sharing a database.

Version history and revert

Every op against the database is recorded as a revision with a kind (schema, data, view, comment, revert, narrowing, formula_recompute). From the database menu you can:

  • Revert a single revision — undoes that op and adds a new revision that reverses it.
  • Revert a range — replays the inverse of every revision in the range in reverse order.
  • See who did what, when — the revision list is the audit log.

A revert never deletes the old history — it appends new compensating revisions, so the audit trail stays intact and you can revert the revert.

Offline editing

The web client buffers edits while you're offline. The header pill at the top of the database shows whether you're live, syncing, connecting, or disconnected. Edits made while disconnected queue up; when the connection returns they replay against the latest server head.

If something on the server changed in a way that conflicts with your queued edits (a revert bumped the generation, for example), a dialog asks you whether to retry, discard, or review your queued ops before applying them.

Formulas

A formula column computes its value from other columns in the same row, using a familiar table-formula surface:

[@Status] = "Done" && [@DueDate] < now()
  • References to other columns use [@Name] (the column's display name). The expression compiles to a stable AST keyed off the column ID, so renaming a column doesn't break the formula — the surface re-renders against the new name automatically.
  • A formula declares its return type up front. If a dependency changes type and the formula no longer fits, the column is marked broken with a clear reason ("references column Owner which was dropped", "expected number, got string", etc.) and you can edit the expression to repair it.
  • Arithmetic + booleans + comparisons + if / and / or / not
    • concat + the aggregates sum, count, min, max, avg are supported, alongside as_string, as_integer, as_decimal, etc. for type coercion.

Formulas can't cycle — if you set up A = [@B] + 1 and B = [@A] + 1, the second commit is rejected with a clear error.

Cell-level formulas (a different cell of the same column overriding the column formula) and filtered rollups are planned but not yet shipped — the schema reserves room for both.

Working with agents

Agents in the space can read, query, and modify the database via a structured tool surface — they do not run raw SQL. They can refer to columns by name (not just internal id) and to dropdown options by their label, so a request like "set Status to Done for everything in this sprint" works without you spelling out any ids. The shipped tools are:

  • describe_database — look up the database's columns (name, type, and the available options for dropdown columns) before reading or editing it.
  • select_rows — read rows matching the structured filter DSL, with order, limit, cursor pagination, and column projection.
  • insert_rows — add up to 1000 new rows in a single call, each with the cell values you provide.
  • update_rows — update many rows in one go, each with its own values (for example, fill in a different headcount and founding year for every company). You can point at each row by a unique field like its name, so you don't have to look up row references first.
  • bulk_set_rows — set a single field to the same value on every row matching a filter (for example, mark everything in this sprint "Done", or tag every overdue task "urgent").
  • bulk_delete_rows — soft-delete every matching row (up to 1000 rows; narrow the filter if more match).
  • add_column — add a new column to an existing database (for example, "add a Priority dropdown" or "add a Headcount number column"). Existing rows start empty in the new column.
  • rename_column — change a column's name. The column keeps its data and any formulas that reference it.
  • drop_column — delete a column and all of its values. Ask the agent to revert if it removes the wrong one.
  • revert_database_revision — undo a single revision, a range, or a branch snapshot.

Common asks:

  • "@agent create a database to track our quarterly OKRs with columns for Owner, Status, Quarter, and Target Date."
  • "@agent add the bug we just discussed to the bug tracker, with severity High and owner @alice."
  • "@agent which projects in our project tracker are still in Backlog past their due date?"
  • "@agent undo my last update on the bug tracker."

Because the agent surface is structured rather than free-form SQL, every action is type-checked end to end and the bulk gates protect you from a single mistaken filter blowing away thousands of rows.

Permissions

Like every Canvas, a database has explicit access roles:

  • Viewers can read the database.
  • Editors can add/edit rows, change schema/views, and comment.
  • Managers can change audiences and archive the Canvas.

Audiences can be the workspace, specific people, Groups, or readers of a Space. Workspace admins can manage all Canvases.

There are no per-row or per-column permissions today. (Column-level permissions are stubbed in the schema for a future capability.)

Mentioning a database in a message

Type # in any message or canvas document and pick the database from the autocomplete menu to drop in a chip that opens the database when clicked. The chip is distinguishable from a document mention by its Circle Stack icon and Database badge, and the chip's label stays in sync as the database is renamed.

Tips

  • Start with one view, add more as you need them. It's easy to duplicate a view by adding a new one with the same kind and copying the filter.
  • Group by enum columns to get a board. If you find yourself filtering "by status", a board view is usually a better experience.
  • Use a timestamptz or date-range column for due dates — they sort and filter correctly, and you can run "due in the next week" queries.
  • Use a database relation column to link rows across databases — a row in your projects database can carry a one/many link to rows in a tasks database, and an agent can follow the link in one hop.
  • Database views — the five view kinds and their per-view state.
  • Canvas documents → Editor — the comment thread UX that database comments reuse.
  • Spaces → Overview for how canvases relate to the space they live in.
  • Agents → Concepts for what agents can do with your data.