# Feedback board

> A public page where your users vote on ideas and suggest new ones, with suggestions held until you approve them.

A public page for your project at `https://launch.nordva.dev/board/<your-slug>`: people vote on ideas, suggest new ones, and see what is planned, in progress and shipped. It is off until you switch it on.

## Switch it on

In the dashboard → **Board**, tick **Public board**. The page's address shows under it. Untick **Visitors can suggest ideas** for a board where only you add ideas. Over the API it is `PATCH /v1/board/settings` with `{ "enabled": true }` (an AI agent uses `update_board_settings`).

## On your own site

The same board can sit inside your own pages, in your colours. Switch it on as above, then add the tag where it should appear:

```html
<div id="ideas"></div>
<script
  src="https://cdn.nordva.dev/v1/board.js"
  data-key="nv_pub_live_YOUR_KEY"
  data-target="#ideas"
  async
></script>
```

| Attribute | Default | What it does |
|---|---|---|
| `data-key` | required | Your publishable key (`nv_pub_live_...`). Never the secret key. |
| `data-target` | none | A CSS selector; the board goes inside that element. Without it, it goes right after the tag. |
| `data-user-id`, `data-user-hash` | none | The signed-in user and the HMAC of their id, [made on your server](/guides/notifications-identity/) like the bell's. They then vote as themselves, on any device, and the browser keeps nothing. Give both or neither. |
| `data-accent` | `#4f46e5` | A colour for the buttons and votes. |
| `data-theme` | `light` | `light`, `dark`, or `auto` to follow the visitor's system. |
| `data-title` | the board's title | The heading. |
| `data-suggest` | shown | `false` hides **Suggest an idea**, even when the board takes suggestions. |
| `data-suggest-label`, `data-thanks`, `data-empty` | | Your own words for the button, the thank-you and the empty list. |

Without a signed-in user, a vote carries a random id the widget keeps in the visitor's local storage (`nordva_board_client`), written only when they first vote. `window.NordvaBoard.refresh()` reloads it and `destroy()` removes it.

It follows the same rules as the other widgets: it renders in its own shadow root, sets text only as text, and styles itself without inline styles, so it works under a strict [Content Security Policy](/guides/content-security-policy/) that allows `https://cdn.nordva.dev` and `https://api.nordva.dev`.

### In an iframe

Or frame the hosted page, without our header and footer:

```html
<iframe src="https://launch.nordva.dev/board/<your-slug>?embed=1" title="Ideas" width="100%" height="700"></iframe>
```

Add `&theme=dark` for a dark page. The page tells its parent its height in a `nordva:board-height` message, so the frame can fit it:

```js
window.addEventListener("message", (e) => {
  if (e.origin === "https://launch.nordva.dev" && e.data?.type === "nordva:board-height") {
    document.querySelector("iframe[title=Ideas]").height = e.data.height;
  }
});
```

## Ideas and their status

| Status | On the page |
|---|---|
| `pending` | No. A suggestion from the page waits here for you. |
| `open` | Yes |
| `planned` | Yes, under **Planned** |
| `in_progress` | Yes, under **In progress** |
| `shipped` | Yes, under **Shipped**, with a link to its changelog entry when you pick one |
| `declined` | No |

A suggestion shows only after you approve it: **Approve** in the dashboard sets it to `open`, **Decline** hides it. Setting any shown status through `PATCH /v1/board/posts/<id>` approves it too.

Add ideas yourself on the Board page or with `POST /v1/board/posts`. From the feedback inbox, **Add to board** makes an idea from a feedback item: its summary becomes the title and its text the body (`{ "feedback_id": "fb_…" }` over the API). The person's email is never shown.

## Votes

Each idea shows its votes and the page sorts by them. A vote is one per idea per browser: the page keeps a random id in the visitor's local storage (`nordva_board_voter`) and sends it with each vote, and a second click takes the vote back. Nothing else about the voter is stored. Votes and suggestions are limited per visitor per hour.

## Suggestions

A visitor writes the idea, optional details, and optionally an email. Suggestions are limited per visitor per hour, and the widget's form has a field people never see; anything a bot types into it is dropped. The email is shown only to you, on the suggestion in the dashboard, so you can ask them about it. Suggestions wait for approval; with 200 waiting, the page stops taking new ones until you handle some.

## From your code or an AI agent

| Endpoint | MCP tool |
|---|---|
| `GET` / `PATCH /v1/board/settings` | `get_board_settings`, `update_board_settings` |
| `GET /v1/board/posts?status=pending` | `list_board_posts` |
| `POST /v1/board/posts` | `create_board_post` |
| `PATCH /v1/board/posts/<id>` | `update_board_post` |
| `DELETE /v1/board/posts/<id>` | `delete_board_post` |

All take a secret key. The hosted page reads `GET https://api.nordva.dev/public/board/<slug>`, and the widget calls `/v1/board/widget` with your publishable key; both answer only when the board is on and never show a waiting suggestion or anyone's email.

Source: https://docs.nordva.dev/guides/feedback-board/
