Let's keep a list of NodeBB installations here :
If you are running your own NodeBB let us know we will add it to the list!
Let's keep a list of NodeBB installations here :
If you are running your own NodeBB let us know we will add it to the list!
This NodeBB plugin pulls RSS feeds and creates topics in predefined categories.
A NodeBB Plugin to post topics using RSS feeds. Contribute to barisusakli/nodebb-plugin-rss development by creating an account on GitHub.
GitHub (github.com)
To customise options for the parser, please consult the "RSS" page in the administration panel, under the "Plugins" heading.
npm install nodebb-plugin-rss
This plugin shows who is currently viewing a topic. This was a core feature that we removed a while ago, now it is back as a plugin
npm install nodebb-plugin-browsing-users
More info at https://github.com/barisusakli/nodebb-plugin-browsing-users
Notes
Currently only persona supports this, if you want to add it to your custom theme make these changes.
Just merged the group-chat branch into master, it will be available in our next release which will most likely be 1.0.0.
There are some breaking changes and schema changes in this merge.
The upgrade script will go through all the chat messages and assign them to rooms. This might take a while depending on how many chats messages there are in the system. The upgrade script should show the progress in the console.
For all the changes check out this PR https://github.com/NodeBB/NodeBB/pull/3968/files
Peace is a simple theme with a sidebar navigation, it comes with a builtin bootswatch theme switcher.
More info and source https://github.com/barisusakli/nodebb-theme-peace
While this topic has some broad ideas about new features following 3.x, this topic will be about new features and quality of life improvements coming in 3.1.0.
Without further ado let see what's new:
Topic thumbnails is a feature that allows users to upload images as part of a topic.
In persona theme it only replaced the user avatar on topic lists but with harmony it is now displayed separately in the topic list. With 3.1 you can now see the topic thumbnails inside the topic and click on them to see large versions and switch between images.
Try it on this topic https://community.nodebb.org/topic/17113/persona-a-retrospective
Our chat message edit interface needed some Previously editing a message used the same input box as sending a message and would lead to confusion, what happens if you already have text in the send input? Now it is possible to edit in place like slack and other chat apps.
Prior to 3.1.0 the only way to edit the tags of a topic was to enter the topic and then click edit on the main post. Starting in 3.1.0 it is possible to use the topic tools dropdown and modify the tags of a topic. It is also available on topic lists like the recent page so you can tag multiple topics at the same time.
Not sure why this wasn't requested before seeing how we share alot of code on this forum. With 3.1.0 you will be able to copy the contents of code blocks with a single click.
Our error pages had the same design since 2016 which used the default bootstrap alert classes.
We have updated them to look nicer, we also included some of our animal friends. See which one you get.
When forking a topic it wasn't possible to specify the category for the new topic. This would lead to problems if the category is only intended for topics from admins.
Now you don't have to move the topic after forking and just select the target category in one step.
Widgets can have start and end date and they will be visible only during that time frame.
We also fixed some issues reported by our users since 3.0.0 release. You can see those here
I have run some tests to check the memory usage.
The redis INFO command was reporting 811kb at the beginning since I was running the tests on db1. An empty NodeBB installation starts with roughly 405kb of memory usage.
start 811.44 kb
**Users **
100 users 1.04M diff (254kb) per user = 2.54kb
1000 users 3.61M diff( 2,885kb) per user = 2.885kb
10000 users 29.88M diff( 29,786kb) per user = 2.97kb
Posts (500 chars each)
336 posts 30.71M diff(849kb) per post = 2.52kb
996 posts 32.70M diff(2,887kb) per post = 2.89kb
9995 posts 54.39M diff (25,098kb) per post = 2.51kb
The memory usage per user is roughly 3kbs at 10,000 users. This value goes up as we have other structures that grow as the user count grows.
The memory usage per post is about 2.5kbs per post, keep in mind the posts I created are all 500 characters long.
So for 2,000,000 posts and 400,000 users :
2,000,000 x 2.5kb + 400,000 x 3kb = 5.9gb
So theoretically 6gb should be enough.
Hope that helps.
We recently added a new system group called Global Moderators, this group has access to the moderator tools but can't access the ACP. They can also ban users. We will let this group see banned users and flagged posts as well.
We have assigned some users as global mods on this forum as well https://community.nodebb.org/groups/global-moderators.
If you think we missed someone or you want to be a global mod ask for it here.
We have been nominated for the 20i Foss Awards in the category "Best Community & Social"
If you want to support NodeBB you can vote below. Thanks everyone!
Enter description here.
(www.20i.com)
Here is another simple widget to add a new topic button into the new brand header widget area. This allows your users to create topics from anywhere in the forum:
Go to admin/extend/widgets
and create an html widget with the below markup. Don't forget to update your category names and ids in the app.newTopic(cid)
calls.
<div class="dropdown">
<button class="btn btn-sm btn-primary" data-bs-toggle="dropdown">New Topic</button>
<ul class="dropdown-menu dropdown-menu-end p-1">
<li><a href="#" class="dropdown-item rounded-1" onclick="app.newTopic(2);">General Discussion</a></li>
<li><a href="#" class="dropdown-item rounded-1" onclick="app.newTopic(3);">NodeBB Development</a></li>
<li><a href="#" class="dropdown-item rounded-1" onclick="app.newTopic(5);">Feature Requests</a></li>
<li><a href="#" class="dropdown-item rounded-1" onclick="app.newTopic(6);">Bug Reports</a></li>
</ul>
</div>
If you want you can use the widget code from https://community.nodebb.org/topic/17095/how-to-create-a-category-selector-in-navigation to have a more complex category dropdown.
I normally don't make announcement topics for patch releases but 3.7.0 had a nasty memory leak issue due to our mongodb dependency.
We noticed increased memory usage on our community and try.nodebb.org as well as instances hosted on https://manage.nodebb.org.
After spending some time with git bisect
I narrowed it down to the mongodb dependency. Thankfully it was fixed in https://github.com/mongodb/node-mongodb-native/pull/4022.
3.7.1 has this fix and 2 more bugfixes https://github.com/NodeBB/NodeBB/issues?q=is%3Aclosed+milestone%3A3.7.1.
If you have upgraded to 3.7.0, you are highly encouraged to upgrade to 3.7.1.
Note: Latest stable is v3.3.9
Hello everyone! We have just released NodeBB 3.3.0.
There are some exciting changes in this release so please read below to learn more.
As mentioned here 3.3.0 comes with a refactored chat system that allows administrators to create public rooms. Here are some more highlights:
The chat system also performs much better with a lot of users, if you were using nodebb-plugin-global-chat you can switch to public group chats and disable that plugin.
Try it out on our chats page here.
Thanks to @oplik0's work on this you can now use fontawesome pro icons and fontawesome is now loaded as an npm dependency like most of our other dependencies.
More info in this pull request and in our docs.
Bootstrap had a minor version upgrade from 5.2.3 to 5.3.1.
For all changes please refer to bootstrap's blog
https://blog.getbootstrap.com/2023/05/30/bootstrap-5-3-0/
https://blog.getbootstrap.com/2023/07/26/bootstrap-5-3-1/
There are some big changes to color modes and addition of new colors.
The acp got redesigned in 3.2.0 and all of the hardcoded colors were replaced with bootstrap theme colors.
Since bootstrap 5.3 comes with a built in dark mode, I've added support for this in the ACP. It can be toggled with a switch on the ACP dashboard and your preference gets saved in local storage.
We have some QoL improvements as well.
Please let us know if you notice any issues in the support thread https://community.nodebb.org/topic/17488/3-3-0-upgrade-support
Let's take a stroll down memory lane and see how the chat system has evolved over the years.
The initial chat feature was built 10 years ago and used websockets to send text messages. The message history wasn't even saved in this first iteration and it was limited to 2 users.
This first version was built using popup windows. In 2014 a separate page for chats was built in https://github.com/NodeBB/NodeBB/issues/1788
In 2015 group chats were introduced allowing more than 2 users. https://community.nodebb.org/topic/7289/group-chat-changes
After this the chat page didn't see any drastic changes, the design stayed mostly the same until we released 3.0.0 with Harmony theme.
Even though we allowed group chats since 2015 the way it was built wasn't scalable to lots of users. It was meant to be used to create chats between a small number of users. Adding thousands of users to a single room would make it really slow due to how the data was stored and delivered to each user. Without going into too much detail; the previous system would naively try to deliver a new message to all users in the room even if they weren't online.
The upcoming 3.3.0 release will add support for public group chats and allow bigger rooms.
Administrators will be able to create public chat rooms and select which groups can access them. If you select registered-users
it would be accessible to everyone who registers to your forum.
Public rooms allow users to view the entire chat history unlike private rooms where you only see messages sent after you have joined.
You can test by going to https://community.nodebb.org/chats. Hopefully you won't see our admin chats
This feature is on the develop
branch for anyone wanting to test it on their dev forums.
Happy chatting
Hello everyone!
Today we are releasing NodeBB 3.5.0. Please read below for all the changes in this release.
Starting with 3.5.0 you will be able to watch individual tags. Whenever a topic is posted that has those tags you will get a notification and/or email depending on your notification settings. This is useful for watching system tags like security and release.
You can watch tags directly from the tag page or from your watched tags page.
We've revamped our emoji dialog to use category icons instead of labels and got rid of the horizontal scrollbar.
Plugins can add buttons into the chat composer via our hooks system, we've added support for this in two plugins nodebb-plugin-tenor-gif and nodebb-plugin-emoji.
A new setting that controls the delay between chat messages for regular and new users. This was hardcoded too 200 milliseconds before.
Pinned messages are now editable in the pinned message area, so you don't have to go searching for it in the message area.
Just like merged topics, forked topics will display a banner at the top showing which topic they were forked from.
Prior to 3.5.0 there was no way to see if you received an award. We added two notifications; one for being added to a group and one for receiving reputation.
As usual there are plenty of bug fixes in this release.
Full list of closed issues
Let us know if you run into any issues in our support thread
Hello Everyone !
Today we are releasing NodeBB 3.9.0. Please read below for all the changes in this release.
nodebb-widget-essentials has been updated to include a chat room widget. This widget allows you to embed a chat room in one of the widget areas. You can select the initial chat room that loads in the widget settings. It is also possible to switch chat rooms with a dropdown menu.
All the widgets in the widget-essentials plugin got a facelift to more closely match our updated design in harmony theme. You can see some old vs new comparisons below.
Some common templates like dropdowns were moved into core and persona theme was updated to use these.
nodebb-plugin-feed design and functionality has been updated to have a social media like feed. You can see all changes in the plugin topic here.
We refactored a button class (btn-ghost-sm
) that was used throughout harmony to follow the bootstrap standard of button classes (ie btn btn-primary btn-sm
). This means if you were using this class in your themes & plugins you need to change it to btn btn-ghost btn-sm
for the small variant and btn btn-ghost
for the default size.
As usual there are plenty of bug fixes in this release.
Full list of closed issues.
Let us know if you run into any issues in our support thread.
Since NodeBB 1.18.6 it is possible to create dropdowns in the navigation (https://github.com/NodeBB/NodeBB/issues/9967). Before 1.18.6 to accomplish this you would have to use nodebb-plugin-customize to modify the menu template or use javascript to inject the markup after page load.
In this tutorial I will show you how to create a dropdown navigation item that replaces the default categories link with a dropdown. The final result will look like this:
First thing to do is to turn the navigation item into a dropdown, to do this head over to yourforum.com/admin/settings/navigation
, select the categories navigation item and toggle the dropdown
option.
Once this is done you can use the text area below the toggle to add your markup. To create a simple dropdown you would just add a list of dropdown items like so:
<li><a class="dropdown-item" href="/categories">All</a></li>
<li><a class="dropdown-item" href="/category/2/general-discussion">General Discussion</a></li>
Since you can input html here you can create custom dropdowns. To achieve the same dropdown as the first gif use the below html code, no css is necessary.
<li><a class="dropdown-item" href="/categories">All</a></li>
<li class="dropdown-divider">
<li><a class="dropdown-item" href="/category/2/general-discussion">General Discussion</a></li>
<li class="d-flex flex-column">
<a class="dropdown-item" href="/category/3/nodebb-development">NodeBB Development</a>
<div class="d-flex flex-column px-4">
<div class="d-flex align-items-center gap-1">
<i class="fa fa-fw fa-caret-right text-primary"></i>
<a class="btn-ghost-sm text-sm text-nowrap" href="/category/13/nodebb-blog">NodeBB Blog</a>
</div>
<div class="d-flex align-items-center gap-1">
<i class="fa fa-fw fa-caret-right text-primary"></i>
<a class="btn-ghost-sm text-sm text-nowrap" href="/category/5/feature-requests">Feature Requests</a>
</div>
<div class="d-flex align-items-center gap-1">
<i class="fa fa-fw fa-caret-right text-primary"></i>
<a class="btn-ghost-sm text-sm text-nowrap" href="/category/6/bug-reports">Bug Reports</a>
</div>
<div class="d-flex align-items-center gap-1">
<i class="fa fa-fw fa-caret-right text-primary"></i>
<a class="btn-ghost-sm text-sm text-nowrap" href="https://explore.transifex.com/nodebb/nodebb/">NodeBB Localization</a>
</div>
</div>
</li>
<li><a class="dropdown-item" href="/category/7/nodebb-plugins">NodeBB Plugins</a></li>
<li><a class="dropdown-item" href="#">...add more as needed...</a></li>
Modify the links to match your forum categories. To create dividers between sections you can use <li class="dropdown-divider">
Now you can navigate your categories without going to the home/categories page.
Thanks to @Ben-Lubar we now have replies to posts. https://github.com/NodeBB/NodeBB/pull/5050
Right now it only displays one level of replies but you can modify your theme and remove this conditional https://github.com/NodeBB/nodebb-theme-persona/blob/master/templates/partials/topic/post.tpl#L87-Lundefined then you will get nested replies as well.
You can update to master or wait for 1.3.0 to get the feature. It looks like this.
As usual please report any bugs you find on our tracker at github.
This plugin allows defining keywords and descriptions in the admin control panel. These keywords will display a tooltip when the user mouse overs them in posts. Keywords are also displayed at /glossary along with information about each keyword.
npm install nodebb-plugin-glossary
More info:
A glossary plugin. Contribute to NodeBB/nodebb-plugin-glossary development by creating an account on GitHub.
GitHub (github.com)
This will be a post about the various caches in NodeBB and how they work.
There are 4 different caches, I will go over each one and explain how they work and how they help make nodebb faster. But before that let's remember what a cache is and how they help:
In computing, a cache is a hardware or software component that stores data so that future requests for that data can be served faster; the data stored in a cache might be the result of an earlier computation or a copy of data stored elsewhere. A cache hit occurs when the requested data can be found in a cache, while a cache miss occurs when it cannot. Cache hits are served by reading data from the cache, which is faster than recomputing a result or reading from a slower data store; thus, the more requests that can be served from the cache, the faster the system performs.
To be cost-effective and to enable efficient use of data, caches must be relatively small. Nevertheless, caches have proven themselves in many areas of computing, because typical computer applications access data with a high degree of locality of reference. Such access patterns exhibit temporal locality, where data is requested that has been recently requested already, and spatial locality, where data is requested that is stored physically close to data that has already been requested.
Source: https://en.wikipedia.org/wiki/Cache_(computing)
All the caches in nodebb use the nodejs module https://www.npmjs.com/package/lru-cache, A cache object that deletes the least-recently-used items.
It let's you cache things and drop things out of the cache if they are not used frequently.
Let's go chronologically and see what caches there are and why they were added.
(added in 2015)
Out of all the caches this one was the most obvious. When a user types a post the content of that post is stored as is in the database. In NodeBB's case this is markdown but other formats can be used as well. Storing the text as the user typed it makes it easy to implement things like editing, since we can just display the same content in the composer. But when we need to display the post as part of the webpage we need to convert it into html. This process happens in :
Posts.parsePost = async function (postData) {
if (!postData) {
return postData;
}
postData.content = String(postData.content || '');
const cache = require('./cache');
const pid = String(postData.pid);
const cachedContent = cache.get(pid);
if (postData.pid && cachedContent !== undefined) {
postData.content = cachedContent;
return postData;
}
const data = await plugins.hooks.fire('filter:parse.post', { postData: postData });
data.postData.content = translator.escape(data.postData.content);
if (data.postData.pid) {
cache.set(pid, data.postData.content);
}
return data.postData;
};
To turn the post content into html the hook filter:parse.post
is used by nodebb-plugin-markdown
https://github.com/NodeBB/nodebb-plugin-markdown/blob/master/index.js#L152-L158. This is done entirely in the nodebb process and blocks the cpu since it is not an async IO operation. When displaying a topic we do this for 20 posts(1 page) and if 20 users are loading the same topic we are doing 400 parses to generate the same output. If the posts are longer the process takes more time as well.
So it was a no-brainer to cache the parsed content since it rarely changes and we can just display the cached html content. As you can see from the first piece of code if the post content is cached filter:parse.post
isn't fired and we don't spend time in the plugins.
This cache makes topic pages faster and reduces the cpu usage of the nodebb process.
(added in 2016)
Next up is the group cache, this cache is used in the groups module and caches all group membership checks.
Groups.isMember = async function (uid, groupName) {
if (!uid || parseInt(uid, 10) <= 0 || !groupName) {
return false;
}
const cacheKey = `${uid}:${groupName}`;
let isMember = Groups.cache.get(cacheKey);
if (isMember !== undefined) {
return isMember;
}
isMember = await db.isSortedSetMember(`group:${groupName}:members`, uid);
Groups.cache.set(cacheKey, isMember);
return isMember;
};
When you load any page in NodeBB there is almost always a privilege check to see if you can see certain content or perform certain actions. Can this user see all categories? Can this user post a reply to this topic? All of these questions are answered by checking if the user is part of a specific group.
After the initial setup of the forum group membership rarely changes so it was a perfect candidate for caching.
Unlike the post cache which lowers the cpu usage of the nodebb process, this cache reduces the calls made to the database. Instead of making one or more database calls on every navigation we just make them once and store the results.
(added in 2017)
The reason why this cache is named Object cache
is because it caches the results of db.getObject(s)
calls.
module.getObjectsFields = async function (keys, fields) {
if (!Array.isArray(keys) || !keys.length) {
return [];
}
const cachedData = {};
const unCachedKeys = cache.getUnCachedKeys(keys, cachedData);
let data = [];
if (unCachedKeys.length >= 1) {
data = await module.client.collection('objects').find(
{ _key: unCachedKeys.length === 1 ? unCachedKeys[0] : { $in: unCachedKeys } },
{ projection: { _id: 0 } }
).toArray();
data = data.map(helpers.deserializeData);
}
const map = helpers.toMap(data);
unCachedKeys.forEach((key) => {
cachedData[key] = map[key] || null;
cache.set(key, cachedData[key]);
});
if (!Array.isArray(fields) || !fields.length) {
return keys.map(key => (cachedData[key] ? { ...cachedData[key] } : null));
}
return keys.map((key) => {
const item = cachedData[key] || {};
const result = {};
fields.forEach((field) => {
result[field] = item[field] !== undefined ? item[field] : null;
});
return result;
});
};
Every time we load a page we make calls to the database to load the post/topic/user/category objects. These all use the call db.getObjects
. Since these objects rarely change and are requested frequently it makes sense to cache these as well.
This lowers the load on the database significantly. Once a topic has been accessed most of the data required will be in the cache for anyone else loading the same topic.
(added in 2018)
The last cache is a bit different than the others as it was added to cache different types of things and can be used from plugins as well. I will give two examples of how this is used in nodebb to make pages faster.
The first one is the list of categories. Whenever someone loads the /categories page we load a list of category ids. Since the list of categories rarely changes we cache it in the local cache.
Categories.getAllCidsFromSet = async function (key) {
let cids = cache.get(key);
if (cids) {
return cids.slice();
}
cids = await db.getSortedSetRange(key, 0, -1);
cids = cids.map(cid => parseInt(cid, 10));
cache.set(key, cids);
return cids.slice();
};
Another use of this cache is for plugin settings. Whenever a plugin loads settings with await meta.settings.get('mypluginid');
the result is loaded and cached.
Settings.get = async function (hash) {
const cached = cache.get(`settings:${hash}`);
if (cached) {
return _.cloneDeep(cached);
}
const [data, sortedLists] = await Promise.all([
db.getObject(`settings:${hash}`),
db.getSetMembers(`settings:${hash}:sorted-lists`),
]);
const values = data || {};
await Promise.all(sortedLists.map(async (list) => {
const members = await db.getSortedSetRange(`settings:${hash}:sorted-list:${list}`, 0, -1);
const keys = members.map(order => `settings:${hash}:sorted-list:${list}:${order}`);
values[list] = [];
const objects = await db.getObjects(keys);
objects.forEach((obj) => {
values[list].push(obj);
});
}));
const result = await plugins.hooks.fire('filter:settings.get', { plugin: hash, values: values });
cache.set(`settings:${hash}`, result.values);
return _.cloneDeep(result.values);
};
Out of all the caches used this one will have the highest hit rate as you can see from the screenshot. Because the things stored in this cache pretty much never change during regular operation, once the list of categories is loaded it will always be served from the cache unless you add or reorder categories.
(/admin/advanced/cache)
On the ACP cache page you can enable/disable the cache, see the hit rate for each cache and even download the contents of the cache as json.
You can also empty the cache here, this is sometimes useful if you have to make changes to the database directly via CLI, for example if you make a change in the database to a topic title and if that topic is cached you won't see the changes until you clear the object cache
.
Hope this answers any questions about the caches in NodeBB!