How to structure Discourse for an online course?

@Dax Is still the case in 2020, that you can’t limit posts in a topic to users in the poster’s group?

We want to use Discourse with our online learning system…we want to have one set of seven or so topics that different cohorts (groups) of users move through, such that they can only see posts within their group. We’re rather have one set of topics rather than creating the same topics again and again each new cohort.

Perhaps another new feature has arrived in the meantime that make this possible? Thanks for any thoughts.


Sorry your question is unclear and seems unrelated.

You can create categories, categories can be secured using groups.

What @HappyGezim is asking for is a custom “whisper” feature within a topic, this is not on our roadmap.

@sam Thanks for your quick response! I’ll try to clarify with our exact scenario:

  • We have four categories set up, one for each of the four courses we offer.

  • In each category (course) we have approximately 5 to 10 topics, one for each “Lesson” in the course…plus a few extra like “Technical Questions”, “Introduce Yourself” etc. As each Lesson arrives, students are asked to make contributions to the related topic.

  • We are going to have lots of cohorts of students moving through these courses, and want to limit posts in a topic to their cohort “group.” That way we keep the same categories and topics static and just modify user properties to assign them to different groups, which we could create (?) via the API and dynamically assign students (?)

So that’s the context that led me to latch on to the top question “Inside a specific topic, can I create a message that’s only visible to users that belong to a specific group?”

1 Like

Daniel, I also have a course I run thru Discourse. I use a category + subcategory that allows for easiest restricting.

Category: Acme Course
Sub Category: 2020-05 - Course Conversations

The students in a specific cohort only see one subcategory.

It’s not perfect but it works!


@waffleslop Awesome. Thanks. Do you create those sub categories manually each time you have a new cohort? (or perhaps via API?)

I was hoping to avoid that because for every cohort I’ll have to set up the same 5 to 10 new topics in a subcategory. We may have a bunch of simultaneous cohorts going through any one run of the course too, which means I’d have to get creative with naming. So building on your example …
2020-05-cohort-A Course Conversations
… or perhaps there’s a way to create sub-sub-subcategories haven’t looked at that yet.

Thanks again for your thoughts.


Put those in read-only categories.

When you get a new cohort, create a new category for the cohort. Have students click the :link: icon and then “new topic” to create a new topic for that assignment in the cohort category. I had them tag each assignment with an assignment tag to make it easier to track whether and when people had done the assignment (and I created badges that were awarded if I “liked” their topic and even made a script to do this for all of them, create a CSV, and upload it to the university LMS that I didn’t want to use).


@pfaffman Thanks for your input.

My working idea was to use subcategories to group cohorts beneath a course, but then saw this in the UI when I was creating a subcategory

Am I correct in thinking this means there’s no way to use subcategories to group cohorts beneath a course and then use group permissions to limit them to that subcategory? @waffleslop were you able to limit by subcategory in your approach? Maybe I’m reading that UI message wrong.

If you can’t limit a subcategory to a group, @pfaffman I think your approach (thanks for explaining) where you create a new category for each cohort is probably the only option.

Since our 10 or so topics in each course are pretty firmly fixed, have specific naming and numbering, etc. I’m thinking I will create those via the API each time a new cohort is created in our system. So for each new cohort we create in our LMS I’ll use the API to:

  • create a new category in Discourse for that cohort
  • create a new group in Discourse with access to that category
  • create the correct 10 or so topics in the new category.
  • anytime a student is added to a cohort in our LMS, add them to the correct group in Discourse (and remove them if they leave)

Did you ever try this approach instead of relying on the student to create the topic themselves? I’m wondering about different students creating slightly different named topics for the same assignment in the course.

Unclear on your suggestion to use “read-only categories” for an aspect of this problem.

Thanks much for taking the time to write down your thoughts!


Here’s the format:

Category: Acme Course
Groups: 2020-01_cohort, 2020-05_cohort


  • 2020-01 - Course Conversations (Group: 2020-01_cohort)
  • 2020-05 - Course Conversations (Group: 2020-05_cohort)

Aha. Thanks @waffleslop. Ok, so you’re saying you can limit subcategory to group and thereby disallow other subcategory access. I’m misunderstanding that UI message I copied above. :zipper_mouth_face:

Therefore our approach will probably be to use the API to:

  • create a new subcategory in Discourse for each cohort
  • create a new group in Discourse with access to that subcategory (as well as parent category, per UI message above)
  • create the correct 10 or so topics in the new subcategory.
  • anytime a student is added to a cohort in our LMS, add them to the correct group in Discourse (and remove them if they leave)

I’m pretty sure that the parent can be read-only the the subcategories are restricted just to the one group.

You can, but this way you need to create (and maintain unless you get them perfect the first time) the read-only categories with the instructions only once, and when you create a cohort, you need to create just the one subcategory.

I think that’s why I used tags. They’ll tag the topic with the assigment tag and then the topic can be descriptive but it won’t hurt anything if they choose a stupid one.


For anybody taking the approach outlined above – i.e. using subcategories for each course ‘cohort’ and repeating the discussion topics in each – make sure to enable the “allow duplicate topic titles” setting, otherwise Discourse won’t let you repeat the same topics in each each subcategory.


This is part of why I like my solution of having a single read only category with the content and having students discuss that content with new topics in the cohort-specific category.


Hi @Daniel_McQuillen. I was curious about how your course went. I am looking at running three courses, each with multiple cohorts, and was interested in your experience so far.

Also, are you expiring any of your courses or access to the discussions?

Thanks in advance for sharing, Hunter


Hi Hunter,

We’re currently in beta but the Discourse integration is going well. We’re using the SSO integration to force sign in on our site. That’s worked fine, although I’ve noticed

  1. Discourse won’t take usernames with “@” sign in them…it truncates the username to just first part before “@” … this can cause problems if you later call the Discourse APIs with that username as an argument. Discourse won’t recognise a username like b/c in Discourse that user’s username is stored as “someone” … easy way around this is to disallow “@” signs in your own usernames!
  2. When someone registers on your own site you have to explicitly call the Discourse API to sync the SSO user, as you might want to do things with that user (e.g. add them to a Discourse group) before they visit the Discourse site for the first time (which would automatically sync the SSO). I have a Django-based site, so I’m using the pydiscourse library and there’s a sync_sso method that make this pretty easy (pydiscourse · PyPI)

Yes, we will expire some of our courses, in which case the server will call the Discourse API and remove the user from the general group for that course, as well as the group dedicated to their cohort in that group.

I’ve created tables in my Django site that keep track of these “course” groups and the various “cohort” groups within each course. So I use that information when adding/removing students, etc: