# Blocks reference

The six block types with the minimal JSON for each, every optional field, and what the templates do with them.

A block is an object with a `type` and the fields of that type. Over the agent endpoints `id`, `order` and `visible` are optional: the server assigns an id, orders blocks as sent, and shows them. Send them only when you read a page back and want to edit it in place.

| Common field | Type | Notes |
| --- | --- | --- |
| `id` | string ≤ 40 | Assigned by the server when absent. Keep it stable when editing. |
| `order` | integer | Position; absent means "as sent". |
| `visible` | boolean | A hidden block keeps its data but is not rendered. Default true. |
| `showFrom`, `showUntil` | ISO datetime or `null` | A window outside which the block is not rendered — a launch, a sale. |

## `link` — a button or card

```json
{ "type": "link", "label": "New album", "url": "https://…" }
{ "type": "link", "label": "Call the studio", "url": "tel:+380501234567" }
{ "type": "link", "label": "Write to me", "url": "mailto:hello@example.com" }
```

| Field | Type | Notes |
| --- | --- | --- |
| `label` | string 1–120 | What the visitor reads. Say what is behind the link, not "click here". |
| `url` | http(s) URL, `tel:+…` or `mailto:…` | The destination. A bare hostname (`example.com/shop`) is accepted and stored with `https://`. A phone number is stored in E.164 (`tel:+380501234567`; spaces and brackets are stripped) and dials on tap; an e-mail opens a new message. Neither gets UTM parameters. |
| `note` | string ≤ 160 | A second line under the label. |
| `image` | storage key | Card image, kind `card`. Templates with cards show it large. |
| `imageFocus` | `{ x, y }` percent or `null` | Where the card crop is anchored. |
| `badge` | string ≤ 20 | A small tag on the button: "New", "−20%". |
| `featured` | boolean | Rendered larger / first-class in most templates. |
| `pulse` | boolean | A pulsing accent ring around the button. Absent means on for a featured link and off otherwise; set `false` to silence a featured one, `true` to light up any link. At most one or two per page. |
| `adult` | boolean | Routes through the age gate; destination never appears in the page. See [Adult links](https://tapmy.link/documentation/agents/adult-links.md). |
| `path` | string ≤ 40 | A short link on the owner's subdomain: `name.tapmy.link/shop`. Unique per page. See [Short links](https://tapmy.link/documentation/agents/short-links.md). |
| `apps.ios`, `apps.android` | http(s) URLs | Per-platform destinations: iPhone goes to `ios`, Android to `android`, everything else to `url`. |

## `socialRow` — one strip of brand marks

```json
{ "type": "socialRow", "items": [
  { "platform": "instagram", "url": "https://instagram.com/name" },
  { "platform": "youtube", "url": "https://youtube.com/@name" }
] }
```

Up to twenty items. `platform` is an id from [Social platforms](https://tapmy.link/documentation/agents/platforms.md). This is the right block for "all my socials": one row, real logos, small.

## `social` — one platform as a full row

```json
{ "type": "social", "platform": "spotify", "url": "https://open.spotify.com/artist/…", "counter": "12k" }
```

A full-width row with the platform's mark and name, and an optional `counter` text ("12k followers"). Use it for the one or two platforms that matter; use `socialRow` for the rest.

## `messenger` — a one-tap chat button

```json
{ "type": "messenger", "platform": "whatsapp", "handle": "+351912345678", "label": "Ask a question" }
```

`platform` is `telegram`, `whatsapp` or `viber`. `handle` is a username for Telegram, a phone number in international format for WhatsApp and Viber. `label` ≤ 80 is optional.

## `embed` — a player

```json
{ "type": "embed", "provider": "youtube", "url": "https://www.youtube.com/watch?v=…", "title": "Live at Roundhouse" }
```

`provider` is `youtube`, `spotify`, `soundcloud`, `applemusic` or `tiktok`. Embeds open in a new tab on tap — inside in-app browsers audio is unreliable, and a link into the app the visitor already has works better than a widget. Prefer a plain `link` for audio; use `embed` for video.

## `text` — a heading or a paragraph

```json
{ "type": "text", "variant": "heading", "content": "This week" }
```

`variant` is `heading` or `paragraph` (default). ≤ 600 characters. Headings split a long page into groups; paragraphs are for one sentence of context, not for a biography.

## A good order

1. The one thing the person wants visitors to do this month, as a `featured` link, with an image if there is one.
2. Two to five plain links, most important first.
3. One `socialRow` with every platform, instead of a link per platform.
4. A `messenger` button if the person takes enquiries by chat.
5. Anything seasonal with `showFrom`/`showUntil`, so it removes itself.

> Eighty blocks is the ceiling, not a target. Pages that convert have five to twelve.

---
Part of the [Tapmy.link agent documentation](https://tapmy.link/documentation/agents.md). Canonical: https://tapmy.link/documentation/agents/blocks.md
