Administrator arranging a forum node tree on a widescreen monitor

Most “ugly forum index” complaints are not a theme problem. They are a tree problem. XenForo will happily render forty forums, three leftover “Test” nodes, and a staff room guests can still see the title of. A custom icon on each row will not hide that. Do this work before extra.less: pick the right node type, put it in a tree a stranger can scan, lock the private rooms, then change icons in a way that survives a 2.3 style variation and the next upgrade.

Members never see the word “node.” They see a forum list. You should still think in nodes — one tree, one parent each, one display order. Customize that tree. Do not decorate a mess.

What a node is, and what it is not

A node is a row in Forums → Nodes. It has a type, a parent, a display order, a URL portion, a description, and its own permission overlay. The public site never says “node.” It says “forum,” “category,” or just shows the list.

That generic name exists because the tree is not only forums. The current XenForo manual lists four types:

Type What it actually does
Category A container. Clicking it usually opens the child list. It is not a place to post.
Forum Threads and posts. This is the product. From 2.2 onward a forum can be discussion, article, question, or suggestion (or a mix).
Link forum A redirect. Click → the URL you typed in the ACP. Use it for a specific thread, a help page, or an off-site resource you truly want in the tree.
Page Static HTML that sits in the tree like a forum. FAQs, rules, a short handbook.

Since 2.2 the ACP also lets you add a Search forum: a saved search that looks like a forum in the list (unanswered questions, threads with a prefix, posts from the last week). The four-type page in the manual has not caught up. Treat Search forums as a fifth type when you are building the tree, not as a replacement for a real forum.

If you cannot say in one sentence what a row is for, it should not be a forum. A “General / Off-topic / Misc / Other” stack is four names for the same leftover pile. One leftover pile is enough.

Pick the type before you pick the icon

Admins reach for a new Forum because that is the button they know. The type is the customization members feel first.

Use a category when the children are the content and the parent is only a heading. A category of one child is a wasted tap on a phone — unless two more rooms are coming this week.

Use a discussion forum when people should start threads and reply. Use an article forum when the first post is the artefact (patch notes, editorial) and replies are comments; converting a living discussion forum later is messy. Use a question forum when a thread should mark a solution — support belongs here, not in a dump of discussions with a hoped-for add-on badge. Use a suggestion forum when votes should change the sort. Feature requests yes. “What should we eat at the meetup” no.

Use a page when the content does not need replies: rules, a short handbook, a staff SOP you still want in the tree. If that page is the first thing a new member should see, hang it off the welcome path in the 30-day onboarding plan, not under Archive / Meta / Other.

Use a link forum when the destination already exists. A rules page and a rules thread is how you get two contradictory versions. Use a search forum as a view, not a home: “Unanswered this week” is a useful row; “everything about cars” is a real forum plus a prefix.

You can mix thread types in one forum. Do that only when staff will actually use the picker. A mixed forum where everyone still hits Discussion is a discussion forum with extra UI.

Build the tree before you decorate it

XenForo’s own example is the one that still works: categories at the top, content nodes inside them. Nest as deep as you want technically. Stop at two levels for anyone who is not staff. A third level is where new members decide the site is “complicated” and leave.

A tree that survives contact with real people looks like this:

  • Start here (category) — introduce yourself, rules page, one “how this place works” forum
  • The actual topic (category) — two to six forums a stranger can tell apart by title alone
  • Making things or Playing (category) — only if that is a different job from the topic above
  • Staff (category, private) — ops, #mod-queue notes, the “why this node exists” thread

Sort with the Sort button on the node list, not by editing display-order integers one at a time. After every drag, open the forum list as a guest and as a brand-new registered account. The ACP order is not always the public order you think it is, because hidden and private nodes drop out of the guest view and leave odd gaps.

Display in the node list is the switch people forget. Turn it off for a page you only reach from navigation, or for a forum that exists so an importer had somewhere to put old threads. The node still has a URL. It just stops cluttering the index. If you hide a parent, remember the official rule: a user who cannot view a parent will never see the children, even if you later grant View on the child. Hiding and locking are different tools. Use the switch for clutter. Use permissions for secrets.

URL portions should be short and stable. Changing a URL portion later is a redirect project. Do not encode the current icon, season, or “v2” in the slug. support beats new-support-desk-2026.

Descriptions are for one line that a skimming member can use. “Bugs, crashes, and ‘it won’t start’ — not feature ideas” is a description. A pasted copy of the rules is not. Long HTML in the description also fights you on small screens, where XenForo already collapses or truncates node extras. Put the essay on a page node.

Permissions sit under the paint

