A platform for community discussion. Free, open, simple.

Overview

Discourse is the 100% open source discussion platform built for the next decade of the Internet. Use it as a:

  • mailing list
  • discussion forum
  • long-form chat room

To learn more about the philosophy and goals of the project, visit discourse.org.

Screenshots

Boing Boing

Mobile

Browse lots more notable Discourse instances.

Development

To get your environment setup, follow the community setup guide for your operating system.

  1. If you're on macOS, try the macOS development guide.
  2. If you're on Ubuntu, try the Ubuntu development guide.
  3. If you're on Windows, try the Windows 10 development guide.

If you're familiar with how Rails works and are comfortable setting up your own environment, you can also try out the Discourse Advanced Developer Guide, which is aimed primarily at Ubuntu and macOS environments.

Before you get started, ensure you have the following minimum versions: Ruby 2.7+, PostgreSQL 13+, Redis 6.0+. If you're having trouble, please see our TROUBLESHOOTING GUIDE first!

Setting up Discourse

If you want to set up a Discourse forum for production use, see our Discourse Install Guide.

If you're looking for business class hosting, see discourse.org/buy.

If you're looking for our remote work solution, see teams.discourse.com.

Requirements

Discourse is built for the next 10 years of the Internet, so our requirements are high.

Discourse supports the latest, stable releases of all major browsers and platforms:

Browsers Tablets Phones
Apple Safari iPadOS iOS
Google Chrome Android Android
Microsoft Edge
Mozilla Firefox

Built With

  • Ruby on Rails — Our back end API is a Rails app. It responds to requests RESTfully in JSON.
  • Ember.js — Our front end is an Ember.js app that communicates with the Rails API.
  • PostgreSQL — Our main data store is in Postgres.
  • Redis — We use Redis as a cache and for transient data.
  • BrowserStack — We use BrowserStack to test on real devices and browsers.

Plus lots of Ruby Gems, a complete list of which is at /master/Gemfile.

Contributing

Build Status

Discourse is 100% free and open source. We encourage and support an active, healthy community that accepts contributions from the public – including you!

Before contributing to Discourse:

  1. Please read the complete mission statements on discourse.org. Yes we actually believe this stuff; you should too.
  2. Read and sign the Electronic Discourse Forums Contribution License Agreement.
  3. Dig into CONTRIBUTING.MD, which covers submitting bugs, requesting new features, preparing your code for a pull request, etc.
  4. Always strive to collaborate with mutual respect.
  5. Not sure what to work on? We've got some ideas.

We look forward to seeing your pull requests!

Security

We take security very seriously at Discourse; all our code is 100% open source and peer reviewed. Please read our security guide for an overview of security measures in Discourse, or if you wish to report a security issue.

The Discourse Team

The original Discourse code contributors can be found in AUTHORS.MD. For a complete list of the many individuals that contributed to the design and implementation of Discourse, please refer to the official Discourse blog and GitHub's list of contributors.

Copyright / License

Copyright 2014 - 2021 Civilized Discourse Construction Kit, Inc.

Licensed under the GNU General Public License Version 2.0 (or later); you may not use this work except in compliance with the License. You may obtain a copy of the License in the LICENSE file, or at:

https://www.gnu.org/licenses/old-licenses/gpl-2.0.txt

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Discourse logo and “Discourse Forum” ®, Civilized Discourse Construction Kit, Inc.

Dedication

Discourse is built with love, Internet style.

