Build ambitious Rails apps
Monolith is a fullstack application development framework built on top of Rails that comes bundled with everything you need that make you an even more productive builder and operator of web applications including a component-first UI framework, a form builder that doesn’t need Strong Parameters, a RESTful routing and view helper library, a file based content management system like Middleman, and integration with payment and third-party authorization systems.
A great app starts with copy, not code
Before a single line of code is written for an application, you should write about it first. What is it? Why should people use it? How does it work?
Article(
title: "Build ambitious Rails apps",
){
Hero {
hgroup {
h1 { @title }
h2 { "A great app starts with copy, not code" }
}
a(href: "/", class: "btn btn-primary") { "Get started" }
}
Markdown %{
Monolith is a fullstack application development framework built on top of Rails that comes bundled with everything you need that make you an even more productive builder and operator of web applications.
Here's what you'll love about it:
1. It's a component-first UI framework
2. Building apps is productive, fun, and easy
3. It's built on Phlex, meaning it's highly customizable
}
}
Writing forces you to clarify your thinking of what’s really important. It’s also the easiest way for anybody to get started.
Ship it!
Once the landing page is complete its time to ship it! Ruby Monolith uses the dockerfile-rails
gem to create a Dockerfile that can be deployed to any Docker-ready host, like Fly.io.
Time for the database
After you’ve shipped your copy and you’re ready to start building your application, you add your database.
Quickly build application UI with Superview
Here’s what a typical controller looks like for a blog in Monolith. If you like how productive you feel building Sinatra applications, you’ll love how this feels.
class PostsController < ApplicationController
# This little DSL loads @posts from the logged in user.
assign :posts, from: :current_user
# Forms are concise, expressive, and highly customizable
# Phlex components.
class Form < ApplicationForm
def template
labeled field(:title).input.focus
labeled field(:publish_at).input
labeled field(:content).textarea(rows: 6)
submit
end
end
# View names correspond with what you'd expect from Rails resources.
class Index < ApplicationView
attr_writer :posts, :current_user
def title = "#{@current_user.name}'s Posts"
def template
# Tables can be abstracted away into components.
render TableComponent.new(items: @posts) do |table|
table.column("Title") { show(_1, :title) }
table.column do |column|
column.title do
link_to(user_blogs_path(@current_user)) { "Blogs" }
end
column.item { show(_1.blog, :title) }
end
end
end
end
class Show < ApplicationView
attr_writer :post
# Method names can be defined in subclasses, like title, that are
# picked up by the layout superclass to use in the HTML title tags
# or other areas outside of the view.
def title = @post.title
def subtitle = show(@post.blog, :title)
def template
table do
tbody do
tr do
th { "Status" }
td { @post.status }
end
tr do
th { "Publish at" }
td { @post.publish_at&.to_formatted_s(:long) }
end
tr do
th { "Content" }
td do
article { @post.content }
end
end
end
end
nav do
# Concicse link helpers bring sanity back to RESTful Rails applications.
edit(@post, role: "button")
delete(@post)
end
end
end
class Edit < ApplicationView
attr_writer :post
def title = @post.title
def subtitle = show(@post.blog, :title)
def template
render Form.new(@post)
end
end
private
def destroyed_url
@post.blog
end
end
When you’re satisified with the views, you can move them off to ./app/views/posts/index.rb
, ./app/views/posts/create.rb
, etc. and continue building your application.
Superform: an absurdly customizable form builder that permits its own parameters
The adage is that if you want to build great web apps, you need to get really good at working with forms.
Superforms makes that possible so you can create concise forms like this:
class Form < TailwindForm
def template
group "Post" do
labeled field(:title).input.focus
labeled field(:content).textarea(rows: 6)
end
labeled field(:publish_at).input
submit "Save Post"
end
end
And customize everything beneath it like this:
class TailwindForm < ApplicationForm
def labeled(component)
div "p-4" do
render component.field.label
render component
end
end
def group(title)
fieldset "p-8" do
legend { title }
yield
end
end
def submit(text)
input(type: "submit", value: "text")
end
end
The best part? You don’t have to jump around between templates, form builder objects, and configuration files. It’s all in one spot.
Actually that’s not the best part. Superform doesn’t need Strong Parameters, which is one less thing you have to worry about when you’re building your apps.
REST easy
Here’s what your config/routes.rb
looks like:
Rails.application.routes.draw do
resources :users, except: :destroy do
nest :blogs
create :session
end
resources :blogs do
nest :posts do
batch :delete, :publish, :unpublish
end
end
resources :posts
resources :sessions
root to: "blogs#index"
end
Remember when REST in Rails was as easy as link_to "Delete Post", method: :delete
before Hotwire arrived on scene? Don’t get me wrong, Hotwire is awesome, but we lost something when UJS was put out to pasture.
Restomatic includes route and view helpers that make REST fun again, so you can do this.
create(Post.new)
show(@post, :title)
edit(@post, :title)
delete(@post) { "Delete Post" }
Just say no to passwords
Let’s face it: passwords suck. The post-it notes your parents write them on and stick to their phones end up falling off, then they have to run through the password reset rigamrole.
Monolith replaces passwords with email login links, sign-in with Google, Apple, and Microsoft. No, it doesn’t use Passkeys because those will always be “just one year away”.
And no, it’s not OmniAuth. NoPassword implemented OAuth flows in Rails controllers which makes them easier to extend and plug into the routes.rb
file.
Upgrade existing Rails apps to Monolith
Monolith is a curated collection of Rails plugins. If you have an existing Rails app, you can upgrade it incrementally, gem-by-gem, and work your way to the productivity of Monolith.
Getting started
Install the Ruby Monolith gem.
gem install rubymonolith
Then create and launch new Monolith project.
monolith new my-first-app
cd my-first-app
bin/dev
This will create a Rails project, add Monolith to it, switch to the project directory, and boot the server. Just open the URL displayed on your console in the browser and it’s off to the races!
Existing Rails apps
If you’re adding Monolith to an existing Rails app, add the gem.
bundle add monolith
Then run the installer.
rails g monolith:install
That’s it!