Edward Loveall

A Week with Lucky

A little over a week ago, thoughtbot announced they were building a new web framework called Lucky. It’s built with Crystal just as Rails is built with Ruby. Its goals are best summed in the description of the main repository:

Catch bugs early, forget about most performance issues, and spend more time on code instead of debugging and writing tests.

I’ve now spent about a week with Lucky building a test app and I’ll talk about what I’ve found here. As a professional Rails developer, I’ll be comparing it most to Rails. There are some stark, and welcome, differences. This isn’t just Crystal on Rails.


First Crystal, the language that built Lucky. It bills itself as a type-safe, very performant alternative to Ruby and the likeness to Ruby is strong. You can take a look at their tutorials or even see the distinctions to Ruby in their Crystal for Rubyists document. TL;DR: if you’re comfortable with Ruby, it won’t take you long to learn much of Crystal.

Actions instead of Controllers

Rails uses controllers which contain multiple actions. Lucky splits everything up into individual actions. This likely has many advantages that I haven’t discovered yet, but one is now you can link directly to an action class:

link "Topics", to: Topics::Index

You can see this in…

Pages instead of Views

Pages are still largely being worked on and will likely go through many changes. One big separation from Rails is all of the page source is written with Crystal, not a templating language like ERB. I imagine this helps keep the views pretty fast as they are now complied along with the rest of the app. It also allows the framework to force developers to identify exactly what the view needs from the action.

Update: Crystal has its own equivalent to ERB called ECR. There’s also something similar to Slim called Slang. Thanks to Isaac Sloan for pointing this out!

For example, the view linked above has two needs declarations at the top. Every time the app renders this page (topics/index_page.cr) it must specify a topics object of type TopicQuery and a vote_form of type VoteForm. No more rendering views with critical dependencies missing!

Models haven’t gone anywhere

Models, along with migrations, are still the preferred pattern to generate and encapsulate data. The biggest differences are models are tiny and type-safe. You specify which fields (attributes) are required and which are optional. These get enforced not only with validations but at the database level too.

In this migration, title has a not-null constraint in the database. description, however, is nilable and doesn’t get that restriction. It forces you as a developer to think about what you’re adding and if it’s required.


Queries to me feel like they’re an extension of models. Instead of cramming all of your scopes and state checking into a model class, you can break that out into a query class. In the linked query object here, you can see a newest_first method that sorts queries by their created_at date in descending order.


I feel like of all the parts of Lucky, I understand forms the least. Talking to the creator, Paul Smith, they are still very much in flux. Forms are where you define validations. Previously, when I was mentioning how migrations can specify which columns have an automatic not-null constraint in the database, they also get an automatic required validation.

Breaking traditional Rails models into Lucky’s models, queries, and forms I think will serve it well in the long run.


Lucky is all-in on using yarn (with node) to manage assets. Rails put a lot of work into making yarn the default asset manager, and this is after 10 years of its asset pipeline. I think this is exactly the right thing to do.

As a side note, Lucky ships with PostCSS by default, something I hadn’t heard of or worked with before. It’s not quite a pre-processor for CSS. If you’re curious about it, I found these articles to be helpful.

Lucky seems promising. I’m excited to see how it evolves and what new community patterns develop around it. Crystal is a joy to work with while type-safe languages are in style.

While it’s not ready for prime-time, it’s worth spending a quick weekend on to see what it can do. You can use my project’s commits as a guide on how to build an app step by step or check out Lucky’s guides which are being added rapidly.

It’s very exciting to be at the dawn of a framework. Lucky has a lot of potential. I hope you’ll check it out.