Pipelines & Deals
Kanban Board

Kanban Board

The Kanban board is the primary visual interface for managing deals within a pipeline. It displays deal cards organized into stage columns, with drag-and-drop support for moving deals between stages.

Board Layout

The board is accessed at /deals/[pipelineId] and displays:

  • Header — Pipeline name (with a breadcrumb link back to "All Pipelines"), a Manage button (Admin+), and a New Deal button.
  • Stage Columns — One column per stage, ordered by order_index. Each column header shows the stage name and the total value of deals in that column.

Responsive Behavior

ViewportBehavior
DesktopHorizontal column layout with horizontal scrolling. Minimum width scales with the number of stages (stages × 300px).
MobileVertical stack. Each stage is a full-width section. Drag-and-drop is replaced by a Move to Stage dialog (tap the ⋮ kebab menu).

Deal Cards

Each deal is displayed as a card within its stage column showing:

  • Title (clickable link to the deal detail page)
  • Value (formatted as currency)
  • Contact name
  • Company name (if linked)

Kebab Menu (⋮)

Each card has a kebab menu with:

ActionDescriptionRestriction
View DetailsNavigate to the deal detail pageAll roles
EditOpen the edit deal dialogAll roles
Move to StageOpen a dialog to select a different stage (mobile alternative to drag)All roles
Mark as WonSet status to won, remove from boardAll roles
Mark as LostSet status to lost, remove from boardAll roles
DeleteDelete the deal after confirmationAdmin+

Drag-and-Drop

The board uses the @dnd-kit library for desktop drag-and-drop:

How It Works

  1. Drag Start — Picks up a deal card, showing a drag overlay with the deal title and value.
  2. Drag Over — Highlights the target stage column using closest-corner collision detection.
  3. Drop — Moves the deal to the new stage.

Optimistic Updates

When a deal is dropped on a new stage:

  1. The UI immediately updates the card's position (optimistic update).
  2. The moveDealToStage server action is called in the background.
  3. If the server action fails, the card reverts to its original position and an error toast is shown.

This pattern ensures the board feels responsive even on slower connections.

Activation Constraint

A minimum drag distance of 8 pixels is required before a drag starts. This prevents accidental drags when the user intends to click the card or open the kebab menu.


Hydration Safety

Since @dnd-kit uses browser-only APIs, the Kanban board uses a client-side mount guard to prevent Next.js hydration mismatch errors:

1. Component mounts → isMounted = false → renders skeleton columns
2. useEffect fires  → isMounted = true  → renders DndContext with full board

This ensures server-rendered HTML matches the initial client render before the drag-and-drop context is mounted.


Terminal States

When a deal is marked as Won or Lost (via the kebab menu or the detail page), it is removed from the active board. The Kanban board only displays deals with status: "open".

Won and lost deals remain accessible from:

  • The All Deals table on the pipeline landing page (filtered by status).
  • The Deals tab on Contact and Company detail pages.
  • The deal detail page directly (via URL or search).

This design keeps the active board focused on actionable deals while preserving historical data.