How to Show "New Topic" Button for Non-Logged In Users in Discourse
Introduction
This guide will show you how to create a "New Topic" button for non-logged-in users in Discourse. By default, "New Topic" button is only visible to logged-in users. When clicked by a guest user, it will prompt them to sign up.
Note from the author: This solution was developed with significant help from Claude (Anthropic's AI). While the code works, I don't fully understand all the technical details of why it works. If you're a developer who can explain this better, please feel free to contact me to help improve upon this guide!
The Solution
Step 1: Add JavaScript Code
In your Discourse admin panel:
- Go to Appearance → Components
- Install → + Create New
- Add this code to the Body section of your Component:
(function() {
const { api } = require("discourse/lib/plugin-api");
const { withPluginApi } = require("discourse/lib/plugin-api");
withPluginApi("0.8", api => {
const addNewTopicButton = () => {
// Check if user is logged in
if (Discourse.User.current()) {
return; // Exit if user is logged in
}
const navContainer = document.querySelector('.navigation-container');
if (!navContainer) return;
// Create button if it doesn't exist already
if (!document.querySelector('.guest-new-topic-button')) {
const button = document.createElement('button');
button.className = 'btn btn-icon-text btn-default guest-new-topic-button';
button.innerHTML = `
<svg class="fa d-icon d-icon-plus svg-icon svg-string" xmlns="http://www.w3.org/2000/svg">
<use href="#plus"></use>
</svg>
<span class="d-button-label">New Topic</span>
`;
// Add click handler to open signup modal
button.addEventListener('click', () => {
const authButton = document.querySelector('.sign-up-button');
if (authButton) {
authButton.click();
}
});
navContainer.appendChild(button);
}
};
api.onPageChange(() => {
setTimeout(addNewTopicButton, 100);
});
api.onAppEvent('page:changed', () => {
setTimeout(addNewTopicButton, 100);
});
});
})();
Step 2: Add the CSS
Add this CSS to your theme's Stylesheet section:
.guest-new-topic-button {
color: var(--secondary);
background: var(--tertiary);
transition: all .3s linear;
border-radius: var(--mint-border-radius);
text-transform: uppercase;
border: 2px solid var(--tertiary);
margin-left: 1em;
height: 38px !important;
min-height: 38px !important;
padding: 3px 12px !important;
line-height: 1 !important;
}
.guest-new-topic-button:hover {
background: color-mix(in srgb, var(--tertiary) 85%, black) !important;
border-color: color-mix(in srgb, var(--tertiary) 85%, black) !important;
}
.guest-new-topic-button .d-icon {
font-size: 0.8em;
margin-right: 4px;
}
.guest-new-topic-button .d-button-label {
font-size: 0.9em;
}
What This Does
- Shows a "New Topic" button to non-logged-in users
- Matches the style of the regular "New Topic" button
- Opens the signup modal when clicked
- Persists across page navigation
- Only appears for guests (non-logged-in users)
Troubleshooting
If the button doesn't appear:
- Verify you added the code to the Body section
- Test while logged out
- Clear your browser cache and reload
- Make sure you're not running other themes that might conflict
Background
Finding a solution for this was challenging because:
- Discourse's documentation doesn't cover this specific use case
- The button needs to persist across Discourse's single-page navigation
- The solution requires understanding of Discourse's plugin API
- There weren't many resources available online about this specific customization
Need Help?
If you run into issues or need to customize the button further, the Discourse community forums are a great place to ask for help. Remember to share any improvements you discover to help others!