# Emoji Reactions

> Emoji reaction buttons for your posts. One reaction per reader, optional counts, no cookies and no raw IPs stored.

Source: https://emdashcmseverything.com/plugins/emoji-reactions/

- Category: reactions
- Status: available
- Version: 0.2.1
- Price: Unknown
- Compatibility: Not stated in the public registry profile
- License: MIT
- Maintainer: toya
- Download: https://plugins.emdashcms.com/plugins/@toya-mimura.bsky.social/reactions
- Repository: https://github.com/toya-mimura/emdash-plugin-emoji-reactions
- Published: 2026-10-21

## Description

Reactions adds emoji reaction buttons (💗 🤔 😗 by default) to your posts.
Each reader picks **one reaction per post**: clicking it again removes it, clicking another one switches.

### Features

- Up to **6 buttons**, configured from the admin page (`key=emoji:label`).
- Optional labels next to each emoji, and optional public counts.
- An admin page that lists your **10 most-reacted posts**.
- The admin page follows the admin locale (English or Japanese).
- **No extra database**: data lives in the plugin's own EmDash storage.
- **No capabilities and no network access** requested.

### Privacy

- Readers are recognised by a SHA-256 hash of their IP address and User-Agent with a random per-site salt. The IP and User-Agent themselves are **never stored**.
- Stored per vote: post ID, the hash, the chosen reaction and a timestamp. **No cookies.**

> **Note:** the plugin does not render anything on its own. After installing it, add the `Reactions.astro` component to your post template (see *Installation*).

### Requirements

- EmDash 1.x on Cloudflare (D1)
- Workers Paid plan (sandboxed plugins run in the Worker Loader binding)

## Installation

### 1. Install the plugin

Install Reactions from this page with **Open in EmDash**, or build it from source:

```sh
pnpm install
pnpm run build   # dist/
```

When building from source, add the package to your site (`pnpm add file:../emdash-plugin-emoji-reactions`) and list it in `astro.config.mjs` under `sandboxed: [reactions]`.

### 2. Enable the plugin sandbox

Sandboxed plugins need the Worker Loader binding. In `wrangler.jsonc` (commented out in the templates):

```jsonc
"worker_loaders": []
```

Make sure `src/worker.ts` exports `PluginBridge` (the `*-cloudflare` templates already do), and that `astro.config.mjs` sets `sandboxRunner: sandbox()`.

### 3. Add the buttons to your post template (required)

Copy [`site-snippets/Reactions.astro`](https://github.com/toya-mimura/emdash-plugin-emoji-reactions/tree/main/site-snippets) into `src/components/` and place it on your post page:

```astro
---
import Reactions from "../../components/Reactions.astro";
// `post` comes from getEmDashEntry()
---

```

Use `post.data.id` (the database ID), **not** `post.id` (the slug). Slugs change when a post is renamed, and translated slugs contain `/`, which the plugin rejects.

Props: `contentId` (required), `heading` (empty string hides it), `label` (accessible name of the button group). Set `--rx-accent` in your CSS to match your accent colour.

### 4. Choose your buttons

Open **Reactions** in the admin sidebar and edit the field, e.g.:

```
love=💗:Love, hmm=🤔:Hmm, whistle=😗:Whoa
```

Up to 6 entries. Keys start with a lowercase letter. Counts are stored per key: renaming a key starts a new button; removing one hides it but keeps its counts.

## FAQ

### The buttons don't appear on my site

1. Check that `Reactions.astro` is added to your post template. The plugin itself renders nothing.
2. Open the browser console. Failures are logged as `[reactions] state: HTTP 403 CSRF_REJECTED ...`.
3. If you copied `dist/` into your site instead of installing the package, check that `dist/index.mjs` contains `"routes"`. Without it, EmDash treats the public routes as private and rejects requests.

### Can I hide the counts?

Yes. Turn off **Show counts** in the admin page. Counts are then also left out of the public API, so they can't be read from the page. They keep being counted and stay visible to you in the admin page.

### Two people in my home/office count as one reader

Readers behind the same IP using the same browser are treated as one. This is a casual reaction button, not a voting system.

### Can people spam the button?

Each reader has one reaction per post, so repeated clicks only toggle it. The routes are public, though. If needed, add a Cloudflare Rate Limiting rule for `/_emdash/api/plugins/reactions/react`.

### Does it work in local development?

Yes. When no client IP is available, the browser sends a random ID kept in `localStorage` (`rx-visitor`) instead.

## Security

### Reporting a vulnerability

Please report security issues privately through
[GitHub private vulnerability reporting](https://github.com/toya-mimura/emdash-plugin-emoji-reactions/security/advisories/new),
not in public issues.

### What the plugin can access

- **No capabilities and no network access.** The plugin can't read or change your content, media, users or settings outside its own storage, and it can't call other services.
- It stores data only in its own EmDash storage: per-post counts, one record per vote, and its button settings.

### Data stored about readers

- A truncated SHA-256 hash of the reader's IP address and User-Agent, combined with a random per-site salt. The IP address and User-Agent themselves are never stored.
- Per vote: post ID, that hash, the chosen reaction and a timestamp. No cookies.

### Public routes

`state` (GET) and `react` (POST) are public. Both validate their input: `contentId` must match `[A-Za-z0-9_\-:.]`, reactions must be a configured key, and request bodies are capped at 1 KB. The admin route is private. To limit abuse, add a Cloudflare Rate Limiting rule for `/_emdash/api/plugins/reactions/react`.

## Changelog

### 0.2.1 — 2026-10-18

- Added the registry icon.

### 0.2.0 — 2026-10-15

First release on the EmDash plugin registry.

- **Show labels** and **Show counts** switches in the admin page. Labels are hidden by default and kept as tooltips and screen-reader text. With counts hidden, the public API leaves them out too.
- Requires EmDash 1.x. Button settings move to `ctx.settings`; buttons saved in 0.1.x carry over.
- The admin page follows the admin locale (English or Japanese). Default labels are now English (`Love` / `Hmm` / `Whoa`); keys are unchanged, so existing counts stay attached.
- `Reactions.astro`: logs failures to the browser console instead of hiding silently, adds a `label` prop and the `--rx-accent` CSS variable, and documents passing `post.data.id`.
- `pnpm run test` now ends with a build, so `dist/` always includes the public route declarations.

### 0.1.0

- Initial version (not published to the registry).
