Best tools, materials & practices to onboard a hoarde of new users?

Hi there!
we’re a higher education learning platform for refugees, and we will launch discourse as part of our platform in a few days. We hope that it will soon become the social core of our virtual campus.

Now I think we’re all aware that discourse has a steeper learning curve than traditional forum systems. For us, we have the additional problem that a considerable share of our student body is below average computer literate.

When we invite 1000-1500 of our students to create a discourse account, we’d obviously like them to learn how to use discourse asap. What are the best ways to accomplish this - are there technical solutions for this, such as showing tips for the most essential features, overlaying a one-time explanatory message/screenrecording or something along those lines? Are there existing materials that we can use? What’s worked and what hasn’t in the past?

(Oh and this is completely offtopic and possibly inappropriate - but we’re always looking for volunteers of all skillsets, but particularily urgently for developers, in case creating scalable education for refugees sounds interesting to anyone reading this. Sorry, I had to…)

Thanks in advance for any input!


I don’t feel this is an accurate characterization, so I’d like to question this assumption.

Discourse is no harder to use than Facebook (on the web), in the sense that if someone is familiar with the basics of creating an account on Facebook and logging in to it, they should have no problem with any modern web app including Discourse.

There’s simply “less stuff on the screen” with Discourse versus an average, say, vBulletin or phpBB forum, so there is less to confuse people.

Now if it is an issue of general computer literacy, that could be a concern. I doubt the resources needed to teach logging in, logging out, the web browser, etc would be particularly unique to Discourse though.

I guess the easiest thing is a few screen recordings of the basics: logging in, reading, replying.


Thanks for your quick reply. Sorry, I must’ve misinterpreted a blog post of your colleague to understand it as there’s an agreement on the steeper learning curve - absolutely not a discussion I’m looking to start here, though. The students are all computer literate, just some are less than average computer literate, meaning I expect them to take a longer time to figure out unknown UX for themselves.

Okay, so

I guess the easiest thing is a few screen recordings of the basics: logging in, reading, replying.

goes in the direction of discussion I was looking to have. Does something like this exist already, do you have an information package for onboarding new users? Otherwise, a screen recording is easy enough to do myself, but how would you display it on discourse so that every new user sees it - are there tools (plugins) for this?

1 Like

IMHO there is a “learning curve”.

For Staff and even more for Admins there can be quite a few CPs to get familiar with and features that need to be understood.

For developers, even with knowledge and experience, there is a lot of Ruby and Ember to get familiar with.

But for a non-Staff forum member, I think most of the UI is fairly straight forward, with most of the “hidden” features becoming known when they are needed.

I think what most have trouble with is learning how to correctly format blocks of code. (if your forum won’t have code examples, this problem won’t exist for you).
And in general how raw to cooked works.
eg. Why didn’t my link onebox?

@Flo Look at the user defaults & set them carefully before you get started. There is no good way to have changes you choose to make later apply to existing accounts.

That’s the learning curve IMO -

  • How to know which categories you want users to Watch by default (watching means they’ll get emailed about activity, even if not online)
  • How teach your users which categories how to Watch/Track, and if “Mailing List Mode” is right for them.

There’s also the fact that that mailing list mode will get them emailed copies of their posts, people who are Watching Categories don’t.


Seriously consider the import process to create users… the built in one or by @vindia (thank you for this tool)

I’ve found that managing who hasn’t accepted an invitation is a challenge (when did they get the last invite? did they know what to do with it, etc). If you are dealing with a closed group, then your process of user-education should make this less of an issue for you.

Actually using discourse

This is where it gets good. I find the UI to be very straightforward and wonderful.

The only thing I can think of which might need education is if you’re going to have Wiki pages… telling people which ones exist or how to ID them would be nice… but only because it’s just not something I’d assume is there in a forum. (Love me some wiki pages!)

1 Like

Thank you so much for your detailed response!

Yes, invitations actually is one of the things on my mind. Does Vinda’s tool offer any additional options to the one built in? Do you know if it’s possible to re-send an invitation to users that haven’t clicked on the link?

Interestingly the discourse how-to says invitations don’t work with SSO, we tested it with one email address, however, and it worked like a charm.

Vinda’s tool creates users, skipping the invite process. :tada:

I haven’t used the built in method, but I guess this one allows you to set a username, where the built in one relies on auto-generation(?).

The problem with auto-generation is the inconsistent display of username and full name if they match for some people (not displayed) and if they don’t match for others (displayed). The argument there is that there’s no need to show the information twice… I find having them both displayed at all times would be better, since Sam Samplesam_samplesamsample