A beautiful staff room that Registered can still open is not customized. It is leaked.

The official pattern for a staff-only forum is still the right one:

  1. Create the forum under a Staff category.
  2. Open Permissions for that forum.
  3. Enable Private node and save. That denies everyone who is not then granted access.
  4. Set View node to Yes for Administrative and Moderating (and any custom staff group you actually use).
  5. Leave Registered and Unregistered / Unconfirmed alone. Private already removed them.

Do not “hide” a staff forum by setting Never on Registered for View across the whole site. That is how you lock yourself out of public forums. Never is a lock. Private plus a Yes on the staff groups is a room.

Parent inheritance matters more than the icon. If Staff category is private, children inherit the wall. If Staff category is public and only one child is private, the category title still tells guests that a staff area exists. Decide which of those you want. Some communities like a visible “Staff” row they cannot enter. Most do not.

Test with three sessions after every permission change: guest, a throwaway Registered account, and an account that only has the Moderator secondary group. The permission analysis page is faster than guessing. The permissions starter map is the model; this article will not re-teach Yes / No / Never / Not set.

Node-specific moderators are a separate control (the Moderators menu on the node). They inherit downward to children. Use them when a game section has its own team and you do not want those people in the global queue. Do not use a node moderator as a substitute for a private node. A moderator who cannot view the node is not a moderator.

Change all the icons first, then the special ones

XenForo 2.3 still ships Font Awesome node icons. It no longer treats them as a webfont you can poke with content: "\f019" and a font-family. Icons are subsetted: the system looks at templates and Less, builds SVG sprites for the icons you actually use, and ships those. That is why a 2.2 extra.less snippet that only set a Unicode code point now shows nothing, or shows the default speech-bubble and a broken extra icon.

Do the global change in the style, not in a template.

  1. Work in a child style. Appearance → Styles → add a style whose parent is the one you currently serve. Put every experiment here. When 2.3.x ships an updated node_list template, you want one outdated extra.less, not a fork of the default style.
  2. Open Style properties → Node / forum list for that child style.
  3. Set Read node icon and Unread node icon. Use the Font Awesome name only — comments, comments-dollar, book — not fa-comments and not a Unicode escape.
  4. Save and hard-refresh the forum list. Confirm read and unread both change. Unread is what members use to decide the board is alive.

If you run style variations (the 2.3 light / dark switch), look at both variations before you celebrate. A property that is marked as variant-aware can differ between light and dark. An image you later paste into extra.less will not flip with the variation unless you write that flip yourself.

This is also the moment to decide whether you want per-node icons. A support community with six forums often looks calmer with one pair of read/unread icons and strong titles. A gaming hub with twenty game rooms is the case for per-node icons: the icon is a wayfinding device, not decoration.

Per-node Font Awesome icons in extra.less (2.3)

Each public row carries a class node--idN where N is the node ID from the ACP (the number in the edit URL, not the display order). That class is the stable hook. Titles change. IDs do not, unless you delete the node and create another.

In the child style, edit the extra.less template. For node 12:

.node.node--id12 .node-icon svg {
  display: none;
}

.node.node--id12 .node-icon i:before {
  .m-faContent(@fa-var-life-ring);
}

Two lines, on purpose.

The first hides the SVG sprite 2.3 injects for the default icon. If you only set :before, a lot of 2.3 boards show both icons stacked. The community threads about “replacing node icons via CSS” after the 2.3 upgrade are almost all this miss.

The second is the supported Less mixin. @fa-var-life-ring is the variable for the life-ring icon. Use the icon name in that variable, not a raw content: "\f1cd". The mixin is what the subsetter can see. A magic Unicode string in extra.less is how you get a missing icon in production and a fine icon on your laptop, because your laptop still has a full Font Awesome webfont cached from 2022.

Repeat per node. Keep the IDs in a staff thread next to the extra.less snippet. The next admin will not remember that 12 is Support and 19 is the archive you meant to delete.

To stamp the same icon on every forum inside a category, hook the category block instead of each child:

.block.block--category4 .node-icon svg {
  display: none;
}

.block.block--category4 .node-icon i:before {
  .m-faContent(@fa-var-gamepad);
}

Use this when a whole section is one kind of room and you do not want twelve ID rules. Override one child with a more specific .node.node--idN if it needs a different mark.

Keep unread on XenForo’s own .node--unread / .node--read classes. Recolour the icon if you must (color: @xf-paletteColor1 on .node.node--id12.node--unread .node-icon i). Do not invent a second unread mechanism with row opacity — you will fight core CSS on every upgrade.

