# RemoteRetro is a self-hostable real-time retrospective board for remote teams

> stride-nyc/remote_retro is the application code behind RemoteRetro.org, a free web app for running Agile retrospectives with distributed teams, written in Elixir and Phoenix with a React and Redux client and real-time updates over Phoenix channels. The interesting engineering is in the toolchain: a pruned Semantic UI build, a legacy OpenSSL flag on every webpack command, and a Google OAuth dependency you must supply yourself.

**stride-nyc/remote_retro** — Free, world-class retrospectives

- Repository: https://github.com/stride-nyc/remote_retro
- Website: https://remoteretro.org/
- Stars: 586 · Forks: 68
- Language: Elixir
- License: MIT
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/stride-nyc-remote-retro

## A free retrospective board for teams that cannot share a room

The repository houses the application code for RemoteRetro.org, a free web app that allows distributed teams to conduct Agile retrospectives. The audience is a team whose members are not in one place, which is the specific problem the tool takes on. A retrospective needs a shared board where observations are written down, grouped, discussed and voted on, and the usual offline version of that is a whiteboard in a room that half the team cannot reach. The application is written in Elixir and Phoenix on the server with React and Redux on the client, and the repository topics point at the mechanism that makes it work, with phoenix-channels, websockets and real-time listed alongside reactjs, redux and elixir. In other words, the board updates live as people type rather than on a save, which is what makes a text-based retrospective feel like a shared session. The project is sponsored by Stride Consulting, and the licence is MIT, so running your own instance of the software is a low-friction decision. The homepage is remoteretro.org, which is both the hosted application and the reason the source is published.

## A Phoenix app with a separately built asset pipeline

The file listing shows a standard Phoenix application with a decoupled front end. On the server side there is lib/, config/, priv/, rel/, test/ and mix.exs with mix.lock, along with a compile directory and a Procfile, which is the shape of an application that can be run on a platform that expects a release. On the front end there is web/ for the client code, package.json and yarn.lock, and a set of webpack configuration files, webpack.shared.config.js, webpack.dev.config.js, webpack.prod.config.js and webpack.dll.js, plus postcss.config.js and .babelrc for the asset build. The buildpack configuration files, elixir_buildpack.config, phoenix_static_buildpack.config and .buildpacks, show that the intended deployment path is a platform that builds Elixir and serves the static Phoenix assets. The .tool-versions file and .pairs file are small but telling, the first pinning tool versions for the version manager and the second being a pairing file for pair programming. The overall shape is a well-trodden Elixir deployment, and the parts that need attention are all in the asset build rather than in the Elixir code.

## Setting up PostgreSQL, asdf and the two databases

The development setup starts with PostgreSQL, and the README routes it through Homebrew on macOS. The commands are short:

```bash
brew install postgresql
createdb
createuser -s postgres
psql -h localhost
```

The two commented steps in the original sequence matter, since brew prints directions on successful installation that you are expected to follow, and the createuser step may not be needed depending on how PostgreSQL was installed. The last command confirms you can log in to the default database. The Elixir side uses the asdf version manager, and rather than listing versions by hand the repository ships install scripts, bin/install_erlang_and_elixir_with_dependencies and bin/install_node_with_dependencies, which install the toolchain and the Node dependencies respectively. Two databases are then created and migrated, one named remote_retro_dev and one named remote_retro_test, using mix ecto.create and mix ecto.migrate, with the test one run under the test environment. Once that is done the README says to start the Phoenix endpoint with mix, and the application is then reachable at localhost:4000. The port matters later, because the OAuth configuration is pinned to it.

## Google OAuth is a required step, not an optional one

Authentication within Remote Retro relies on Google OAuth and the Google+ API, and the README treats this as part of the setup rather than an option. The procedure is to create a project in the Google API console, then use the Credentials section to create an OAuth client ID of type Web application. The authorized JavaScript origin is http://localhost:4000 and the authorized redirect URI is http://localhost:4000/auth/google/callback, both pinned to the local development port. The resulting values go into the environment, and the variable names are explicit:

```bash
export REMOTE_RETRO_GOOGLE_OAUTH_CLIENT_ID="<Client Id>"
export REMOTE_RETRO_GOOGLE_OAUTH_CLIENT_SECRET="<Client secret>"
export REMOTE_RETRO_GOOGLE_OAUTH_REDIRECT_URI="http://localhost:4000/auth/google/callback"
```

The last step is to enable the Google+ API for the project. This is the sharpest constraint in the whole setup, and it is worth being clear-eyed about it. A team that cannot create Google Cloud credentials cannot run the application in its documented configuration, and the README does not describe an alternative sign-in method or a local-only authentication mode, so anything else would be your own work. It also means the redirect URI has to change for a deployed instance, and the README gives no guidance on that, which is the first thing to sort out when moving from localhost to a real domain.

## Webpack, a pruned Semantic UI and a legacy OpenSSL flag

