Alchemy is the Open Source Rails CMS framework for the component based web that can be used as classic server side rendered or headless CMS.
906
stars
8,964
commits
Ruby
primary language
Sep 10, 2026
updated
Alchemy is an open source CMS engine written in Ruby on Rails.
Read more about Alchemy on the website and in the guidelines.
[!CAUTION] This main branch is a development branch that can contain bugs.
For productive environments you should use the current Ruby gem version, or the latest stable branch (8.0-stable).**
Visit the existing demo at https://demo.alchemy-cms.com/
demodemo123This version of AlchemyCMS runs with >= Rails 7.2
8.0-stable branch.7.4-stable branch.7.0-stable branch.6.1-stable branch.5.3-stable branch.4.5-stable branch.3.6-stable branch.3.1-stable branch.2.8-stable branch.2.1-stable branch.2.0-stable branch.1.6-stable branch.[!NOTE] For Rails
>= 8, use Alchemy version>= 8.0.0awhich comes with propshaft support. If you are on Rails>= 8with an older Alchemy version, you will need to temporarily comment out thepropshaftgem.
Alchemy runs with Ruby >= 3.1.0 including 4.0.
For a Ruby 3.0 compatible version use the 7.2-stable branch.
For a Ruby 2.4 compatible version use the 5.2-stable branch.
For a Ruby 2.2 compatible version use the 4.1-stable branch.
For a Ruby 2.1 compatible version use the 3.6-stable branch.
For a Ruby 2.0.0 compatible version use the 3.2-stable branch.
For a Ruby 1.9.3 compatible version use the 3.1-stable branch.
For a Ruby 1.8.7 compatible version use the 2.3-stable branch.
If you do not have a Rails project yet or just want to check out Alchemy, then use this Rails template.
Make sure you have Rails installed first:
$ gem install rails
Then create a new Rails project with:
$ rails new -m https://raw.githubusercontent.com/AlchemyCMS/rails-templates/master/all.rb <MY-PROJECT-NAME>
and follow the on screen instructions.
If you want to manually install Alchemy into your Rails project follow these steps.
Put Alchemy into your Gemfile with:
$ bundle add alchemy_cms
Now you have to decide, if you want to use your own user model or if you want to use the Devise based user model that Alchemy provides and was extracted into its own gem.
If you don't have your own user class, you can use the Alchemy user model. Just add the following gem into your Gemfile:
$ bundle add alchemy-devise
Then run the alchemy-devise installer:
$ bin/rails g alchemy:devise:install
In order to use your own user model you need to tell Alchemy about it.
The best practice is to use an initializer:
# config/initializers/alchemy.rb
Alchemy.configure do |config|
config.user_class = 'YourUserClass' # This has to be configured
config.current_user_method = 'current_admin_user' # Defaults to 'current_user'
config.signup_path = '/your/signup/path' # Defaults to '/signup'
config.login_path = '/your/login/path' # Defaults to '/login'
config.logout_path = '/your/logout/path' # Defaults to '/logout'
config.logout_method = 'http_verb_for_logout' # Defaults to 'delete'
config.unauthorized_path = '/some/public/page' # Defaults to '/'
end
Alchemy needs a alchemy_roles column in your database for the RBAC to work.
Alchemy provides a migration generator that adds these tables to your users table.
$ bin/rails g alchemy:user_columns_migration --table-name=my-users-table
Then include this module in your model.
class User
include Alchemy::UserMethods
end
Please follow this guide for further instructions on how to customize your user class even more.
After you set the user model you need to run the Alchemy install task:
$ bin/rails alchemy:install
Now everything should be set up and you should be able to visit the Alchemy Dashboard at:
*) Use your custom path if you mounted Alchemy at something else then '/'
Alchemy has very flexible ways to organize and manage content. Please be sure to read the introduction guide in order to understand the basic idea of how Alchemy works.
Beginning with Alchemy 3.1 we do not patch the ApplicationController anymore. If you have controllers that loads Alchemy content or uses Alchemy helpers in the views (i.e. render_menu or render_elements) you can either inherit from Alchemy::BaseController or you include Alchemy::ControllerActions in your controller (that's the recommended way).
By default, Alchemy Dashboard is accessible at http://example.com/admin. You can change this by setting Alchemy.admin_path and Alchemy.admin_constraints.
For example, these settings:
# config/initializers/alchemy.rb
Alchemy.admin_path = 'backend'
Alchemy.admin_constraints = {subdomain: 'hidden'}
will move the dashboard to http://hidden.example.com/backend.
Alchemy uses the Dragonfly gem to render pictures on-the-fly.
To make this as performant as possible the rendered picture gets stored into public/pictures so the web server can pick up the file and serve it without hitting the Rails process at all.
This may or may not what you want. Especially for multi server setups you eventually want to use something like S3.
Please follow the guidelines about picture caching on the Dragonfly homepage for further instructions:
http://markevans.github.io/dragonfly/cache
We also provide an extension for Cloudinary
Alchemy ships with one default English translation for the admin interface. If you want to use the admin interface in other languages please have a look at the alchemy_i18n project.
We, the Alchemy team, take upgrades very seriously and we try to make them as smooth as possible. Therefore we have build an upgrade task, that tries to automate the upgrade procedure as much as possible.
That's why after the Alchemy gem has been updated, with explicit call to:
$ bundle update alchemy_cms
you should always run the upgrader:
$ bin/rake alchemy:upgrade
Alchemy will print out useful information after running the automated tasks that help a smooth upgrade path. So please take your time and read them.
Always be sure to keep an eye on the output of your Rails app when starting. There will probably be useful information about deprecations.
Also, git diff is your friend.
The Alchemy upgrader comes prepared with several rake tasks in a specific order. This is sometimes not what you want or could even break upgrades. In order to customize the upgrade preparation process you can instead run each of the tasks on their own.
$ bin/rake alchemy:install:migrations
$ bin/rake db:migrate
$ bin/rake alchemy:db:seed
$ bin/rake alchemy:upgrade:config
$ bin/rake alchemy:upgrade:run
WARNING: This is only recommended, if you have problems with the default rake alchemy:upgrade task and need to
repair your data in between. The upgrader depends on these upgrade tasks running in this specific order, otherwise
we can't ensure smooth upgrades for you.
You can also run an individual upgrade on its own:
$ bin/rake -T alchemy:upgrade
provides you with a list of each upgrade you can run individually.
$ bin/rake alchemy:upgrade:4.1
runs only the Alchemy 4.1 upgrade
Alchemy has an official Capistrano extension which takes care of everything you need to deploy an Alchemy site.
Please use capistrano-alchemy, if you want to deploy with Capistrano.
If you don't use Capistrano you have to make sure that the uploads, tmp/cache/assets, public/assets and public/pictures folders get shared between deployments, otherwise you will loose data. No, not really, but you know, just keep them in sync.
On SQLite, a migration that rebuilds a table silently deletes data from other tables.
SQLite has no real ALTER TABLE, so Rails implements the operations below by recreating the table: it copies the rows aside, runs DROP TABLE, and copies them back.
change_columnchange_column_nullchange_column_defaultrename_columnremove_column and remove_columnsadd_timestampsadd_column with null: false and no default:With foreign keys enforced, SQLite's DROP TABLE performs an implicit DELETE, which fires ON DELETE CASCADE. The rebuilt table keeps its rows, because they come back from the copy, but every cascading descendant is deleted permanently. Since Alchemy cascades from pages down to ingredients, rebuilding alchemy_pages empties alchemy_page_versions, alchemy_elements and alchemy_ingredients.
Rails tries to prevent this by disabling foreign keys for the rebuild, but that only works outside a transaction, and migrations run inside one by default. The safeguard is therefore silently ineffective.
So when a migration touches a table that has cascading children:
add_column with both null: false and a default: is a plain ALTER TABLE ADD COLUMN. A nullable column combined with a model level default behaves the same on every adapter, and is the only option for MySQL text columns, which cannot carry a literal default.remove_column in down, declare disable_ddl_transaction! in the migration. Because it no longer rolls back as a single unit, make sure the migration is safe to run again after a partial failure.You can check the migrations in this repository with:
ruby bin/check-destructive-migrations
This also runs in CI, and fails when a migration rebuilds a table without disable_ddl_transaction!.
If you want to contribute to Alchemy (and we encourage you to do so) we have a strong test suite that helps you to not break anything.
First of all you need to clone your fork to your local development machine.
Using Docker (recommended):
$ docker compose build
$ docker compose up
This starts the Rails dev server, Sass watcher, and JS bundle watcher. The dev server is available at http://localhost:3000.
Local setup:
$ bin/setup
To prepare the tests of your Alchemy fork please make sure to run the preparation task:
$ bundle exec rake alchemy:spec:prepare
to set up the database for testing.
$ bin/rspec
Alternatively you can just run*:
$ bundle exec rake
*) This default task executes the database preparations and runs all defined test cases.
You can even start the dummy app and use it to manually test your changes.
To run the whole stack in Docker (builds the images and starts the Rails server, Sass watcher, and JS bundle watcher):
$ bin/start
After changing dependencies (Gemfile or package.json), rebuild the image and
refresh the baked node_modules in one step:
$ bin/start --refresh
Or, to run the dummy app locally without Docker:
$ bin/dev
There is a Rake task that helps you to release a new version of Alchemy.
$ bundle exec rake alchemy:release
[!NOTE] This will release a new patch level
If you want to release a new minor or major version you can do so by setting the VERSION environment variable accordingly.
$ bundle exec rake alchemy:release VERSION=X.Y.Z
If something goes wrong with the automated release task you can still release a new version manually.
Bump the version number in lib/alchemy/version.rb.
$ export GITHUB_ACCESS_TOKEN=...
$ PREVIOUS_VERSION=4.1.0 bundle exec rake alchemy:changelog:update
$ git commit -am "Bump version to vX.Y.Z"
This task will publish the ruby gem. It also tags the latest commit.
$ bundle exec rake release
PLEASE don't use the Github issues for feature requests. If you want to contribute to Alchemy please read the contribution guidelines before doing so.
This project exists thanks to all the people who contribute. [Contribute].
Thank you to all our backers! 🙏 [Become a backer]
Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [Become a sponsor]
If you like Alchemy, please help us to spread the word about Alchemy and star this repo on GitHub, upvote it on The Ruby Toolbox, mention us on Twitter.
That will help us to keep Alchemy awesome.
Thank you!
(top 30 of 109)
Ruby
63.0%
SCSS
15.8%
JavaScript
15.3%
HTML
5.7%
Alchemy is the Open Source Rails CMS framework for the component based web that can be used as classic server side rendered or headless CMS.
906
stars
8,964
commits
Ruby
primary language
Sep 10, 2026
updated
Alchemy is an open source CMS engine written in Ruby on Rails.
Read more about Alchemy on the website and in the guidelines.
[!CAUTION] This main branch is a development branch that can contain bugs.
For productive environments you should use the current Ruby gem version, or the latest stable branch (8.0-stable).**
Visit the existing demo at https://demo.alchemy-cms.com/
demodemo123This version of AlchemyCMS runs with >= Rails 7.2
8.0-stable branch.7.4-stable branch.7.0-stable branch.6.1-stable branch.5.3-stable branch.4.5-stable branch.3.6-stable branch.3.1-stable branch.2.8-stable branch.2.1-stable branch.2.0-stable branch.1.6-stable branch.[!NOTE] For Rails
>= 8, use Alchemy version>= 8.0.0awhich comes with propshaft support. If you are on Rails>= 8with an older Alchemy version, you will need to temporarily comment out thepropshaftgem.
Alchemy runs with Ruby >= 3.1.0 including 4.0.
For a Ruby 3.0 compatible version use the 7.2-stable branch.
For a Ruby 2.4 compatible version use the 5.2-stable branch.
For a Ruby 2.2 compatible version use the 4.1-stable branch.
For a Ruby 2.1 compatible version use the 3.6-stable branch.
For a Ruby 2.0.0 compatible version use the 3.2-stable branch.
For a Ruby 1.9.3 compatible version use the 3.1-stable branch.
For a Ruby 1.8.7 compatible version use the 2.3-stable branch.
If you do not have a Rails project yet or just want to check out Alchemy, then use this Rails template.
Make sure you have Rails installed first:
$ gem install rails
Then create a new Rails project with:
$ rails new -m https://raw.githubusercontent.com/AlchemyCMS/rails-templates/master/all.rb <MY-PROJECT-NAME>
and follow the on screen instructions.
If you want to manually install Alchemy into your Rails project follow these steps.
Put Alchemy into your Gemfile with:
$ bundle add alchemy_cms
Now you have to decide, if you want to use your own user model or if you want to use the Devise based user model that Alchemy provides and was extracted into its own gem.
If you don't have your own user class, you can use the Alchemy user model. Just add the following gem into your Gemfile:
$ bundle add alchemy-devise
Then run the alchemy-devise installer:
$ bin/rails g alchemy:devise:install
In order to use your own user model you need to tell Alchemy about it.
The best practice is to use an initializer:
# config/initializers/alchemy.rb
Alchemy.configure do |config|
config.user_class = 'YourUserClass' # This has to be configured
config.current_user_method = 'current_admin_user' # Defaults to 'current_user'
config.signup_path = '/your/signup/path' # Defaults to '/signup'
config.login_path = '/your/login/path' # Defaults to '/login'
config.logout_path = '/your/logout/path' # Defaults to '/logout'
config.logout_method = 'http_verb_for_logout' # Defaults to 'delete'
config.unauthorized_path = '/some/public/page' # Defaults to '/'
end
Alchemy needs a alchemy_roles column in your database for the RBAC to work.
Alchemy provides a migration generator that adds these tables to your users table.
$ bin/rails g alchemy:user_columns_migration --table-name=my-users-table
Then include this module in your model.
class User
include Alchemy::UserMethods
end
Please follow this guide for further instructions on how to customize your user class even more.
After you set the user model you need to run the Alchemy install task:
$ bin/rails alchemy:install
Now everything should be set up and you should be able to visit the Alchemy Dashboard at:
*) Use your custom path if you mounted Alchemy at something else then '/'
Alchemy has very flexible ways to organize and manage content. Please be sure to read the introduction guide in order to understand the basic idea of how Alchemy works.
Beginning with Alchemy 3.1 we do not patch the ApplicationController anymore. If you have controllers that loads Alchemy content or uses Alchemy helpers in the views (i.e. render_menu or render_elements) you can either inherit from Alchemy::BaseController or you include Alchemy::ControllerActions in your controller (that's the recommended way).
By default, Alchemy Dashboard is accessible at http://example.com/admin. You can change this by setting Alchemy.admin_path and Alchemy.admin_constraints.
For example, these settings:
# config/initializers/alchemy.rb
Alchemy.admin_path = 'backend'
Alchemy.admin_constraints = {subdomain: 'hidden'}
will move the dashboard to http://hidden.example.com/backend.
Alchemy uses the Dragonfly gem to render pictures on-the-fly.
To make this as performant as possible the rendered picture gets stored into public/pictures so the web server can pick up the file and serve it without hitting the Rails process at all.
This may or may not what you want. Especially for multi server setups you eventually want to use something like S3.
Please follow the guidelines about picture caching on the Dragonfly homepage for further instructions:
http://markevans.github.io/dragonfly/cache
We also provide an extension for Cloudinary
Alchemy ships with one default English translation for the admin interface. If you want to use the admin interface in other languages please have a look at the alchemy_i18n project.
We, the Alchemy team, take upgrades very seriously and we try to make them as smooth as possible. Therefore we have build an upgrade task, that tries to automate the upgrade procedure as much as possible.
That's why after the Alchemy gem has been updated, with explicit call to:
$ bundle update alchemy_cms
you should always run the upgrader:
$ bin/rake alchemy:upgrade
Alchemy will print out useful information after running the automated tasks that help a smooth upgrade path. So please take your time and read them.
Always be sure to keep an eye on the output of your Rails app when starting. There will probably be useful information about deprecations.
Also, git diff is your friend.
The Alchemy upgrader comes prepared with several rake tasks in a specific order. This is sometimes not what you want or could even break upgrades. In order to customize the upgrade preparation process you can instead run each of the tasks on their own.
$ bin/rake alchemy:install:migrations
$ bin/rake db:migrate
$ bin/rake alchemy:db:seed
$ bin/rake alchemy:upgrade:config
$ bin/rake alchemy:upgrade:run
WARNING: This is only recommended, if you have problems with the default rake alchemy:upgrade task and need to
repair your data in between. The upgrader depends on these upgrade tasks running in this specific order, otherwise
we can't ensure smooth upgrades for you.
You can also run an individual upgrade on its own:
$ bin/rake -T alchemy:upgrade
provides you with a list of each upgrade you can run individually.
$ bin/rake alchemy:upgrade:4.1
runs only the Alchemy 4.1 upgrade
Alchemy has an official Capistrano extension which takes care of everything you need to deploy an Alchemy site.
Please use capistrano-alchemy, if you want to deploy with Capistrano.
If you don't use Capistrano you have to make sure that the uploads, tmp/cache/assets, public/assets and public/pictures folders get shared between deployments, otherwise you will loose data. No, not really, but you know, just keep them in sync.
On SQLite, a migration that rebuilds a table silently deletes data from other tables.
SQLite has no real ALTER TABLE, so Rails implements the operations below by recreating the table: it copies the rows aside, runs DROP TABLE, and copies them back.
change_columnchange_column_nullchange_column_defaultrename_columnremove_column and remove_columnsadd_timestampsadd_column with null: false and no default:With foreign keys enforced, SQLite's DROP TABLE performs an implicit DELETE, which fires ON DELETE CASCADE. The rebuilt table keeps its rows, because they come back from the copy, but every cascading descendant is deleted permanently. Since Alchemy cascades from pages down to ingredients, rebuilding alchemy_pages empties alchemy_page_versions, alchemy_elements and alchemy_ingredients.
Rails tries to prevent this by disabling foreign keys for the rebuild, but that only works outside a transaction, and migrations run inside one by default. The safeguard is therefore silently ineffective.
So when a migration touches a table that has cascading children:
add_column with both null: false and a default: is a plain ALTER TABLE ADD COLUMN. A nullable column combined with a model level default behaves the same on every adapter, and is the only option for MySQL text columns, which cannot carry a literal default.remove_column in down, declare disable_ddl_transaction! in the migration. Because it no longer rolls back as a single unit, make sure the migration is safe to run again after a partial failure.You can check the migrations in this repository with:
ruby bin/check-destructive-migrations
This also runs in CI, and fails when a migration rebuilds a table without disable_ddl_transaction!.
If you want to contribute to Alchemy (and we encourage you to do so) we have a strong test suite that helps you to not break anything.
First of all you need to clone your fork to your local development machine.
Using Docker (recommended):
$ docker compose build
$ docker compose up
This starts the Rails dev server, Sass watcher, and JS bundle watcher. The dev server is available at http://localhost:3000.
Local setup:
$ bin/setup
To prepare the tests of your Alchemy fork please make sure to run the preparation task:
$ bundle exec rake alchemy:spec:prepare
to set up the database for testing.
$ bin/rspec
Alternatively you can just run*:
$ bundle exec rake
*) This default task executes the database preparations and runs all defined test cases.
You can even start the dummy app and use it to manually test your changes.
To run the whole stack in Docker (builds the images and starts the Rails server, Sass watcher, and JS bundle watcher):
$ bin/start
After changing dependencies (Gemfile or package.json), rebuild the image and
refresh the baked node_modules in one step:
$ bin/start --refresh
Or, to run the dummy app locally without Docker:
$ bin/dev
There is a Rake task that helps you to release a new version of Alchemy.
$ bundle exec rake alchemy:release
[!NOTE] This will release a new patch level
If you want to release a new minor or major version you can do so by setting the VERSION environment variable accordingly.
$ bundle exec rake alchemy:release VERSION=X.Y.Z
If something goes wrong with the automated release task you can still release a new version manually.
Bump the version number in lib/alchemy/version.rb.
$ export GITHUB_ACCESS_TOKEN=...
$ PREVIOUS_VERSION=4.1.0 bundle exec rake alchemy:changelog:update
$ git commit -am "Bump version to vX.Y.Z"
This task will publish the ruby gem. It also tags the latest commit.
$ bundle exec rake release
PLEASE don't use the Github issues for feature requests. If you want to contribute to Alchemy please read the contribution guidelines before doing so.
This project exists thanks to all the people who contribute. [Contribute].
Thank you to all our backers! 🙏 [Become a backer]
Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [Become a sponsor]
If you like Alchemy, please help us to spread the word about Alchemy and star this repo on GitHub, upvote it on The Ruby Toolbox, mention us on Twitter.
That will help us to keep Alchemy awesome.
Thank you!
(top 30 of 109)
Ruby
63.0%
SCSS
15.8%
JavaScript
15.3%
HTML
5.7%