KothariAPI Framework

Rails-style API framework for Crystal with JWT auth, migrations, and a full CLI

KothariAPI – Rails‑Style API Framework for Crystal

KothariAPI is a lightweight, Rails‑inspired API framework for Crystal.

It's built for fast JSON APIs with simple conventions:

  • CLI: kothari for generating apps, auth, scaffolds, etc.
  • Router DSL: KothariAPI::Router::Router.draw do |r| ... end.
  • Controllers: KothariAPI::Controller with JSON helpers and error helpers.
  • Models: KothariAPI::Model with SQLite + crystal-db for CRUD.
  • Auth: kothari g auth gives you User, JWT tokens, /signup and /login.

KothariAPI was created by Shaquel Kothari, founder of Traqr.

1. Requirements

On a typical Ubuntu server:

  • Crystal >= 1.0.0
  • SQLite
  • Boehm GC runtime (libgc.so.1) for Crystal binaries
  • Git

Install base dependencies (Ubuntu)

sudo apt-get update
sudo apt-get install -y crystal git
# Boehm GC runtime for Crystal
sudo apt-get install -y libgc1c2 || sudo apt-get install -y libgc1 libgc-dev

2. Installing the Kothari CLI (global)

KothariAPI is published as a public GitHub repo:

  • Repo: https://github.com/backlinkedclub/kothari_api

Clone and build the CLI:

cd ~
git clone https://github.com/backlinkedclub/kothari_api.git
cd kothari_api
# Install shard dependencies
shards install
# Build the CLI
crystal build src/cli/kothari.cr -o kothari

Move it into your PATH:

sudo mv kothari /usr/local/bin/kothari

Now you can run:

kothari

You should see the Kothari logo and a list of commands.

3. Using KothariAPI as a shard

KothariAPI is also a normal Crystal shard (shard.yml is configured correctly):

name: kothari_api
version: 0.1.0
description: |
  KothariAPI is a Rails-style API framework for Crystal with JWT auth, migrations, and a full CLI.
authors:
  - Shaquel Kothari
license: MIT
crystal: ">= 1.0.0"
dependencies:
  db:
    github: crystal-lang/crystal-db
  sqlite3:
    github: crystal-lang/crystal-sqlite3
  jwt:
    github: crystal-community/jwt
targets:
  kothari:
    main: src/cli/kothari.cr

Adding Kothari to an existing Crystal app

In your app's shard.yml:

dependencies:
  kothari_api:
    github: backlinkedclub/kothari_api
    version: ~> 0.1.0

Then:

shards install
shards build kothari    # produces ./bin/kothari

You can then use ./bin/kothari inside that project if you don't want a global install.

4. Creating a new Kothari app (auth + scaffold)

Below is the standard flow you can instruct Cursor AI to use on a new Ubuntu server.

4.1 Create the app

mkdir -p /var/apps
cd /var/apps
kothari new auth_app
cd auth_app
shards install

Generated shard.yml (important part):

dependencies:
  kothari_api:
    github: backlinkedclub/kothari_api
    version: ~> 0.1.0
targets:
  auth_app:
    main: src/server.cr

4.2 Generate auth (User + AuthController + routes)

kothari g auth user

This will:

  • Create app/models/user.cr with User < KothariAPI::Model and password hashing.
  • Create db/migrations/..._create_users.sql.
  • Create app/controllers/auth_controller.cr with:
    • POST /signup
    • POST /login
  • Register AuthController in KothariAPI::ControllerRegistry.
  • Add routes to config/routes.cr:
KothariAPI::Router::Router.draw do |r|
  r.get "/", to: "home#index"
  r.post "/signup", to: "auth#signup"
  r.post "/login", to: "auth#login"
end

4.3 Run DB migrations

kothari db:migrate

This creates the users table in db/development.sqlite3.

4.4 Generate a Post scaffold (example resource)

kothari g scaffold post title:string body:text
kothari db:migrate

This gives you:

  • app/models/post.cr (with table "posts" and fields title, body, created_at, updated_at).
  • app/controllers/posts_controller.cr for /posts CRUD JSON routes.
  • Routes added to config/routes.cr:
KothariAPI::Router::Router.draw do |r|
  r.get "/", to: "home#index"
  r.post "/signup", to: "auth#signup"
  r.post "/login", to: "auth#login"
  r.get "/posts", to: "posts#index"
  r.post "/posts", to: "posts#create"
end

5. Running the server in auth_app

From /var/apps/auth_app:

kothari server

This runs src/server.cr which:

  • Requires:
    • kothari_api
    • ./app/controllers
    • ./app/models
    • ./config/routes
    • http/server
  • Connects to db/development.sqlite3.
  • Uses KothariAPI::Router::Router.match + ControllerRegistry to dispatch to controller actions.

Visit:

  • http://localhost:3000/{"message":"Welcome to KothariAPI"}

6. HTTP examples for your Latimer app docs

These are the canonical examples you can show on latimer.traqr.co.uk to demonstrate a working Kothari app.

6.1 Signup

curl -s -X POST http://localhost:3000/signup \
  -H "Content-Type: application/json" \
  -d '{"email":"user@example.com","password":"password123"}'

Response (201):

{
  "token": "JWT_TOKEN_HERE",
  "email": "user@example.com"
}

6.2 Login

curl -s -X POST http://localhost:3000/login \
  -H "Content-Type: application/json" \
  -d '{"email":"user@example.com","password":"password123"}'

Response (200):

{
  "token": "JWT_TOKEN_HERE",
  "email": "user@example.com"
}

6.3 Create a post

curl -s -X POST http://localhost:3000/posts \
  -H "Content-Type: application/json" \
  -d '{"title":"Hello","body":"World"}'

Response (201):

{
  "errors": {},
  "title": "Hello",
  "body": "World",
  "created_at": "2025-11-24 03:33:55",
  "updated_at": "2025-11-24 03:33:55"
}

6.4 List posts

curl -s http://localhost:3000/posts

Response (200):

[
  {
    "errors": {},
    "title": "Hello",
    "body": "World",
    "created_at": "2025-11-24 03:33:55",
    "updated_at": "2025-11-24 03:33:55"
  }
]

6.5 404 example

curl -s -X POST http://localhost:3000/does_not_exist \
  -H "Content-Type: application/json" \
  -d '{}'

Response (404):

{"error":"Not Found"}

7. Console and Benchmark

7.1 Kothari console

From inside an app (e.g. auth_app):

kothari console
  • help → prints available commands.
  • models → lists registered models (User, Post).
  • User.all, Post.all, etc., via the console DSL described in console.cr.

7.2 Benchmark

In one terminal:

cd /var/apps/auth_app
kothari server

In another:

cd /var/apps/auth_app
kothari benchmark
  • Checks that the server is running on http://127.0.0.1:3000.
  • Runs a simple GET-based performance benchmark against /.
  • Prints throughput and latency stats.