The npm scripts are where this project is unusual, and they are worth reading before you build anything. Every webpack invocation is prefixed with NODE_OPTIONS=--openssl-legacy-provider, including the production compile, the test compile, the watch script and the dev server. That is a compatibility workaround for an older Node and webpack combination with a newer OpenSSL, and it is applied consistently because the toolchain is pinned rather than floated. Another script, prune-semantic-ui-to-used-selectors, runs PostCSS PurgeCSS over priv/static/css/semantic-ui/ to produce a purged stylesheet, and a postinstall hook calls bin/prepare_semantic_ui_for_consumption_by_phoenix, so a plain install prepares the CSS for the Phoenix asset pipeline. There is a second pruning path, reprune-semantic-ui-on-web-changes, that watches jsx and heex files with nodemon and re-runs the prune, which keeps the purged stylesheet in step with templates. The client tests run under mocha with the --exit flag and watch jsx extensions, and lint-staged runs eslint on js and jsx files at precommit. The package manager is pinned to yarn 1.22.22 with an integrity hash.

## Four ways to run the tests, and where CI runs them

The README documents four separate test entry points, which is unusual and reflects the split between an Elixir backend and a JavaScript client. The backend unit tests can be executed continuously on file change with mix test.watch, or manually with mix test. The end-to-end tests are run with mix e2e, a separate task from the unit tests. On the client side, the equivalent pair is yarn test:watch for continuous execution and yarn test for a manual run. The local eslint run has its own task, mix lint, which is notable because the linting of client code is driven from the Elixir side rather than from an npm script, so a developer working only in the client still needs the Elixir toolchain installed. Continuous integration runs on CircleCI, and there is a coverage badge pointing at coveralls, with coveralls.json in the repository root to configure the upload. The combination of a coverage service, a badge in the README and separate end-to-end tasks tells you the project treats the browser test suite as a first class part of the build rather than an afterthought.

## Running your own instance versus using the hosted app

The realistic alternative is the hosted service at remoteretro.org, and for most teams that is the better starting point, since the application is free and you can open a retrospective today. The difference in approach is about ownership of the moving parts. Using the hosted app means someone else runs the Phoenix application, the PostgreSQL database, the OAuth configuration and the asset build. Running it yourself means all four are yours, and the specific costs are visible in this repository. You need a PostgreSQL instance and a database per environment, a Google Cloud project with an OAuth client and the Google+ API enabled, a Node and yarn toolchain matching the pinned versions, and a build that can pass the OpenSSL legacy flag, which on a modern CI image may also need a newer Node than the one the project pinned. There is also the versioning question. The repository has no GitHub releases, so a deployment based on it tracks the master branch, and the last push was on 2026-10-19. The licence is MIT, so the code is easy to fork and rebrand, and the project accepts contributions through its contributing guidelines under the Contributor Covenant code of conduct.

## Conclusion

RemoteRetro suits a team that wants a retrospective board running on its own infrastructure, with live updates as people type, and that is prepared to maintain a Phoenix application, a PostgreSQL database and a Google OAuth client. It is unnecessary if the hosted app at remoteretro.org already meets your needs, and it is a poor base if your environment cannot run the pinned Node and webpack pipeline. Before deploying, check the Google OAuth and Google+ API setup, since the README treats it as a required step, and note the last push was on 2026-10-19 with no tagged releases, so you are tracking the master branch rather than a version.

## FAQ

### How do I run RemoteRetro locally?

Install PostgreSQL, create the remote_retro_dev and remote_retro_test databases and migrate them with mix ecto.create and mix ecto.migrate, install the toolchain with the scripts in bin/, set the Google OAuth environment variables, then start the Phoenix endpoint with mix and open localhost:4000.

### What does RemoteRetro need for authentication?

Authentication relies on Google OAuth and the Google+ API. You create an OAuth client ID of type Web application in the Google API console, register http://localhost:4000 as the authorized JavaScript origin and http://localhost:4000/auth/google/callback as the redirect URI, and then enable the Google+ API for the project.

### Which test commands does the RemoteRetro project provide?

The backend tests run with mix test.watch for continuous runs and mix test manually, end-to-end tests run with mix e2e, and the client tests run with yarn test:watch or yarn test. The local eslint run is mix lint, and CircleCI with a coveralls coverage badge runs the suite on every push.

### Why do the npm scripts set NODE_OPTIONS to the openssl legacy provider?

Every webpack command in package.json, including the production compile, the test compile, the watch script and the dev server, is prefixed with NODE_OPTIONS=--openssl-legacy-provider, and a separate postinstall hook prepares the pruned Semantic UI stylesheet for the Phoenix asset pipeline.

## Sources

- [Issues](https://github.com/stride-nyc/remote_retro/issues)
- [License: MIT](https://github.com/stride-nyc/remote_retro/blob/master/LICENSE)
- [Project website](https://remoteretro.org/)
- [README](https://github.com/stride-nyc/remote_retro/blob/master/README.md)
- [stride-nyc/remote_retro on GitHub](https://github.com/stride-nyc/remote_retro)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/stride-nyc-remote-retro
