---
title: Monday (the earlier name of the built-in board app)
---

# Monday

## What it is

> **Superseded by [Mission Control](mission-control.md)** — the Monday plugin was renamed
> (`mondayEnabled` → `missionControlEnabled`, `src/plugins/monday` → `src/plugins/mission-control`);
> this page is kept as a historical record of the pre-rename phase history and is no longer maintained.

A pixel-near **monday.com** clone, built as an isolated React sub-app and surfaced inside Omniscio as a sidebar virtual project. Gated on `mondayEnabled` (default off). **Phase 2 (Board core / Main Table) shipped** (on top of Phase 0 auth + Phase 1 workspace shell) — opening a board renders the signature **Main Table**: groups of items with a **typed-EAV column engine** (status, text, long-text, numbers, people, date, timeline, dropdown, checkbox), inline cell editing, status pills with Edit Labels, a Column Center to add columns, and group-footer summaries. **Phase 2b** added the **item card** (a modal with an Updates feed), **item duplicate/delete**, and a **batch-action bar** (multi-select → archive/delete). **Phase 2c** added **drag-and-drop reorder** (items within/across groups + groups, via `@dnd-kit`) and a **WS realtime board channel** — every mutation publishes a `board-changed` event over `/realtime` and connected clients reload (the client disconnects on unmount). **Phase 3a** added the **view system**: a `views` table + a view-switcher (Main Table + saved views), the first alternate view — **Kanban** (group items by a status column, drag a card between columns to set its status) — and four more column types (link, email, phone, rating). **Phase 3b** added two more views — **Calendar** (place items on a month grid by a date column, with an unscheduled strip) and **Cards** (a gallery) — plus an add-view menu and the country/week/world-clock column types. Alternate views are just `views` rows whose `type` (a free string) + `config` the frontend switches on, so a new view is a component + a render branch — no backend change. **Phase 3c** added the **Main Table view controls** — search (across the item name + all column text), sort (by a column or name, asc/desc), a per-column contains filter, and hide-columns — all client-side over the loaded board data (no backend). **Phase 3d** added the **Chart** view — bucket items by a column and render the counts as a bar or pie (group-by + chart type are local UI state); it's a config-only view over the loaded data. **Phase 3e** added the **Timeline/Gantt** view — bars across a time track by a timeline column, with month gridlines and an unscheduled strip. So the board now has **six views** (Main Table, Kanban, Calendar, Cards, Chart, Timeline). **Phase 3f** added the last view — **Form**: a board→form whose submissions create items, backed by a **public (unauthenticated), tokened** submit endpoint (`formsPublicRoutes` in monday-back). That endpoint is deliberately narrow: token-gated, create-only, accepts values only for the form's configured fields, validates each through the column-type registry, and returns no board data. So **all six board views now ship** (Main Table, Kanban, Calendar, Cards, Chart, Timeline, Form). **Phase 4** begins the cross-board surfaces. **Phase 4a** shipped **Search Everything** — a backend `GET /search?q=` and a `SearchPage` (debounced, opens a result on click; the top-bar search routes here). It began **items-only** (grouped by board); a parity fast-follow **broadened it to four result types — items, boards, dashboards, and people, grouped by type** (private boards you're not a member of are excluded from every group) — see **Grouped search** below. **Phase 4b** shipped **My Work** — a backend `GET /my-work` that returns the items assigned to me (matched by `auth.userId` against any People column value, account-scoped) each with one derived date (the board's first date/timeline column the item has set), and a `MyWorkPage` that buckets them into monday's six date sections (Past dates / Today / This week / Next week / Later / Without a date) as a table; clicking a row opens its board. A **fast-follow** upgraded My Work pixel-near: `GET /my-work` now also resolves, per the item's board, the **first column of each type** (group, people, status, priority) so the page renders the full table — name · Group · Board · People · Date · Status · Priority — with **colored, collapsible time-bucket sections**, an **overdue** alert on past dates, a **New item / + Add task** board→group picker (creates via the shared `POST /items`), and a working **Calendar tab**. The calendar is the board's grid reused: `CalendarView`'s month/week/day grid was extracted into a shared presentational **`CalendarGrid`** (driven by a generic `CalEvent[]` + `useCalendarNav`/`CalendarNav`); the board became a thin adapter and `MyWorkCalendar` feeds it cross-board items as uniform light-blue "Due date" events. The enrich is read-only (no migration); status vs priority are distinct backend column **types**, so they separate cleanly. Bucketing/overdue math is unit-tested (`tests/unit/plugins/mission-control/my-work-buckets.test.ts`); spec `docs/superpowers/specs/2026-06-08-monday-my-work-design.md`, plan `docs/superpowers/plans/2026-06-08-monday-my-work.md`. **Phase 4c** shipped **Notifications** — a `notifications` table whose rows are written ONLY as a server-side side-effect of an owner-checked mutation (a People-column write that adds you → an `assigned` notification; an `@YourName` in an item update → a `mentioned` one; the actor is never notified about their own action), read via `GET /notifications` + `GET /notifications/unread-count` (both owner-scoped by `auth.userId`) with `POST /:id/read` + `POST /read-all`, and a `NotificationsPage` (a bell feed with tabs All / Unread / I was mentioned / Assigned to me, mark-read on click, mark-all-read) plus a top-bar bell badge. **Phase 4d** shipped **Dashboards** — a `dashboards` table (workspace-scoped + account-isolated like boards) with an opaque `config` JSONB (`boardIds` + `widgets`); it's **config-only** (no per-widget backend), with CRUD via `dashboardsRoutes`. The `DashboardPage` computes every widget client-side over the existing ownership-checked `GET /boards/:id/full` (so a foreign board id in config just 404s — no leak); a left-nav "Dashboards" section lists + creates them. **Phase 4d-redesign** rebuilt it pixel-near monday: a header (favorite star, inline-rename, Export ▾ / Invite / ⋯ overflow), a toolbar (**+ Add widget** dropdown, **N connected board** → connect-boards modal, type-to-filter, save with dirty-dot, **People** + **Filter** scopers, settings gear), a polished empty state, and a **drag-and-resize grid** (`react-grid-layout`; per-widget `layout {x,y,w,h}` stored in `config`). Editing is always-on with a **draft + debounced-autosave** model (no Edit/View toggle). Widgets: **Numbers** (abbreviated $378k figure), **Chart** (bar / column / pie / donut / line), the sprint trio **Velocity / Planned-vs-unplanned / Burndown** (frontend-computed from configured sprint/effort/done/date columns — Velocity faithful, the other two documented **approximations** since there's no sprint-history backend). Battery/Table/Apps remain in code but off the menu. Toolbar **People**/**Filter** write `config.filters` and scope every widget's data via a shared `applyFilters` (a rule only constrains boards that have its column); **Export** rasterises the grid with `html-to-image` (PNG / print-to-PDF); **Invite** reuses the member directory. Pure logic (`dashboardLayout` / `sprintData` / `dashboardFilter`) is unit-tested; design spec at `docs/superpowers/specs/2026-06-07-monday-dashboard-redesign-design.md`. **Phase 4e** shipped the **Activity log** — an `activity_log` table whose rows are written ONLY server-side (via `lib/activity.ts`) as a side-effect of an owner-checked item mutation (item **created / renamed / deleted** and **column value changed**, each with a prev→next summary; the actor is joined separately, not baked into the text), read via `GET /activity?boardId=&itemId?=` (gated by `ownedBoard`, newest-first), and surfaced two ways — the **ItemCard Activity tab** (item-level) and a **board-level Activity modal** from the board header (both render a shared `ActivityFeed`). **All Phase 4 cross-board surfaces now ship** (Search, My Work, Notifications, Dashboards, Activity log). Next: the automations engine (Phase 5).

## Where to find it

There is nothing to open under this name any more — it was renamed to **Mission Control**, and the sidebar entry, settings key and documentation all carry the new name.

### UI surface

A **"Monday"** row in the projects sidebar (alphabetical slot after MCP Servers, before PR Merge Queue), shown only while `mondayEnabled` is on. Enable it at **Settings → Features → Enable Monday**. Clicking the row mounts the Monday app full-pane (no Omniscio SessionsSidebar — it hosts no Omniscio sessions). Auth is via Omniscio's Firebase Global Auth — users sign in once via Omniscio; when not signed in to Omniscio, a "Not signed in" placeholder is shown.

## How it behaves

### Workspace shell (Phase 1)

Once authenticated, the panel mounts a `MemoryRouter` (Omniscio owns the real URL) → an `AppShell`: a **top bar** (wordmark, search bar, notifications bell with unread badge, and an **account menu** — an avatar button at the far right that opens a dropdown with the user's identity, a theme toggle, and a log-out option; matches Ollert's `AccountMenu` pattern) and a **left nav** with a workspace switcher (a monday workspace header + ⋯ actions menu — see Workspaces functionality below), a "My Work" entry (the cross-board My Work table + calendar — see Phase 4b), and the board list for the active workspace. Clicking **+** creates a board (with a default group) and navigates to it. **Home** shows recent boards (first-N for now) with empty states; **workspace** and **board** routes render their own pages (the board is a Phase-2 placeholder). The whole tree comes from one backend aggregate, `GET /nav/tree` → `{ workspaces: [{ ...ws, folders, boards }] }`, fetched by `useNavTree()`.

The backend (`amc-back/`) adds account-scoped CRUD modules — `workspaces`, `folders`, `boards` (each guarded by a shared `requireAuth` Elysia plugin that verifies the Firebase ID token via `admin.auth().verifyIdToken()` and derives `{ userId, accountId }`, filtering every query by `accountId`; dual-auth: also accepts legacy JWT during migration) — plus the `/nav/tree` aggregate. Registering a new account auto-seeds a "Main workspace".

### Main Table (Phase 2)

The board route (`/board/:id`) renders `BoardView`, which loads everything in one call — `GET /boards/:id/full` → `{ board, groups, columns, items, values }` — and draws a custom grid (no heavy table lib): a column header (with a **Column Center** `+` to add any of the essential column types), then each group (colored strip, collapse) as item rows, an "+ Add item" row, and a group footer of per-column summaries. Each cell is driven by a **frontend column registry** (`features/board/columns/`) that maps a column `type` to a renderer/editor — the status cell is a colored pill with a label picker + Edit Labels; numbers/text/date/checkbox/timeline/people/dropdown have inline editors.

The backend's core primitive is the **column-type registry** (`src/lib/column-types/` in `monday-back`): one handler per type owning `defaultSettings` / `validate` / `serialize` / `toText` / `summarize`. `columns` rows store `type` + `settings` (JSONB); `column_values` rows store `value` (JSONB) + a denormalized `text`. Writing a cell (`PUT /items/:id/columns/:colId`) validates the value through the registry (HTTP 400 on a bad value), so a status value must match one of its column's labels. New backend modules — `groups`, `columns` (the Column Center), `items` + column-values — are account-scoped through the board's workspace via a shared `ownedBoard` helper.

### Board filter toolbar (post-Phase-4 fast-follow)

A pixel-near rebuild of monday's Main-Table toolbar, replacing the plain Phase-3c controls with monday's real filter surfaces (`features/board/BoardControls.tsx` + `features/board/toolbar/`). The row reads as one control set — **New task · Search · Person · Filter · Sort · Hide** — over the shared `ToolbarButton` shape (`px-2.5 py-1 text-sm`, 1px border, foreground text idle → accent when active). All logic is a pure module (`features/board/boardQuickFilter.ts` + codec), compiled to a predicate in `BoardView` and applied client-side over the loaded board data (no backend).

- **Board search** — collapsed it's a plain toolbar button (search glyph + "Search"); clicking **expands it in place** into a ~240px "Search this board" input (accent border) that owns the query. Escape clears + collapses, an empty blur collapses, a non-empty value keeps it open.
- **Person filter** — a toolbar button (accent-tint fill when active) opening a popover of member avatars; multi-selecting members filters items by the people assigned to them.
- **Quick filters panel** — the Filter split-button (funnel + "Filter", showing **"Filter / {n}"** once selections exist; accent-tint fill when the panel is open or `n > 0`) opens a wide panel of **per-column facet columns**, each a scrollable list of multi-select chips. Chips are **OR within a column, AND across columns**. The panel **stays open across chip clicks** (only a click-away closes it); a header **"Showing X of Y tasks"** count and a **Clear all** reset are always present.
- **Save as new view** — both the Person popover and the Quick filters panel offer **"Save as new view"** (enabled only when a real handler exists and something is filtered). It persists the **current filter set as a new saved view tab** (a `views` row) via the existing view system. Edits to filters while viewing an already-saved view are **session-only** — they don't mutate the saved view until you save again as a new one. The save is guarded against **double-submit**.

Pure filter/codec logic is unit-tested (`tests/unit/plugins/mission-control/board-quick-filter.test.ts`); the toolbar components have component coverage (`search-board-button`, `person-filter-button`, `quick-filters-panel` under `tests/unit/plugins/monday/`).

### Grouped search (Phase 4a, extended)

Search Everything originally returned **items only**, grouped by board. A parity fast-follow **broadened it to four result types — items, boards, dashboards, and people — grouped by type**. **Private boards you're not a member of are excluded** (both the board results themselves and any items on them; dashboards and people are workspace/account-scoped and unaffected), consistent with the private-board enforcement above.

### Board favorites (parity fast-follow)

The **star** in the board-info popover is now wired to **real favorites** — starring a board persists it as a favorite (it was previously a dead control). (The automations engine is still future — Phase 5.)

### Stub cleanup (no dead buttons)

Every affordance that did nothing was either wired up or removed, so a control the user can see is a control that works. **Wired:** the view menu's **Share** item now opens the board share modal (access is per-board, not per-view, so it's labelled "Share board"); the board nav-row's **Add to favorites** now toggles the shared `FavoritesProvider`; and **User management** gained a real **Filter** menu (`features/users/UserFilterMenu.tsx`) — client-side status + role facets over the already-loaded member list, where an empty facet means "no constraint" and the two facets AND together. **Removed** (each needs a subsystem nobody has built): _Save as template_ (board nav + workspace ⋯), My Work's _Customize_, the Gantt toolbar's _Baseline_/filter/⋯ affordances, the dashboard widget's _Dock this widget_, the workspace _Feedback_ button (the plugin has no host bridge to Omniscio's intake), and the board-info popover's fake "🔔 Everything" notifications row. The **Apps** widget left the Add-widget menu, but `'apps'` stays in the persisted `WidgetType` union and `WidgetCard` still renders a placeholder body for it, so a dashboard that already saved one keeps working — it just can't be added again.

## Related

- [mission-control.md](mission-control.md) — the current name, and the page to read instead of this one.
- Monday part 2 — workspaces, sharing, the data mirror and the automations, carried over unchanged.
- [mc-templates.md](mc-templates.md) — board templates, one of the parts that came with the rename.

### See also

- monday-integration-contract.md — the invariants + the tests that guard them
- `pm-inbox-contract.md` — inbox source invariants + tests
- `pm-board-templates-contract.md` — board template save/deploy/gallery/editor invariants
- `pm-calendar-overlay-contract.md` — calendar overlay invariants
- `pm-session-link-contract.md` — session linking invariants
- [INDEX.md](INDEX.md)
- [Integration standards](../plans/integration-standards.md)