Issues
  • DEV: Prefabrication (test optimization)

    DEV: Prefabrication (test optimization)

    Whereas:

    let!(:user) { Fabricate(:user) }
    

    Creates a user object in the database for each test.

    prefabricate(:user) { Fabricate(:user) }
    

    Creates a user object in the database for each group of tests. These objects get cleaned up by virtue of being created in a transaction which is rolled back when the group completes.

    opened by danielwaterworth 58
  • following category on the category page

    following category on the category page

    I added a dropdown button on the category page where a logged in user can change the notification level of the category. latest_meta_topics_-_discourse

    opened by Catrin 32
  • Synced editor scrolling PoC.

    Synced editor scrolling PoC.

    Proof of concept for the synchronised source/preview scrolling in composer (see here: https://meta.discourse.org/t/syncing-the-editor-viewport-scroll/13249).

    This PR is probably not suitable for production - code is not fully optimised and there may be some not properly tested edge cases - but I'd like to hear your opinion if the approach I've used works ok before putting more time into polishing the code.

    opened by velesin 31
  • Improving search result blurb

    Improving search result blurb

    Problem

    Discourse blurb does not correlate with the Postgres methods used to index and search data.

    Solution

    This PR does the following:

    • Removes Ruby methods that build "blurbs" in search results. In place, harnessing powerful Postgres ts_headline to build better blurbs.
    • Removes unnecessary index data from raw_data fields (topic title) in posts, and topic indexes leaving search_data fields in current format
    • Improves result processing by using preprocessed raw_data
    • Removes blurb-length search option due to irrelevance in blurb calculations
    opened by jumbojett 29
  • FEATURE: Autocomplete support on search

    FEATURE: Autocomplete support on search

    • Improve advanced search parameter matching using ^ and $ where applicable
    • Added support for tag hash syntax in advanced search
    • Enable autocomplete of users, categories and tags in Advanced Search and the Search Menu
    opened by cpradio 27
  • Fix typo in AUTHORS.md

    Fix typo in AUTHORS.md

    opened by practicingruby 27
  • FEATURE: Make auth_redirect param options on user_api_keys

    FEATURE: Make auth_redirect param options on user_api_keys

    This is a possible solution for https://meta.discourse.org/t/user-api-keys-specification/48536/19 This allows for user-api-key requests to not require a redirect url. Instead, the encypted payload will just be displayed after creation ( which can be copied pasted into an env for a CLI, for example )

    opened by cfitz 27
  • FIX: allows the selection of the default landing tab

    FIX: allows the selection of the default landing tab

    Meta: Where does one select the default landing tab?

    Screenshot_17_03_13_00_01

    • [x] associates the / route to the first item in the top_menu site setting (1) in order to mark the right item in the menu as active when visiting the homepage
    • [x] prevents duplicate routes when the categories is the default landing page
    • [x] removed duplicate static routes declaration

    (1) my solution to retrieve the top_menu data from the site settings feels a bit hacky-ish. Unfortunately, I can't use the default PreloadStore API as it's a read-only-once structure and would delete its content.

    opened by ZogStriP 27
  • Quick access to bookmarks and messages on user menu.

    Quick access to bookmarks and messages on user menu.

    This is work in progress. For now, basic support for bookmarks has been implemented. I will continue with messages and then add styling. Any feedback is much appreciated.

    opened by nbianca 26
  • UX: Better placement for bulk select actions button

    UX: Better placement for bulk select actions button

    The bulk select action button is placed awkwardly on the right of the screen. This PR makes the table header for these lists sticky, and places that button there alongside the other buttons (toggling bulk select, select all, select none).

    Note that some plugins and themes use the bulk-select-button component, PRs incoming.

    Before (button visible on the far right, but table header missing on scroll)

    image

    After

    image
    opened by pmusaraj 0
  • PERF: Improve database query perf when loading topics for a category.

    PERF: Improve database query perf when loading topics for a category.

    Instead of left joining the topics table against categories by filtering with categories.id, we can improve the query plan by filtering against topics.category_id first before joining which helps to reduce the number of rows in the topics table that has to be joined against the other tables and also make better use of our existing index.

    The following is a before and after of the query plan for a category with many subcategories.

    Before:

                                                                                                           QUERY PLAN
    
    -------------------------------------------------------------------------------------------------------------------------------------
    -----------------------------------------------------------------------------------
     Limit  (cost=1.28..747.09 rows=30 width=12) (actual time=85.502..2453.727 rows=30 loops=1)
       ->  Nested Loop Left Join  (cost=1.28..566518.36 rows=22788 width=12) (actual time=85.501..2453.722 rows=30 loops=1)
             Join Filter: (category_users.category_id = topics.category_id)
             Filter: ((topics.category_id = 11) OR (COALESCE(category_users.notification_level, 1) <> 0) OR (tu.notification_level > 1))
             ->  Nested Loop Left Join  (cost=1.00..566001.58 rows=22866 width=20) (actual time=85.494..2453.702 rows=30 loops=1)
                   Filter: ((COALESCE(tu.notification_level, 1) > 0) AND ((topics.category_id <> 11) OR (topics.pinned_at IS NULL) OR ((t
    opics.pinned_at <= tu.cleared_pinned_at) AND (tu.cleared_pinned_at IS NOT NULL))))
                   Rows Removed by Filter: 1
                   ->  Nested Loop  (cost=0.57..528561.75 rows=68606 width=24) (actual time=85.472..2453.562 rows=31 loops=1)
                         Join Filter: ((topics.category_id = categories.id) AND ((categories.topic_id <> topics.id) OR (categories.id = 1
    1)))
                         Rows Removed by Join Filter: 13938306
                         ->  Index Scan using index_topics_on_bumped_at on topics  (cost=0.42..100480.05 rows=715549 width=24) (actual ti
    me=0.010..633.015 rows=464623 loops=1)
                               Filter: ((deleted_at IS NULL) AND ((archetype)::text <> 'private_message'::text))
                               Rows Removed by Filter: 105321
                         ->  Materialize  (cost=0.14..36.04 rows=30 width=8) (actual time=0.000..0.002 rows=30 loops=464623)
                               ->  Index Scan using categories_pkey on categories  (cost=0.14..35.89 rows=30 width=8) (actual time=0.006.
    .0.040 rows=30 loops=1)
                                     Index Cond: (id = ANY ('{11,53,57,55,54,56,112,94,107,115,116,117,97,95,102,103,101,105,99,114,106,1
    13,104,98,100,96,108,109,110,111}'::integer[]))
                   ->  Index Scan using index_topic_users_on_topic_id_and_user_id on topic_users tu  (cost=0.43..0.53 rows=1 width=16) (a
    ctual time=0.004..0.004 rows=0 loops=31)
                         Index Cond: ((topic_id = topics.id) AND (user_id = 1103877))
             ->  Materialize  (cost=0.28..2.30 rows=1 width=8) (actual time=0.000..0.000 rows=0 loops=30)
                   ->  Index Scan using index_category_users_on_user_id_and_last_seen_at on category_users  (cost=0.28..2.29 rows=1 width
    =8) (actual time=0.004..0.004 rows=0 loops=1)
                         Index Cond: (user_id = 1103877)
     Planning Time: 1.359 ms
     Execution Time: 2453.765 ms
    (23 rows)
    

    After:

                                                                                                                                QUERY PLAN
    ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
     Limit  (cost=1.28..438.55 rows=30 width=12) (actual time=38.297..657.215 rows=30 loops=1)
       ->  Nested Loop Left Join  (cost=1.28..195944.68 rows=13443 width=12) (actual time=38.296..657.211 rows=30 loops=1)
             Filter: ((categories.topic_id <> topics.id) OR (topics.category_id = 11))
             Rows Removed by Filter: 29
             ->  Nested Loop Left Join  (cost=1.13..193462.59 rows=13443 width=16) (actual time=38.289..657.092 rows=59 loops=1)
                   Join Filter: (category_users.category_id = topics.category_id)
                   Filter: ((topics.category_id = 11) OR (COALESCE(category_users.notification_level, 1) <> 0) OR (tu.notification_level > 1))
                   ->  Nested Loop Left Join  (cost=0.85..193156.79 rows=13489 width=20) (actual time=38.282..657.059 rows=59 loops=1)
                         Filter: ((COALESCE(tu.notification_level, 1) > 0) AND ((topics.category_id <> 11) OR (topics.pinned_at IS NULL) OR ((topics.pinned_at <= tu.cleared_pinned_at) AND (tu.cleared_pinned_at IS NOT NULL))))
                         Rows Removed by Filter: 1
                         ->  Index Scan using index_topics_on_bumped_at on topics  (cost=0.42..134521.06 rows=40470 width=24) (actual time=38.267..656.850 rows=60 loops=1)
                               Filter: ((deleted_at IS NULL) AND ((archetype)::text <> 'private_message'::text) AND (category_id = ANY ('{11,53,57,55,54,56,112,94,107,115,116,117,97,95,102,103,101,105,99,114,106,113,104,98,100,96,108,109,110,111}'::integer[])))
                               Rows Removed by Filter: 569895
                         ->  Index Scan using index_topic_users_on_topic_id_and_user_id on topic_users tu  (cost=0.43..1.43 rows=1 width=16) (actual time=0.003..0.003 rows=0 loops=60)
                               Index Cond: ((topic_id = topics.id) AND (user_id = 1103877))
                   ->  Materialize  (cost=0.28..2.30 rows=1 width=8) (actual time=0.000..0.000 rows=0 loops=59)
                         ->  Index Scan using index_category_users_on_user_id_and_last_seen_at on category_users  (cost=0.28..2.29 rows=1 width=8) (actual time=0.004..0.004 rows=0 loops=1)
                               Index Cond: (user_id = 1103877)
             ->  Index Scan using categories_pkey on categories  (cost=0.14..0.17 rows=1 width=8) (actual time=0.001..0.001 rows=1 loops=59)
                   Index Cond: (id = topics.category_id)
     Planning Time: 1.633 ms
     Execution Time: 657.255 ms
    (22 rows)
    
    opened by tgxworld 0
  • DEV: Add plugin outlet to the bottom of flag modal

    DEV: Add plugin outlet to the bottom of flag modal

    This will be used by discourse-akismet to show the current status of the Akismet scan (post marked as spam, not spam, etc).

    opened by udan11 0
  • FIX: Tests that depend on particular translations

    FIX: Tests that depend on particular translations

    I prefer to update tests to not depend on particular translations rather than include the translations, where possible.

    opened by eviltrout 0
  • FEATURE: Allow admins to permanently delete posts and topics

    FEATURE: Allow admins to permanently delete posts and topics

    Sometimes administrators want to permanently delete posts and topics from the database. To make sure that this is done for a good reasons, administrators can do this only after one minute has passed since the post was deleted or immediately if another administrator does it.

    What is left to do:

    • hide functionality under a site setting
    • change the interval from 1 minute to more
    • add client tests
    • add server tests
    opened by nbianca 0
  • DEV: Reuse can_invite_to_forum? in can_invite_to?

    DEV: Reuse can_invite_to_forum? in can_invite_to?

    This commit resolves refactors can_invite_to? to use can_invite_to_forum? for checking the site-wide permissions and then perform topic specific checkups.

    can_invite_to_forum? was never used with a parameter, so it was removed.

    Similarly, can_invite_to? is always used with a topic object and this is now enforced.

    There was another problem before when must_approve_users site setting was not checked when inviting users to forum, but was checked when inviting to a topic.

    Another minor security issue was that group owners could invite to group topics even if they did not have the minimum trust level to do it.

    opened by udan11 1
  • DEV: Automatically handle macOS readlink issues

    DEV: Automatically handle macOS readlink issues

    The Docker boot_dev script has a bug on macOS when using plugins: it attempts to invoke readlink -f, which works fine with GNU readlink but doesn't work with macOS readlink. (I reproduce the issue on macOS Big Sur 11.6, which is latest as of today.)

    The script on master includes a comment documenting how to work around the issue manually, using Homebrew to install coreutils, which installs a GNU version of readlink as greadlink. The comment then recommends symlinking readlink to greadlink so bare calls to readlink will use the GNU version instead of the macOS default version.

    That's a pretty weird thing to do to a machine just to satisfy this one script, and, anyway, it's a bummer that the script fails and that the end user has to manually follow directions in a comment to fix it.

    In this PR, I attempt to readlink -f the directory that we just created; if that fails, we create a one-liner Python script that does the same thing as readlink -f, and we use that, instead.

    I got the one-liner from https://stackoverflow.com/questions/1055671/how-can-i-get-the-behavior-of-gnus-readlink-f-on-a-mac … there are other implementations there, including a few pure-bash implementations, but they're kinda verbose; various replies warn that there are a lot of weird corner cases. The Python one-liner seems like the easiest way to handle it.

    (This infrastructure script has no tests, and I didn't add any.)

    opened by dfabulich 0
  • Add three reports

    Add three reports

    This PR adds the following reports requested on this PM:

    • Top Users by likes received
    • Top Users by likes received from a user with a lower trust level
    • Top Users by likes received from a variety of people
    opened by michebs 3
  • FIX: empty state message on the user bookmarks page

    FIX: empty state message on the user bookmarks page

    After adding an empty state banner to the user bookmarks page, we have found the bug. Steps to reproduce:

    1. Go to the user bookmarks page
    2. Search for something that doesn’t exist in bookmarks
    3. Click again Bookmarked on the sidebar or View All Bookmarks on the user menu again

    You'll see the empty state banner:

    412fa97284508d597ea3dbf7ef58a2a0cce135bd_2_1034x272

    This is the problem with routing, and it's hard to fix because of how this page is implemented. We're not loading the model in the model hook in the route, so when transition is happening ember calls the model hook, but the loading isn't happening.

    This PR removes code that load bookmarks from the ember model. I moved initial loading to the model hook in the route, and loading of additional bookmarks that is triggered when a user scroll down the page - to the controller. This fixes the bug, and it also will save us from problems in the future when touching this code or migrating to new Ember versions.

    :+1: OP to merge 
    opened by AndrewPrigorshnev 1
  • DEV: uses vanilla js for widget hooks

    DEV: uses vanilla js for widget hooks

    Note that this change also introduces an initialiser for widget hooks instead of calling it on each mount-widget

    opened by jjaffeux 2
Owner
Discourse
The 100% open source discussion platform built for the next decade of the Internet.
Discourse
Sharetribe Go is a source available marketplace software, also available as a hosted, no-code SaaS product. For a headless, API-first marketplace solution, check out Sharetribe Flex: https://www.sharetribe.com/flex.

Sharetribe Sharetribe develops advanced marketplace software for every business life cycle stage. Sharetribe Go gives you the complete feature set to

Sharetribe 2.2k Sep 24, 2021
Popcorn Time is a multi-platform, free software BitTorrent client that includes an integrated media player ( Windows / Mac / Linux ) A Butter-Project Fork

Popcorn Time A multi-platform, free software BitTorrent client that includes an integrated media player. Visit the project's website at popcorntime.ap

Popcorn Software 6.3k Sep 15, 2021
Open source API management platform

About Fusio is an open source API management platform which helps to build and manage REST APIs. Fusio provides all tools to quickly build an API from

Apioo 997 Sep 15, 2021
Predictive AI layer for existing databases.

Website | Docs | API Docs | Community forum MindsDB is an open-source AI layer for existing databases that allows you to effortlessly develop, train a

MindsDB Inc 3.9k Sep 17, 2021
Graphical program used to map keyboard buttons and mouse controls to a gamepad. Useful for playing games with no gamepad support

antimicro ?? Important update ?? This repo is currently unmaintained. The code hasn't been updated for a while. But not all is lost, antimicro has a f

null 1.5k Sep 24, 2021
An agile project planning tool

Fulcrum Fulcrum is an application to provide a user story based backlog management system for agile development teams. See the project page for more d

null 1.5k Aug 13, 2021
Helping to catalog, preserve and free the artifacts you need to produce music.

Musical Artifacts Helping to catalog, preserve and free the artifacts you need to produce music. Donate via Paypal Donate via Bitcoin Read the wiki Is

Lucas 60 Sep 3, 2021
A black hole for Internet advertisements

Network-wide ad blocking via your own Linux hardware The Pi-hole® is a DNS sinkhole that protects your devices from unwanted content, without installi

Pi-hole 32.5k Sep 17, 2021
Create agents that monitor and act on your behalf. Your agents are standing by!

What is Huginn? Huginn is a system for building agents that perform automated tasks for you online. They can read the web, watch for events, and take

Huginn 32.2k Sep 15, 2021
OpenProject is the leading open source project management software.

OpenProject OpenProject is a web-based project management software. Its key features are: Project planning and scheduling Product roadmap and release

OpenProject 5.1k Sep 15, 2021
NO LONGER MAINTAINED - Project management and time tracking should be easy. SprintApp is simple to setup, simple to use, and elegant - making you look like a hero in your organization.

SprintApp DEPRECATED This project has not seen any community contributions for a year now, and I have not had time for the project, or the need, for a

Matthew Millsaps-Brewer 304 Aug 12, 2021
Eventx

EventX What do you do when you have an event and all the event management applications available are too heavy but with little functionality to serve

Andela 20 Jun 29, 2019
🎧 Kaku is a highly integrated music player supports different online platform like YouTube, SoundCloud, Vimeo and more. Available on Mac, Windows and Linux.

Kaku Kaku is a highly integrated music player that supports different online platforms like YouTube, SoundCloud, Vimeo and more. Available on Windows,

Chia-Lung Chen 1k Sep 20, 2021
Virtual Mailbox Administration

ViMbAdmin Virtual Mailbox Administration The ViMbAdmin project (vim-be-admin) provides a web based virtual mailbox administration system to allow mail

Open Solutions 451 Aug 10, 2021
The Rails application that powers OpenStreetMap

"The Rails Port" This is The Rails Port, the Ruby on Rails application that powers the OpenStreetMap website and API. The software is also known as "o

OpenStreetMap on GitHub 1.4k Sep 20, 2021
A one-of-a-kind resume builder that keeps your privacy in mind. Completely secure, customizable, portable, open-source and free forever. Try it out today!

A free and open source resume builder. Go to App What is this app all about? Reactive Resume is a free and open source resume builder that’s built to

Amruth Pillai 3k Sep 12, 2021
A cross-platform tool for optimizing PNG and JPG files.

Made by @kilianvalkhof Other projects: ?? Polypane - Develop responsive websites and apps twice as fast on multiple screens at once ??️ Superposition

Kilian Valkhof 634 Sep 19, 2021
🔥 Open source static (serverless) status page. Uses hyperfast Go & Hugo, minimal HTML/CSS/JS, customizable, outstanding browser support (IE8+), preloaded CMS, read-only API, badges & more.

Über fast, backwards compatible (IE8+), tiny, and simple status page built with Hugo. Completely free with Netlify. Comes with Netlify CMS, read-only

cState 1.4k Sep 17, 2021