NodeBB
Node.js based forum software built for the modern web
Alternative to: discourse, vanilla forums, circle
v4.14.0
2026-07-09Release build (minor) of NodeBB @ 2026-07-09T12:41:51.241Z
v4.14.0 (2026-07-09)
New Features
- categories: add first-run modal for new installations (19e25f20)
- admin: add localhost and URL mismatch warnings to dashboard notices (644034d4)
- add missing view-original key (66c0bc18)
- add reject all on registration queue (39f1115e)
- add confidence to title (cba42c4d)
- activitypub:
- extend prune cutoff for followed remote categories (57e65d08)
- make public key fetch rate limit configurable (471b827f)
- posts: block re-queuing of rejected crossposts (b9473b9d)
- acp/tokens: add link to write API docs (ed83e80f)
Bug Fixes
-
throw in Mocks._normalize when
attributedTois not a URI. This normalization step is only run against incoming activities, so attributedTo should always be a URI (dc45bd7f) -
dont allow loading group list via api/v3 (3760c1e4)
-
match topicsAPI.get and topic controller (c8072500)
-
check topics:read privilege when loading post diffs (84679459)
-
timeout method (a61e0c15)
-
closes #14432, dont show mobile nav on chat page (1633b476)
-
closes #14431, use lock when awarding rewards (80aeb631)
-
relax overly-strict utils.isPEM logic (9095e0ab)
-
skip signature verification for GET /actor (0e7fc1ab)
-
borked translation string in ap relays acp page (92cb52f5)
-
no-op on AP delete(object) that references an already-deleted message (90461e00)
-
undo(like) targetting unknown pid no longer errors, is just ignored now (45997038)
-
remove typo $ (2d58bccb)
-
closes #14405, apply same checks to getRaw (da444dc5)
-
closes #14429, dont load thumbs if privateUpload is on (c45dc245)
-
silently return if ap Follow received targeting an object that is not a local user or category (1bae7ed6)
-
return number for config.activitypub.probe (40297359)
-
title generation error when empty postdata content was passed in to generateTitle (4a0e4ffd)
-
unintentional origin mismatch error thrown when user deletes their own post and the community announces it (d19d0972)
-
report config.activitypub.probe as false if guest (server-side restriction already in place) (3b69c7d9)
-
url of hstspreload (45abe492)
-
closes #14425, allow turning off strictTransportSecurity (4b045b5a)
-
update dislike handler to use same logic as like handler (f9b687ad)
-
move the rendering of post-queue-body to notification.tpl (8d61107a)
-
post-queue notification body (c7d0939d)
-
deletions must be made by an actor of the same origin (18b4d6c5)
-
show recipient in ap errors page (66856467)
-
show intended recipient in ap errors page if available (9ef5e8ba)
-
set topic_count on recent/popular/topic/unread so topic tools is visible (ed642b96)
-
pass unmodified request body into receiptError (and inbox._reject) (28d9f91a)
-
clear stuck loading indicator on bfcache restore (#14419) (7862653c)
-
btn-close color on skins (bc79f862)
-
translate topic/post tools plugin entries (cffdf5b8)
-
notif dropdown staying open after successive opens (2e5d640d)
-
create tooltips on registration queue (db2e1d34)
-
descriptionParsed (189ee51e)
-
path to registration-queue and move client side js to front end (360c301c)
-
closes #14405, check category disabled flag (7ea5e93d)
-
let administrators bypass post length limits in quick reply (#14399) (909a6b36)
-
let users who can approve requests join private groups directly (#14398) (2be954fa)
-
show confirm dialog when plugin suggest returns null version (#14390) (db172637)
-
chat page browser title (77075c22)
-
closes #10501 (2d3d8830)
-
parseInt on actor follower cache deletion (12dab1e4)
-
tx.escape user.displayname when merging notifs (420b8238)
-
modals need benchpress.render (fa77f1ee)
-
translate chat room notif options (9658d253)
-
use helpers.escape when creating markup (4dcfd152)
-
#14379 (a2bc7b69)
-
typo in post-queue.tpl (49db31e6)
-
margin (e91ec695)
-
invite table (b21207e3)
-
registration table alignment (16d4de8a)
-
align invitations (d1f27173)
-
tag notifications (a35bb311)
-
txescape chat message parent and post parent (69f47f6c)
-
notification email for post queue (c4a38e75)
-
add missing tx string (cb3b935e)
-
register (a9e94a8e)
-
login and chat message scrollbar (d3e759bb)
-
category label and breadcrumbs (065ea0fb)
-
topic titles getting double escaped (da0f5c7e)
-
title on /world page (0ec8c68d)
-
notification email escaping and tx (fb9e6629)
-
acp page titles (cd15bd88)
-
add application/vnd.rar to mime mapping (6efa0963)
-
regex (366a4a6d)
-
activitypub:
- handle duplicate votes in like and dislike (f875e918)
- return early instead of throwing on invalid pid (25fd6799)
- catch no-user error in prune and add to missing set (4119b2dc)
- validate response body is JSON object in activitypub.get (97e1c6b6)
- handle resolveObjects failures in like and flag handlers (e4d0e74b)
- remove mutex lock from fetchPublicKey rate limiter and raise default to 256 (7f11768b)
- #14385, skip outbound update for scheduled topic edits (61758eab)
- guard against falsy cid in announce followers (3face39f)
- resolve toMid from remote message URIs in assertPrivate (4ed6d845)
- remove dead maxBodyLength option from actor fetch (0ce7e515)
- make parent traversal depth configurable and add tests (73e3544c)
-
chat: wire copy link/text handlers in minimized chat window (#14387) (0e231015)
-
uploads:
- handle application/octet-stream as reported by browsers (c383e8b3)
- normalize cross-platform MIME type aliases before validation (385b32af)
- replace extension-based MIME validation with content sniffing (66800601)
-
acp/tokens: openapi schema (e9ac7b51)
-
topics:
- add source category privilege check to crossposts and fix system uid (7e6e9b94)
- move queued post update before topic delete in merge (5847fb8d)
-
world: unescape category name in selectedCategory (929f624a)
-
auth: use dummy lockout key for non-existent users to prevent username enumeration (e65c23a3)
Refactors
- use desctructoring (b799d51d)
- split registration-queue message (7564afc5)
- refresh page after rejecting all registrations (09f96a96)
- only remove thumbs that are local uploads (cc0947c0)
- add noindex to remote topics and user profile pages (2518e718)
- remove parens (85146069)
- use als storage to get current user lang (66bc43ea)
- use tx helper (eaaefdde)
- use tx, dont parse description if cid == -1 (d4779f91)
- use modals module (e77e6714)
- move registration-queue out of ACP (42c51791)
- get rid of promiseParallel (eceb530c)
- use email used during registration (3882642d)
- dont throw errors for editTitle/editContent (e0c08a1c)
- add fallback to languages.getFull (6007af7a)
- when accepting/rejecting user register (8dc71a86)
- use double {{}} on tx (29dffc6c)
- if key is fasly use empty string (1cc93c56)
- split registration queue and invitations into tabs (625557d5)
- remove renderTitle/renderContent (4f4a97a9)
- move search, filters and results to core (8b00bf2c)
- move digest.tpl duplicated topics to partial (893796a3)
- failOnError deprecated (455c847b)
- use json2csv (c2e85bd6)
- activitypub: add action:userRemote.create/delete hooks and static:users.search short-circuit (0f983531)
- acp/tokens: move token management page out from under and into , this makes it administrator only (3feae91e)
- posts: remove superfluous removeFromQueueByTid method (e3fa2fb1)
Tests
- add some timeout to reward test to wait for action hooks to finish (7f6ed9ae)
- fix tests since helper translates now (28fa37ed)
- move config (ef42fadb)
- fix registration-queue lang config (6be0edd7)
- fix urls to registration-queue (991a5967)
- remove old route test (aefb7a22)
- add a test for single quotes (2fba9138)
- activitypub: ensure that when an Announce comes in after a note is asserted, it gets categorized properly (92f3b2bd)