The backend powering Hack Club.
Switch branches/tags
add-1st-survey-of-2018-q1 add-2nd-survey-of-2018-q1 add-2nd-survey-of-Q1-2018 add-finder-to-cors add-notes add-print-and-download-buttons-for-workshops add-skylight add-waitlist-message-to-application-confirmation add-workshop-project-clicks add-workshops-to-frontend allow-applicant-deletion allow-updating-events athul-club-form athul-clubs bulckcah-alt-domain challenge-post-comment-email-notifications challenge-post-comments club-acceptance club-ownership configure-codeclimate convert-clubs-to-new-clubs deprecate-notify-interaction document-scheduled-jobs event-groups event-link-tracking extend-auth-expiration-to-3-days filter-submitted fix-athul-club-deletions fix-geocodeable-tests fix-heroku-scheduler fix-leader-check-ins-job-poc fix-schedule-leader-check-ins-job-string-literals fix-set-poc-bug fix-when-athul-report-email-is-sent flag-hackclub-addresses-as-spam get-new-leaders holiday-check-ins implement-admin-login implement-challenges implement-club-acceptance implement-events implement-new-app-rejection improve-athul-clubs improve-events install-coveralls leader-rollover leader-video-url-not-required master migrate-lecture-hall-to-frontend minor-application-improvements new-application-process new-slack-invites no-submit-twice remove-2nd-survey-of-2018-q1 remove-3rd-survey-of-2018-q1 remove-deprecated-fields-from-verification-email remove-events-check-in-questions remove-first-check-in-of-semester remove-leader-group-project remove-old-fields-from-email remove-parens-around-login-code-email remove-slack-username-from-intake-form remove-web revert-344-add-1st-survey-of-2018-q1 rubocop-upgrade server-render-workshop-pdfs skip-tasks-for-school-break snyk-fix-5cd08237 switch-to-sidekiq trigger-check-ins-for-India-clubs trunc_average_attendance update-api-gemfile update-dependencies update-funding-deals-schema update-gemfile upgrade-to-five-point-one validate-streak-syncing
Nothing to show
Clone or download
Latest commit c34d99d Dec 15, 2018
Type Name Latest commit message Commit time
Failed to load latest commit information.
.circleci Create V1 of sync script for Local Hack Day Nov 7, 2018
app Merge pull request #389 from hackclub/extend-auth-expiration-to-3-days Dec 15, 2018
bin Run rails app:update May 23, 2018
config Create V1 of sync script for Local Hack Day Nov 7, 2018
db Add unique constraints to User and NewLeader emails Nov 23, 2018
lib Capture screenshots if missing when submitting workshop projects Oct 28, 2018
log Move files out of ./api and into root May 10, 2018
public Move files out of ./api and into root May 10, 2018
spec 3 day -> 3 days Dec 15, 2018
.gitignore Move files out of ./api and into root May 10, 2018
.hound.yml Move files out of ./api and into root May 10, 2018
.rspec Move files out of ./api and into root May 10, 2018
.rubocop.yml Move files out of ./api and into root May 10, 2018
Aptfile Move files out of ./api and into root May 10, 2018
Dockerfile Move files out of ./api and into root May 10, 2018
Gemfile Replace Sentry with Bugsnag Jun 13, 2018
Gemfile.lock Update ffi to fix security vuln Oct 27, 2018
Guardfile Don't re-run request specs on route changes May 17, 2018
LICENSE Improve spacing May 27, 2018
Procfile Move files out of ./api and into root May 10, 2018 Replace Sentry with Bugsnag Jun 13, 2018
Rakefile Move files out of ./api and into root May 10, 2018 Move files out of ./api and into root May 10, 2018
docker-compose.yml Update docker-compose.yml May 10, 2018

Monolith icon


The backend powering Illustrated above.

CircleCI Skylight

Development Setup

Environment Variables

Create a file called .env. The following configuration options are available to set in it:

# Number of Rails threads to run per server instance. One database connection is
# made per thread (ex. if this is set to 5, then the database connection pool
# will hold 5 connections).

# Port to listen for HTTP requests on

# Environment to run Rails in (can be "development", "test", or "production")

# URL of Postgres instance to connect to. Rails will automatically connect to
# Docker Compose's instance of Postgres if this isn't set.

# API key for Google Maps geocoding API.
# You must also enable the timezone API in your Google Cloud account.
# Get a key from

# API key for Streak API. Must be an admin's key.

# Keys for application, club, leader, letter, and fundraising pipelines in Streak

# Name of team to put members of Hack Club into on Cloud9 & credentials for
# an account with access to that team.

# Keys for school and teacher outreach pipelines

# For Slack authentication

# For Slack invitation authentication ( (make sure this is an admin's legacy-token)

# For Slack stats authentication

# Default Slack team ID (probably going to be T0266FRGM, which is Hack Club's
# team)

# Secret code required when redeeming .tech domains

# The email of who to assign Streak tasks to

# Slack channel to mirror Hackbot interactions to

# Comma separated list of Slack user IDs that Hackbot should recognize as
# admins. User IDs can be from multiple Slack teams.

# Streak box to use for demo check-ins

# The API key for our giffing engine. Can be requested from,
# otherwise stealing the one from production will probably be find.

# Access token with all scopes enabled for the GitHub account to use as a bot.

# Credentials to a Stripe account

# A list of channel IDs (comma separated) of channels which should have all new messages deleted from them.

# Segment analytics

# SMTP settings for sending emails like application confirmations

# Auth Token used when receiving a POST request to create an Athul club

# HTTP auth to access Sidekiq's web interface

Build the container & install dependencies for runtime environment

$ docker-compose build
$ docker-compose run web bundle
$ docker-compose run web rails db:create db:setup

Run tests to ensure everything is working as expected:

$ docker-compose run web rails spec

Setting up the integrated Slack bot

  1. Create a new Slack app on Slack
  2. Create one (and only one) bot user and set "Always Show My Bot as Online" to "On"
  3. Click "Event Subscriptions" on the sidebar in the left and set the request URL to HOSTNAME/v1/hackbot/webhooks/events, replacing HOSTNAME with your actual hostname.
  4. Subscribe to the following bot events: message.channels,, message.groups, message.mpim
  5. Click "Interactive Messages" on the left sidebar and set the request URL to HOSTNAME/v1/hackbot/webhooks/interactive_messages, replacing HOSTNAME with your actual hostname.
  6. Manually go through the Oauth flow and POST code to /v1/hackbot/auth

Production Setup

Scheduled Jobs

This application depends on a few jobs running periodically in the background. Set this up using cron or a similar scheduler on your deployment of the application -- we use Heroku's scheduler in production.

  • rails heroku_scheduler:queue_update_hackbot_slack_username_job hourly
  • rails heroku_scheduler:queue_record_slack_stats_job daily
  • rails heroku_scheduler:queue_activate_clubs_job daily
  • rails heroku_scheduler:queue_collect_projects_shipped_job daily
  • rails heroku_scheduler:queue_schedule_leader_check_ins_job daily
  • rails heroku_scheduler:queue_handle_spam_club_applications_job every 10 minutes
  • rails heroku_scheduler:queue_update_from_streak_job hourly
  • rails heroku_scheduler:queue_close_check_ins_job daily

Deployment on Heroku

We use Heroku for managing our deployment of this project and that brings along some special caveats. Specifically, we rely on multiple buildpacks.

Here are the buildpacks that need to be configured (they must be in the given order):

Refer to for instructions on configuring buildpacks.


We use Skylight to profile the performance of our backend in production. To use it, you must set SKYLIGHT_AUTHENTICATION in the environment to the value that Skylight gives you.