crystal-api-starter

๐Ÿ’Ž Modern Crystal JSON API starter: Kemal, typed JSON, specs, Ameba linting and a static binary in a FROM scratch Docker image.

๐Ÿ’Ž crystal-api-starter

A modern JSON API starter for Crystal.
Ruby-like syntax, compiled speed, and a single static binary in a tiny `FROM scratch` Docker image.

CI Crystal 1.21 MIT license GitHub stars

What's inside

๐Ÿš€ Kemal Fast, Sinatra-style routing
๐Ÿงฑ Typed JSON JSON::Serializable models and request structs, validation with clear errors
๐Ÿ”’ Thread-safe store In-memory, mutex-guarded, easy to swap for Postgres or SQLite
๐Ÿงช Specs Request specs with spec-kemal
๐Ÿงน Linting Ameba + crystal tool format
๐Ÿณ Docker Static binary in a FROM scratch image
๐Ÿค– CI Format, lint, specs and Docker build on every push

Quick start

git clone https://github.com/stijnwtf/crystal-api-starter my-api
cd my-api
shards install
crystal run src/app.cr     # http://localhost:3000

Needs Crystal 1.21+ (brew install crystal).

$ curl -X POST localhost:3000/tasks -d '{"title":"Try Crystal"}'
{"id":1,"title":"Try Crystal","completed":false,"created_at":"2026-10-09T09:29:56Z"}

Commands

Command Does
make dev Run with auto-restart (watchexec)
make test Run specs
make lint Run Ameba
make format Format code
make build Optimized binary in bin/app
make docker Build the production image

API

Method Path Body Response
GET /health {"status","version"}
GET /tasks Task[]
GET /tasks/:id Task or 404
POST /tasks {"title"} 201 Task, 400 or 422
PATCH /tasks/:id {"title"?, "completed"?} Task, 404 or 422
DELETE /tasks/:id 204 or 404

Structure

src/
โ”œโ”€โ”€ app.cr            entry: config, JSON error handlers, server start
โ”œโ”€โ”€ store.cr          thread-safe in-memory store
โ”œโ”€โ”€ models/task.cr    Task model, request bodies, validation
โ””โ”€โ”€ routes/           one file per resource
spec/                 request specs

Add a resource: create src/models/thing.cr and src/routes/things.cr. Both folders are required with a glob, so no wiring needed.

Deploy

docker build -t my-api .
docker run -p 3000:3000 my-api

Configure the port with PORT (default 3000).

If this saved you time, a โญ๏ธ helps others find it.

License

MIT

Repository

crystal-api-starter

Owner
Statistic
  • 0
  • 0
  • 0
  • 0
  • 3
  • about 1 hour ago
  • October 9, 2026
License

MIT License

Links
Synced at

Fri, 09 Oct 2026 09:33:39 GMT

Languages