The user import GitHub - vindia/discourse_user_importer: A tiny script to import users from a CSV file into Discourse by @vindia looks to be exactly what I need, however I am unable to make it work.

I am not a developer and I do not know ruby or rake. I have downloaded the zip file from github and unzipped it in a folder, but when I try to run it, I get:

No Rakefile found (looking for: rakefile, Rakefile, rakefile.rb, Rakefile.rb

I tried searching the web for this error and found some stuff about making sure you are running from the project root directory. (I am in the folder containing the .rake file).

Any help for a ruby novice? A step-by-step idiot’s guide would be helpful.

Hey Alan,

You need to put the file in the lib/tasks folder of the main Discourse Rails application. This is where you will also find other folders like app/, config/ and files like Gemfile, Gemfile.lock, Rakefile etc. You cannot just download it and run it from a random folder, as it will need the Discourse Rails application to run. This is also why you get the error you posted above, since the script cannot find the Rakefile file, which is needed to run the script (and it doesn’t need just that file, it will need the entire Rails application too).

Once you’ve copied the file into the right folder, you can run it with rake user_importer:check[/path/to/users.csv].

For example, when you’ve created a CSV file users.csv and save it in the tmp/ folder, which you can find in the Discourse Rails application folder (which is also where you’ve just saved the script in the lib/tasks folder). You can now run the script as follows:

rake user_importer:check[tmp/users.csv]

Let me know if this works.

1 Like

Hi Vincent,
Thanks for the reply. I have finally located a directory like you described. It is a bit obscure:


I put the user_importer.rake in lib/tasks under that directory, and trying again, I get the same error. I’m thinking this may not be the right directory?

This instance is a “pre-built” installation on Digital Ocean. Discourse version 1.8.0b10 on Ubuntu 14.04

root@discourse-2gb-nyc3-01:/var/lib/docker/aufs/diff/03aa5df8216686cd9381e210e81118b80db2d90fcbfd06eb8a40f8324f59c1a9/var/www/discourse# rake user_importer:check /tmp/users.csv --trace
rake aborted!
No Rakefile found (looking for: rakefile, Rakefile, rakefile.rb, Rakefile.rb)
/usr/lib/ruby/vendor_ruby/rake/application.rb:584:in `raw_load_rakefile'
/usr/lib/ruby/vendor_ruby/rake/application.rb:89:in `block in load_rakefile'
/usr/lib/ruby/vendor_ruby/rake/application.rb:160:in `standard_exception_handling'
/usr/lib/ruby/vendor_ruby/rake/application.rb:88:in `load_rakefile'
/usr/lib/ruby/vendor_ruby/rake/application.rb:72:in `block in run'
/usr/lib/ruby/vendor_ruby/rake/application.rb:160:in `standard_exception_handling'
/usr/lib/ruby/vendor_ruby/rake/application.rb:70:in `run'
/usr/bin/rake:27:in `<main>'

I think that’s because you’re trying to run the file directly, whereas the Rails app lives inside a Docker container. You need to run the file from the Docker container, otherwise the Rails application is not loaded and thus the Rake task will not work.

As you can see in Regis answer here, you enter the Docker container by doing the following:

  1. ssh into your server on DigitalOcean
  2. cd /var/discourse
  3. ./launcher enter app
  4. rake user_importer:check[tmp/users.csv]

Now it should work (haven’t tested it, and it’s a while that I’ve used Discourse, but I think it does).

The next issue will probably be getting your CSV file inside the Docker container. As far as I know and remember, you can used the shared folder for this, as this will be automatically mounted by the Docker container. To do so, do the following:

  1. On your server, save / move your CSV file in the /var/discourse/shared/standalone folder
  2. Start the Docker container with ./launcher enter app from the /var/discourse folder, as in the previous steps above
  3. Execute the command cp /shared/users.csv tmp/users.csv, this will copy the CSV file to the right directory for my script (change users.csv to whatever the name of your file is)

You can read a little more on this here /shared folder not mounted in Docker container


Thanks so much for the very detailed reply. I think I understand better how this is supposed to work. However, I am getting a number of errors when I run it:

Any ideas on this?

rake user_importer:check tmp/users.csv
rake aborted!
SyntaxError: /var/www/discourse/lib/tasks/user_importer.rake:7: syntax error, unexpected '<'
<!DOCTYPE html>
/var/www/discourse/lib/tasks/user_importer.rake:8: syntax error, unexpected '<'
<html lang="en">
/var/www/discourse/lib/tasks/user_importer.rake:9: syntax error, unexpected '<'
/var/www/discourse/lib/tasks/user_importer.rake:14: syntax error, unexpected '<'
  <link crossorigin="anonymous" ...
/var/www/discourse/lib/tasks/user_importer.rake:14: syntax error, unexpected tIDENTIFIER, expecting end-of-input
...nk crossorigin="anonymous" href="https://assets-cdn.github.c...
...                               ^
/var/www/discourse/vendor/bundle/ruby/2.3.0/gems/activesupport-4.2.8/lib/active_support/dependencies.rb:268:in `load'
/var/www/discourse/vendor/bundle/ruby/2.3.0/gems/activesupport-4.2.8/lib/active_support/dependencies.rb:268:in `block in load'
/var/www/discourse/vendor/bundle/ruby/2.3.0/gems/activesupport-4.2.8/lib/active_support/dependencies.rb:240:in `load_dependency'
/var/www/discourse/vendor/bundle/ruby/2.3.0/gems/activesupport-4.2.8/lib/active_support/dependencies.rb:268:in `load'
/var/www/discourse/vendor/bundle/ruby/2.3.0/gems/railties-4.2.8/lib/rails/engine.rb:658:in `block in run_tasks_blocks'
/var/www/discourse/vendor/bundle/ruby/2.3.0/gems/railties-4.2.8/lib/rails/engine.rb:658:in `each'
/var/www/discourse/vendor/bundle/ruby/2.3.0/gems/railties-4.2.8/lib/rails/engine.rb:658:in `run_tasks_blocks'
/var/www/discourse/vendor/bundle/ruby/2.3.0/gems/railties-4.2.8/lib/rails/application.rb:452:in `run_tasks_blocks'
/var/www/discourse/vendor/bundle/ruby/2.3.0/gems/railties-4.2.8/lib/rails/engine.rb:453:in `load_tasks'
/var/www/discourse/vendor/bundle/ruby/2.3.0/gems/railties-4.2.8/lib/rails/railtie.rb:194:in `public_send'
/var/www/discourse/vendor/bundle/ruby/2.3.0/gems/railties-4.2.8/lib/rails/railtie.rb:194:in `method_missing'
/var/www/discourse/Rakefile:7:in `<top (required)>'
/usr/local/bin/bundle:22:in `load'
/usr/local/bin/bundle:22:in `<main>'
(See full trace by running task with --trace)

Hey Alan,

I’m not entirely sure, but getting this error means that at least you’re running the file from the right location :).