If a correct mixin still shows nothing, rebuild caches from the ACP and confirm the icon exists in the Font Awesome set XenForo 2.3 ships. A name from a newer Font Awesome marketing page may not be in that set. If it still fails, the style or an add-on is still emitting 2.2 webfont markup. Fix that style; do not pile more content: hacks on top.

When you actually want images

Image icons make sense when the mark is a game crest, a product silhouette, or something FA cannot say in 16 pixels. They are a worse default than FA: they do not recolour for unread, they need a dark-variation version, and they add requests to the forum list — the page you most want to be cheap.

A minimal 2.3-friendly pattern: kill the FA glyph, then paint a background on the i.

.node.node--id12 .node-icon i {
  background: url("styles/yourchild/support-node.png") center / 32px 32px no-repeat;
}

.node.node--id12 .node-icon i:before,
.node.node--id12 .node-icon svg {
  display: none;
}

Put the files in your child style’s styles/ path, not in the default style directory and not in /data as a one-off upload you will lose track of. Use a 64×64 PNG if you serve 32×32, so high-density screens do not smear. Keep the node-icon column width in mind — Style properties → Node / forum list is where the default column is sized. A 96-pixel crest in a 40-pixel gutter overflows into the title on mobile.

For read / unread with images, swap the background on .node--unread .node-icon i versus .node--read .node-icon i. For light / dark variations, serve a second asset with the variation selector your style already uses. If you do not know that selector, stay on Font Awesome. A crest that vanishes in dark mode looks like a broken board, not a branded one.

Layout tweaks that should stay in extra.less

Icons are one percent of the index. The rest is density. Stay in extra.less and existing classes; do not fork node_list_forum.

Tighten category strips with the Node / forum list and category style properties before you write CSS. extra.less is for the one category that should not look like the others. Sub-forums in the list are also a property — turn them on only where the child name helps on the parent row. Eight tiny child links under a parent is worse than clicking the category.

Do not hide last-post columns or thread counts globally. Counts are how a new member tells a room is alive; hiding .node-extra everywhere makes a quiet board look deader. If the default responsive rules wrap badly on your style, hide extras at your breakpoint and check a phone and a 1200-pixel laptop.

When extra.less is not enough, use a template modification on node_list_forum or forum_list with a narrow find/replace. A cloned template goes outdated the next time XenForo adds a data attribute. If the modification is more than a handful of lines, you are writing a node-list add-on. Directly editing the default node_list is how 2.3 upgrades produce a white screen. Child style + extra.less + optional modification. That is the stack.

When an add-on is the right tool

Stock XenForo will not give you a three-column card grid, a per-node background photograph, or a “featured forum” mosaic. Those are add-on jobs, and they still exist for 2.3.

Use one when the index layout is the product (a gaming portal, a server hub, a magazine front). Do not install one because you wanted different icons. You already have icons.

If you add one, confirm it is built for 2.3 SVG icons and style variations, keep its CSS in the same child style as your extra.less, and re-test private nodes — some layout add-ons render a card from the title before they check View. Guests should not see a “Staff” tile. Keep a screenshot of the stock list so rollback is not “restore last night’s database.”

An add-on is not a substitute for a bad tree. Cards of Misc, Off-topic, and Test 3 are still Misc, Off-topic, and Test 3.

FAQ

Do I need an add-on to set a different icon per forum?
No. node--id plus .m-faContent in extra.less is enough for Font Awesome. Add-ons save time when you have dozens of nodes and want a UI for it. They are not required for six forums.

Why do I see two icons after I add my Less?
You did not hide the 2.3 SVG. display: none on .node-icon svg in the same rule block.

Can guests see a node I set to “not displayed in the node list”?
If they have View and they have the URL, yes. Display-in-list is not a permission. Private node is.

Will extra.less icons break on the next 2.3.x?
The mixin is the supported hook. A cloned node_list template is what breaks. Keep extra.less small and the template vanilla.

Do this afternoon

  1. On paper, list every public row a guest can see. Cross out anything you cannot explain in a title plus five words.
  2. In Forums → Nodes, make the survivors match that list. Categories on top. Sort with the Sort button.
  3. Private the staff rooms. Confirm with a guest session and a fresh Registered account. Check analysis, not just the eye test.
  4. Create a child style. Change the global read / unread icons in Node / forum list. Stop here if the board already looks like a place with a job.
  5. Add per-node FA icons only for rooms a new member would otherwise mix up. Hide the SVG. Use .m-faContent. Write the ID map in a staff thread.
  6. Resist the card-grid add-on until the tree is boring and correct.

A customized node list is a map. The icons are street signs. If the streets are wrong, nobody cares that the signs are handsome.