Awesome Open Source
Awesome Open Source


Jet is an open source e-commerce framework for Amber / Crystal.

Current State

The base application is working and can be started.

Is Jet ready for non-development use? No, many things are missing, but progress is happening with a steady pace.


Code and Dependencies

Download Jet and take care of dependencies:

  1. git clone
  2. cd jet
  3. crystal deps
  4. crystal deps build amber
  5. crystal deps build micrate

Database Configuration

Jet uses two database users - admin user for management functions and password verification, and app user for runtime access to tables.

Admin User

  1. createuser -dlPrS jet_admin (run this as user "postgres")
  2. Copy "jet_admin" username and password into config/environments/development_admin.yml under "database_url" (the default is user "jet_admin", password "jet_admin")

App User

  1. createuser -DlPRS jet_www (run this as user "postgres")
  2. Copy "jet_www" username and password into config/environments/development.yml under "database_url" (the default is user "jet_www", password "jet_www")

Migrations and Seeds

Create database, run all migrations:

  1. AMBER_ENV=development_admin ./bin/amber db create
  2. AMBER_ENV=development_admin ./bin/amber db migrate

Load seeds and samples:

  1. AMBER_ENV=development_admin crystal db/ (you could also run AMBER_ENV=development_admin ./bin/amber db seed, but it won't print any debug output and so will appear as taking a long time to complete)
  2. AMBER_ENV=development_admin crystal db/


After the above has been executed without errors, please run:

  1. crystal src/ or amber watch
  2. And visit http://localhost:3000/ to see "It works!" along with app information

Design Goals

  1. Full-featured e-commerce platform for Amber / Crystal
  2. Focused on performance and quality
  3. Compatible with Shopify themes
  4. Powered by PostgreSQL database and Pg-specific features
  5. Completely correct database schema
  6. Secure user management - users can't download passwords table
  7. App-wide unique bigint IDs for all records
  8. All tables have standard set of fields (sort_order, visible, created_at, updated_at, deleted_at)
  9. Multi-tenant functionality out of the box
  10. As much code and logic as possible placed in existing software components (load balancer, Crystal, Amber, PostgreSQL) and the minimum necessary in Jet
  11. OAuth 2.0 and OpenAPI support

Usage Notes

Here follow various additional usage / design notes so that developers and users can get a quick sense of the application:

What's Where

Everything related to Amber is already grouped under the module Amber. Everything related to Jet is grouped under the module Jet.

Things that Jet needs to initialize only once (things like logger, embedded file system, precompiled template cache, and everything else that is constant and doesn't get re-created for every request) are kept in uppercase-named constants directly under Jet. Then, there are methods defined using the same name in lowercase to access them.

Typical example of e.g. Jet.logger:

module Jet
  class Logger


  def self.logger

Database Migrations, Seeds, and Samples

Database migrations are in db/migrations/ as expected. Database is created and migrations are run with ./bin/amber db create migrate.

"Seeds" (good data usually required for operation) is loaded using AMBER_ENV=development_admin crystal db/ If you do not want to pre-seed the database with all seeds, simply edit the mentioned file and remove some of the lines, or edit the actual seed files in db/seeds/ to add or remove entries that will be loaded into the database.

"Samples" (example data which makes the shop work out of the box, but which is typically not wanted in production environment) is loaded using AMBER_ENV=development_admin crystal db/ The same note for adding/removing samples applies as said above for seeds.

If you would like to initialize a production database without loading seeds and/or samples in bulk, the correct approach is to simply go through files db/ and db/ and load your own database content in the order shown there. Most probably you can go a long way by re-using the existing setup for loading the data — you just remove the seeds and samples that you do not need and add any additional ones that are needed.

User Model and Authentication

There are two user accounts used by Jet:

  1. The privileged user called "jet_admin" which owns all tables and functions, and which Jet is using when migrations or read-only data is being run. This user has all privileges on the created tables.
  2. The regular user called "jet" which Jet is using when accessing the database as a web application. This user only has the minimum necessary permissions on the tables, and also has permission to invoke a function to check user password.


It is envisioned that there would be a total of 3 logger-like objects in the application:

  1. The first one, and the only "real" logger in the application, is Amber.settings.logger (Amber also aliases it as Amber.logger` for convenience). This is the main logger which needs to be configured to select options, format, etc. In the logs, log lines coming from this logger are identified with name "Amber".
  2. Then there is a pass-through Jet.logger which simply forwards all its calls to Amber.logger, but automatically identifies itself as "Jet" in the logs. This is used by Jet's code.
  3. And then there is a pass-through user logger which also just forwards its calls to Amber.logger, but automatically identifies itself as "App-*" in the logs. This should be used by end user / app code.


To start contributing, please be familiar with Crystal Guide and Amber Introduction.

Then do:

grep -rP 'TODO|XXX' config db src spec

That will produce a list of entry-level, simple TODOs for new contributors.

Get A Weekly Email With Trending Projects For These Topics
No Spam. Unsubscribe easily at any time.
ecommerce (223
crystal (179
e-commerce (80
ecommerce-platform (58
commerce (27
storefront (24
multi-tenant (23