I see two things that might cause this:

  1. You forgot to add the [ and ] surrounding the file name in your command. It should be rake user_importer:check[tmp/users.csv]
  2. It looks like your users.csv file is in fact an HTML file, not a CSV file. Could you open it from within the Docker container with something like nano tmp/users.csv or less tmp/users.csv and check if the format of the file is similar to the example file in my repo?

OK, I found that the user_importer.rake script did not contain the actual script. I remember that I had downloaded it directly into the lib/tasks using wget from github. It was full of html output from wget, rather than the actual script. :flushed:

Apologies for wasting your time with my stupidity!

I re-downloaded the zip file and copied the script from that file and now I am a step farther:

root@discourse-2gb-nyc3-01-app:/var/www/discourse# rake user_importer:check[tmp/users.csv] Username alehman-work is free to use!

I ran a check on your example file and that worked also, so I thought I was there!

Then I ran it with import on my file, but now I’m getting a new set of errors:

root@discourse-2gb-nyc3-01-app:/var/www/discourse# rake user_importer:import[tmp/users.csv]
rake aborted!
NoMethodError: undefined method `bio_raw_will_change!' for nil:NilClass
/var/www/discourse/lib/promotion.rb:59:in `change_trust_level!'
/var/www/discourse/app/models/user.rb:707:in `change_trust_level!'
/var/www/discourse/app/services/trust_level_granter.rb:13:in `grant'
/var/www/discourse/app/services/trust_level_granter.rb:8:in `grant'
/var/www/discourse/app/models/group_user.rb:63:in `grant_trust_level'
/var/www/discourse/vendor/bundle/ruby/2.3.0/gems/activesupport-4.2.8/lib/active_support/callbacks.rb:432:in `block in make_lambda'
/var/www/discourse/vendor/bundle/ruby/2.3.0/gems/activesupport-4.2.8/lib/active_support/callbacks.rb:228:in `block in halting_and_conditional'
/var/www/discourse/vendor/bundle/ruby/2.3.0/gems/activesupport-4.2.8/lib/active_support/callbacks.rb:506:in `block in call'
/var/www/discourse/vendor/bundle/ruby/2.3.0/gems/activesupport-4.2.8/lib/active_support/callbacks.rb:506:in `each'
/var/www/discourse/vendor/bundle/ruby/2.3.0/gems/activesupport-4.2.8/lib/active_support/callbacks.rb:506:in `call'
/var/www/discourse/vendor/bundle/ruby/2.3.0/gems/activesupport-4.2.8/lib/active_support/callbacks.rb:92:in `__run_callbacks__'
/var/www/discourse/vendor/bundle/ruby/2.3.0/gems/activesupport-4.2.8/lib/active_support/callbacks.rb:778:in `_run_save_callbacks'
/var/www/discourse/vendor/bundle/ruby/2.3.0/gems/activerecord-4.2.8/lib/active_record/callbacks.rb:302:in `create_or_update'
/var/www/discourse/vendor/bundle/ruby/2.3.0/gems/activerecord-4.2.8/lib/active_record/persistence.rb:120:in `save'
/var/www/discourse/vendor/bundle/ruby/2.3.0/gems/activerecord-4.2.8/lib/active_record/validations.rb:37:in `save'
/var/www/discourse/vendor/bundle/ruby/2.3.0/gems/activerecord-4.2.8/lib/active_record/attribute_methods/dirty.rb:21:in `save'
/var/www/discourse/vendor/bundle/ruby/2.3.0/gems/activerecord-4.2.8/lib/active_record/transactions.rb:286:in `block (2 levels) in save'
/var/www/discourse/vendor/bundle/ruby/2.3.0/gems/activerecord-4.2.8/lib/active_record/transactions.rb:351:in `block in with_transaction_returning_status'

It goes on and on.

Great job with the progress you’re booking, we’re almost there! Fun isn’t it ;-).

The error you’re getting is because Discourse has changed since I wrote this script (which is not surprising, since my script is more than 2 years old now). Anyway, I’ve looked into the Discourse code and think it might be fixed by adding the line u.user_profile = between lines 27 and 28, see below for how it should look:

u.import_mode = true
u.groups = parse_user_groups new_user['groups']
u.user_profile =

I haven’t tested this as I’m not maintaining a Discourse install anymore, but I think it works. If not, it will destory anything so it’s worth the try. If it indeed works, let me know and I will update my script accordingly.

Thanks for sticking with me on this. I added the line you suggested. Now I get:

root@discourse-2gb-nyc3-01-app:/var/www/discourse# rake user_importer:check[tmp/users.csv]
Username alehman-work is free to use!

root@discourse-2gb-nyc3-01-app:/var/www/discourse# rake user_importer:import[tmp/users.csv]
rake aborted!
ActiveRecord::RecordNotUnique: PG::UniqueViolation: ERROR:  duplicate key value violates unique constraint "user_profiles_pkey"
DETAIL:  Key (user_id)=(32) already exists.
: INSERT INTO "user_profiles" ("user_id") VALUES (32) RETURNING "user_id"
/var/www/discourse/vendor/bundle/ruby/2.3.0/gems/rack-mini-profiler-0.10.1/lib/patches/db/pg.rb:90:in `exec'


I looked for user_profiles_pkey in the code but I don’t see it.

Ah that’s frustrating Alan! The key is something in the Database, I will try tomorrow if I can test some things and make my script work again for you.

Thanks Vincent. It would be most appreciated.

I’ve ran my original script, using the sample file in the GitHub repository, and don’t get the error that you’re getting Alan. Could you paste the first few lines of the CSV you’re trying to import so I could see if something else is causing this?

Sorry for the delay. Here’s the contents of file:

root@discourse-2gb-nyc3-01-app:/var/www/discourse# cat tmp/users.csv
email;name;username;title;groups;AlanL;alehman-work;Board Member at Large;members,imaging

I just upgraded to 1.9.0beta1. I am getting the following error:

rake user_importer:import[tmp/users.csv]
rake aborted!
ActiveRecord::RecordNotUnique: PG::UniqueViolation: ERROR:  duplicate key value violates unique constraint "user_profiles_pkey"
DETAIL:  Key (user_id)=(35) already exists.
: INSERT INTO "user_profiles" ("user_id") VALUES (35) RETURNING "user_id"
/var/www/discourse/vendor/bundle/ruby/2.3.0/gems/rack-mini-profiler-0.10.5/lib/patches/db/pg.rb:90:in `async_exec'