Surfaces
WordPress plugin v0.30.0
The flagship surface and the most complete implementation of Red Pen. A logged-in Dev Mode overlay on the site front end, plus a full notes repository in wp-admin - all from a single self-contained plugin file.
What it is
Reviewing a WordPress site usually means a messy spreadsheet, a thread of "the about page has a typo", or comments scattered across email. Red Pen puts the note where you found the problem - on the page itself - and collects every note in one place your whole team can see. It is good for editorial review, client hand-offs, content audits, QA passes, and shared to-do lists.
The plugin has two halves that share one data store:
- The front-end overlay - a floating button (bottom right) shown only to logged-in users who can edit posts. This is where you leave, pin, and reply to notes while looking at the live page.
- The repository - an admin screen under Tools in wp-admin listing every note across the whole site, with filters and one-click status changes. There is also a per-post meta box on each edit screen showing that page's notes.
Install and activate
- Copy the
wp-red-penfolder towp-content/plugins/(or upload the zip via Plugins -> Add New -> Upload). - Activate it. There is no build step and no settings you must configure to start - it is a single self-contained
wp-red-pen.phpwith inline CSS and JS. - Click Red Pen: Off in the admin bar to turn Dev Mode on for your account.
- Open any post or page on the front end and use the floating button.
- Review everything under the Red Pen repository in wp-admin (under Tools).
wp-content/plugins/ (and activates it with WP-CLI) keeps every local site on the same version.
Dev Mode
Red Pen is invisible until a logged-in user with the edit_posts capability (editors and admins) turns on Dev Mode from the admin-bar toggle. Dev Mode is per user - flipping it on affects only your account, so a client and a developer logged into the same site can have it on or off independently.
- The admin-bar item reads Red Pen: On / Red Pen: Off and carries an open-note count badge, mirrored on the floating button, so you always see how many notes are still open.
- Logged-out visitors never receive the Red Pen assets at all - the capability check happens before any CSS or JS is enqueued. There is no way for an end user to see or trigger the overlay.
- A global "Where Red Pen appears" setting controls which views show the button - singular posts and pages, archives, taxonomy pages, the home/front page, search, and 404. It defaults to everywhere. Since v0.29.0 only administrators see and change it, because it applies to the whole site.
Leaving a note
With Dev Mode on, the floating button opens the note panel. From there you can:
- Type a note with a type - note, idea, problem, or question - plus a priority of Low, Normal, or High. Custom note types with their own colour flag are supported too.
- Set a severity (optional) - under More, next to Priority, tag the note's impact as Blocker, Critical, Major, Minor, or Trivial. Severity is the impact axis where priority is the scheduling one (see Severities); it is left unset by default, dev-only (client reviewers never see it), and shows on the note, in the CSV export, and on the Hub board.
- Pin to an element - the "Pin to element" picker lets you click any element on the page to anchor the note to it. Anchored notes appear as numbered markers on the page; clicking a marker opens its note, and the note can jump you back to the element. A pin is labelled by the element's own visible text (falling back to its alt / aria-label / title, then a plain-language name for the tag), and editing a note re-resolves the saved selector, so a pin whose target has gone reads as gone. On a phone the page still scrolls normally in pin mode - a deliberate tap pins, a drag scrolls - and a visible Cancel control stands in for the Esc key.
- Choose who sees it - Visible to client reviewers, off by default. Notes are internal unless you tick it; see Client review links below.
- Snip a screenshot - click Screenshot, drag a box around the area, and the region is captured client-side (via vendored html2canvas) and stored as a small WebP in
uploads/wp-red-pen/, attached to the note. - Set the reporting level - target This page (the exact post or archive you are on) or This template (the view type, so the note covers every page rendered the same way). A page shows its own notes plus the template notes that apply to it.
Every note also records auto-context - the browser, OS, and viewport it was created in - so a layout bug carries the environment it happened in.
Editing a note
Any note can be edited after it is added - change the text, type, priority, or assignee; swap, remove, or add a screenshot; and re-pin, move, or clear the attached element. The front-end panel has full editing.
Statuses, priorities, and replies
Every note carries a status, a priority, and its own reply thread.
- Three-state workflow - every note is Open, In progress, or Resolved. Resolve and reopen are one click; In progress sits between the two for work that is underway.
- Priority - Low, Normal, or High, surfaced as a column and a filter in the repository.
- Threaded replies - reply to any note from the panel to build a discussion under it. Replies are stored as child notes of the parent.
Assignee and agent
WordPress is the surface where assignment is fully implemented today. A note carries two distinct, complementary fields:
- Assignee - a WordPress user the note is assigned to (a real person). The repository adds an Assigned column and an "Assigned to me" filter. This is the manual-work lane.
- Agent - an AI agent slug (for example a coding agent's handle). An empty agent means a human note; a set agent marks the note as automated work, and the REST API can return just the notes targeted at a given agent. This is the automated-work lane.
The repository
The shared repository admin page lists every note across the site. You can filter by Open / In progress / Resolved / All, by priority, and by assignee ("Assigned to me"), and resolve or reopen any note with one click. A CSV export dumps the current view (honouring the active filters) for handing off or archiving - generated locally, with no external service, and carrying a Client visible column. Each post's edit screen also carries a meta box listing that page's notes inline.
Client review links v0.13.0, free
The reason this surface exists for client work: you can let a non-technical client leave pinned notes on a site without a WordPress login. From the "Client review links" panel (under Tools, alongside the Hub settings) you generate a labelled, shareable link. Send it privately to your client; they open it, click the red button, and leave typed notes and replies pinned to the page - the same overlay you use, in a restricted "reviewer mode". This is free core, never gated. Since v0.26.0 the link is a one-way door by default: it collects your client's feedback and shows them their own reports, and it shows them nothing of yours unless you deliberately share it.
What a reviewer can and cannot do
Reviewer mode is a deliberately narrow door. A link holder can open the overlay, pin notes to elements, leave typed notes (type and priority), and reply. Since v0.27.0 they can also edit or delete their own notes while those are still Open; a note locks for them once you move it to In progress or Resolved, and a deleted note goes to the Trash. A link holder cannot resolve, reopen, or assign notes, cannot edit or delete anyone else's, cannot open the admin repository, cannot view screenshots, and never sees the user list, the agent options, or any other reviewer link. The boundary is enforced on the server, not just hidden in the interface.
What a reviewer can see changed in v0.26.0
Two rules decide whether a note reaches a reviewer link, and both are checked on the server through one gate:
- Their own reports, at any status. A note filed through a link is visible to that link whatever state it has reached, with the date it was marked fixed. Before 0.26.0 reviewer reads were pinned to open notes, so a client's Resolved tab could never fill and a fixed report looked identical to one that never saved. A note also records which link filed it, so one client's link cannot surface another client's history.
- Your notes, only when you share them. Everything else is internal by default and reaches a reviewer only when its author ticks Visible to client reviewers on the note - and then only while it is open. The check fails closed: no flag means internal, so every note that predates 0.26.0 is invisible to a reviewer link until it is shared deliberately.
The checkbox sits on the note form in both the front-end panel and the repository edit panel, off by default. A shared note carries a badge in the front-end list, the edit-screen meta box and the repository table, and a Client visible column rides along in the CSV export - so "what has the client actually seen?" is answerable from the same screens you triage on.
What a reviewer is told changed in v0.29.0
- That the note was saved. After a client adds a note or a reply, the panel says it was saved and that the website team can see it. Before, the only sign was the note turning up in the list, which is easy to miss for someone using the panel for the first time.
- Who answered. Replies from you or anyone else logged in to the site show to the client as Website team. They used to show as "Reviewer", which read as if another client had answered. Your own name never reaches a review link. In your panel, a client's note carries the name they typed on it instead of "Unknown".
- Why a save failed. The message gives the real reason in plain words (the link has stopped working, too many notes in a few minutes, or the connection dropped) and says that what they typed is still in the box. Every failure used to say "check your connection".
- That the link has stopped working. An expired or switched-off link now tells the client so on the page, and to ask the person who sent it for a new one. It used to open the site with no panel and no explanation, which looked like a broken site.
Pages the host had cached changed in v0.30.0
The panel used to be part of the page HTML. A copy of the page stored by the host's cache or the client's browser before the link was opened had no panel in it, and a client could see the panel on one page and a bare site on the next, with nothing wrong on the server. Versions 0.26 to 0.27 asked caches not to keep those pages; some hosts' edges ignored every one of those requests. Since v0.30.0 the page carries only a small loader, identical for every visitor of a site with a live review link, and the panel is fetched over a request that browsers and edges are told not to keep. Whatever copy of the page a client is served, the panel appears on it. Nothing a visitor should not see is in the page: the loader holds the page's own context and the address to ask, and only a valid link holder gets the panel back.
Two things changed with it. The plugin no longer sends no-cache headers on every page of a site with a live review link, so review and staging sites can be cached like any other site. And a reviewer's page no longer loads the icon font in its head; it arrives with the panel.
Managing links
- Generate with a label (the client or project name) and an optional expiry (never, 7, 30, or 90 days). The full URL is shown once at creation - copy it then, because only a hash is stored and it cannot be displayed again.
- Revoke any link instantly from the active-links table. A revoked link stops working on the next request.
- Triage reviewer feedback in the repository: reviewer notes carry a red "Client" badge and the reviewer's name, and a Source filter (All / Client reviews / Dev notes) narrows the list so you can review or bulk-action client feedback on its own.
Client report v0.21.0
The deliverable you hand a client. From the Client report panel (under Tools, alongside the review links) you generate a clean, printable summary of the site's notes - Generate report (all) for everything including resolved items, or Open items only. It opens in a new tab; use the browser's Print / Save as PDF to send it. This is the "here is what you asked for, here is what is done" document, drawn straight from the notes you have been triaging.
The report groups notes by status (Open, In Progress, Resolved) with summary counts, and shows each note's type, its severity when set, the page it is on, its screenshot, and the dates it was added and resolved. It is deliberately client-facing: the agent queue and internal-only fields (assignee, agent, code scope, browser context) are left out.
Plain and branded reports
The report comes in two styles, both free. The plain report carries the tool's credit; the branded report lets you set a custom report title, your logo, an accent colour, and hide the "Generated with Red Pen" credit, so it goes out as your own deliverable rather than the tool's. You set these in the same panel. Since v0.29.0 the branding settings are shown to administrators only.
REST API
The front-end button talks to a small REST API under the wprp/v1 namespace. The same routes are what the Red Pen Hub uses for two-way write-back. Every route is gated by an edit_posts capability check. The front-end button authenticates with the standard wp_rest nonce; a server-to-server client (such as the Hub) authenticates with a WordPress Application Password over HTTP Basic auth.
| Method + route | Purpose |
|---|---|
GET /wp-json/wprp/v1/notes | List notes for a view. Accepts target, status, context keys, or an agent slug to fetch an agent's queue. Also accepts scope=all so the Hub can pull every note on the site, not just site-wide (target=0) ones. Notes carry an ISO createdAt and, once resolved, resolvedAt + resolvedBy. |
POST /wp-json/wprp/v1/notes | Create a note (body, type, priority, target, anchor, screenshot, agent, and more). |
POST /wp-json/wprp/v1/notes/{id} | Edit an existing note - text, type, priority, assignee, anchor (re-pin / clear), screenshot, and context. |
POST /wp-json/wprp/v1/notes/{id}/status | Set the status (open, progress, or resolved). The Hub's Resolve / Reopen calls this route. |
POST /wp-json/wprp/v1/notes/{id}/replies | Add a threaded reply to a note. |
Connect to Hub
To see this site's notes alongside every other project, connect it to the Red Pen Hub. Under the plugin's Display settings (administrators only since v0.29.0), fill in "Connect to Red Pen Hub" with the Hub URL and the shared connect token. The plugin then pushes its notes to the Hub whenever a note changes - the site sends to the Hub, so no Application Password or inbound access is needed.
What the push sends. A push includes every top-level note on the site - all pages and posts, not just site-wide ones - each with its full data: type, priority, severity, anchor, the ISO created and resolved timestamps, statusAt (when the status last moved), the custom type's typeLabel, the resolver, and the assignee. So the board shows the same detail no matter how the site is connected.
There is a second way to connect: instead of the site pushing, the Hub can pull from the site using a WordPress Application Password (see the REST /notes route above). A pull uses the ?scope=all parameter added in v0.19.0 to get the whole note set - before it, a pull saw only site-wide (target=0) notes and page/post-attached ones went missing. Pull connections are also how the Hub writes a resolve back into the WordPress database over REST.
http://localhost:3900, not localhost:3900. A schemeless URL is silently rejected by WordPress sanitisation, which saves the token but blanks the URL, so the push quietly no-ops. Recent versions auto-prepend http://, but include it to be safe.
Architecture and data
The plugin keeps everything in standard WordPress structures - no custom tables:
- Storage - a private
wprp_notecustom post type. The note body is the post content; author and date are native; status is a custom post status (wprp_open/wprp_progress/wprp_resolved). - Replies are child
wprp_noteposts (the parent is the note id). Priority, assignee, agent, context, and the element anchor are all post meta. - Targeting context - each note stores a context key (for example
post:12,pt_archive:composer,term:genre:5,tpl:single-track,search,404), a human label, and a level (page or template). The front end fetches by the current view's page and template keys. - Clean uninstall - deleting the plugin removes every note and preference it created, and nothing else.
Troubleshooting
- No floating button. Confirm you are logged in as an editor or admin and Dev Mode is On in the admin bar. Logged-out users never get the assets. Check the "Where Red Pen appears" setting covers the view you are on.
- Notes not reaching the Hub. Verify the Hub URL includes
http://and the connect token matches the Hub's token exactly. A bad token returns a 401; a missing scheme blanks the URL. - A screenshot did not save. Screenshots are stored under
uploads/wp-red-pen/; confirm the uploads directory is writable. - "Could not take the screenshot." The capture failed on that part of the page. Try a smaller area, or describe what you see in the note instead. Before v0.29.0 a failed capture closed without a word.
- The panel says a note could not be saved. The message gives the reason: the connection dropped, you were logged out of WordPress, the review link stopped working, or too many notes went in within a few minutes. What was typed stays in the box. A tab left open for more than a day fetches a fresh WordPress token and tries once more by itself, so an overnight tab keeps saving.
- A client sees the site with no panel on some pages. The site is on a version before v0.30.0 and those pages were cached before the link was opened. Update the plugin; since v0.30.0 the panel is fetched fresh on every page. On an older version a hard reload of the page brings it back.
- A save failed and no message appeared. The site is on a version before v0.29.0. Those versions drew the panel's messages as white text with no background, so every error was there but could not be read. Update the plugin.
- Display settings or report branding are missing. Your account is not an administrator. Since v0.29.0 those settings are for administrators only, because they change things for the whole site, the Hub connection included. Everything else in the repository works the same for editors.