> ## Documentation Index
> Fetch the complete documentation index at: https://okl-ink.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Bento Grid & Canvas Builder

> How okl.ink uses bento grid geometry, drag-and-drop mechanics, and automatic layout filling.

# Bento Grid & Canvas Builder

okl.ink replaces traditional vertical lists with an interactive **Bento Grid**. The canvas allows you to craft visually compelling layouts that adapt seamlessly across devices.

***

## Tile Sizes & Dimensions

Every tile in the bento grid is allocated a discrete span across a 4-column desktop grid:

<CardGroup cols={2}>
  <Card title="1x1 (Compact Square)" icon="square">
    **Column Span**: 1 · **Row Span**: 1

    Ideal for secondary social links, quick action icons, and badge links.
  </Card>

  <Card title="2x1 (Standard Horizontal)" icon="rectangle">
    **Column Span**: 2 · **Row Span**: 1

    The standard link card format. Displays the icon, custom title, destination domain, and optional right chevron.
  </Card>

  <Card title="2x2 (Rich Preview / Embed)" icon="table-cells">
    **Column Span**: 2 · **Row Span**: 2

    Recommended for media embeds (YouTube videos, X/Twitter posts, LinkedIn embeds) or links with custom image thumbnails.
  </Card>

  <Card title="4x1 (Full Width Banner)" icon="rectangle-wide">
    **Column Span**: 4 · **Row Span**: 1

    Spans the entire width of the grid. Great for hero links, primary product announcements, or main documentation buttons.
  </Card>
</CardGroup>

***

## Grid Layout Engine & Math

The layout engine in `src/lib/grid-filler.ts` and `src/lib/link-layout.ts` computes the exact CSS grid placement and dynamically resolves spacing.

### Responsive Breakpoints

| Viewport                      | Column Count   | Behavior                                                        |
| :---------------------------- | :------------- | :-------------------------------------------------------------- |
| **Desktop** (`>= 1024px`)     | 4 Columns      | Full bento grid geometry using specified span sizes             |
| **Tablet** (`768px - 1023px`) | 2 Columns      | `4x1` spans 2 columns; `2x1` and `2x2` adapt smoothly           |
| **Mobile** (`< 768px`)        | 1 or 2 Columns | Adaptive layout mode switching or uniform stacked touch targets |

### Gap Sizing by Density

The pixel gap between bento tiles is calculated based on the project's **Density** preset:

```typescript theme={null}
export function densityGapPx(density: DensityPreset): number {
  if (density === "compact") return 8;   // 0.5rem
  if (density === "airy") return 16;     // 1.0rem
  return 10;                             // 0.625rem (comfortable)
}
```

***

## Drag-and-Drop Workflow (`@dnd-kit`)

In the live canvas editor (`src/components/project/link-builder-canvas.tsx`), tiles use `@dnd-kit/core` and `@dnd-kit/sortable` for fluid reordering.

```mermaid theme={null}
sequenceDiagram
    autonumber
    actor User as Creator
    participant UI as DndContext (Canvas)
    participant Action as reorderLinks (Server Action)
    participant DB as Prisma / PostgreSQL

    User->>UI: Drags tile from Pos 0 to Pos 3
    UI->>UI: Optimistically updates UI tile positions
    UI->>Action: Calls reorderLinks(projectId, [id1, id2, id3, id0])
    Action->>DB: Executes prisma.$transaction(batch update positions)
    Action->>UI: Revalidates cache tags for /[slug] and /projects/[id]/edit
```

***

## Device Preview Switcher

The top toolbar in the editor includes a responsive device toggle:

* **Mobile Viewport**: Simulates an iPhone / Android screen width (375px)
* **Tablet Viewport**: Simulates an iPad / tablet width (768px)
* **Desktop Viewport**: Displays the full fluid 4-column bento canvas (1024px+)

This allows creators to verify how their links and social embeds look across all devices without leaving the workspace.
