← Home // Published 2nd June, 2025
AttendList is an attendance tracker for Google Meet. It's built on a Ruby on Rails backend that talks to a Chrome Extension.
This article explores the infrastructure and gem choices I've made while building AttendList, from the basics like background jobs, auth and blogging, to deployment and some fun extras.
Table of contents:
gem "pg" # database
gem "redis" # cache
gem "sidekiq" # background jobs
gem "rspec-rails" # testing
gem "factory_bot_rails" # test data
AttendList's core stack is pretty vanilla — it uses PostgreSQL for the database, Redis for caching and job queues, and Sidekiq for background jobs.
This is the stack I use for all my side-projects. It's rock-solid, reliable and cheap to host.
I veer slightly off the "Rails way" with RSpec & factories for tests, but that's just a preference thing.
gem "devise" # Auth
gem "activerecord-session_store" # Session storage
gem "omniauth-rails_csrf_protection" # Make Oauth and Devise play together nicely
gem "omniauth-google-oauth2" # Support "login with Google"
gem "pretender" # Devise impersonation
An AttendList user logs in through a Devise login flow via Google OAuth.
AttendList then asks users to re-auth with Google to connect Google Meet (ie: grant necessary scopes), via an incremental authorization flow. It's an auth style that Google encourages where you initially only request the minimal scopes from a user (ie: name & email), then re-request more scopes as needed.
An incremental auth flow with Devise looks a bit like this:
button_to(user_google_oauth2_omniauth_authorize_path(
scope: "...",
prompt: "consent",
include_granted_scopes: "true",
login_hint: current_user.email,
), data: { turbo: false }) do
>>> Connect Google Meet <<<
end
This prompts a user to OAuth again via Google — thereby granting additional scopes — after they've initially logged in.
Finally, I use the Pretender gem to login as different users within AttendList, for support & debugging.
gem "tailwindcss-rails" # use TailwindCSS
gem "view_component" # better version of partials
gem "rails_icons" # easily use various icon libraries
I've been a big fan of ViewComponent for years now, and I use them heavily in all my apps. I've written about ViewComponents before; they plug in very neatly to the standard Rails stack, feel excellent to work with and are a huge step up from regular partials.
For styling, I use Tailwind CSS. It helps me style UIs extremely quickly, and it plays nicely with Rails and ViewComponent.
I lean heavily on TailwindUI for UI components, and pair it with the Phosphor icon library (via the rails_icons gem gem). I previously defaulted to Heroicons for icons, but Phosphor has vastly more icons available.
gem "rack-mini-profiler" # Page rendering insights, SQL counts etc
gem "bullet" # Automatically alerts for N+1 queries
I use the Bullet gem to catch N+1 queries, and combine it with rack-mini-profiler to keep an eye on performance. Both are handy and painless to setup.
I only run these gems in the development
environment, but I saw recently that Campsite used to run rack-mini-profiler in production, which I might look into.
gem "googleauth"
gem "google-apps-meet-v2"
gem "google-apis-people_v1"
Google has a bunch of Ruby client libraries, and I use these three for AttendList.
There's not much to say here — they work fine; they're auto-generated, so they can feel a bit clunky to use, but it's not too bad.
gem "redcarpet" # markdown parsing
gem "rouge" # code highlighting
gem "sitemap_generator" # sitemap builder
gem "front_matter_parser" # parse frontmatter from .md files
I've rolled my own blogging system for AttendList.
Its cornerstone is the Redcarpet gem. Redcarpet powers all the markdown rendering, which I pipe through a Tailwind CSS prose
class to neatly format each blog post.
I pair Redcarpet with Rouge for code highlighting (like above), using the included plugin for Redcarpet and the base16.solarized.light
theme (preview other themes).
I also use the Sitemap Generator gem to create an XML sitemap, and front-matter-parser to extract data from each post, like the title & published_at date.
I use Hatchbox to deploy AttendList and host on servers from Hetzner.
Hetzner is absurdly good value — I'm using a single CAX31
instance, with 8 vCPU
cores, 16 GB
of RAM, 160 GB
of storage and 20 TB
of bandwidth... for US $15.50/mo
🤯.
Hatchbox costs $10/mo
on top, but it's worth it. It eliminates deployment headaches and automatically configures the server, updates it, deploys new builds from GitHub, handles my domain names, SSL and much more.
gem "blazer" # Dashboards & queries
gem "ahoy_matey" # Product analytics
gem "rails_charts" # Charts (bar, line, pie etc.)
gem "annotate" # Annotate models, specs etc
gem "honeybadger" # Monitoring
gem "loops_sdk" # Email marketing
Here are a couple of handy extra gems I use in AttendList:
I hope you found this short article interesting!
Despite being an early-stage app, AttendList still has a lot of moving parts; I hope this look under the hood was insightful.