The only thing better than a Matcha latte is a match made in Ruby.
This is a fully-documented, TDD-driven Sinatra API for the Matcha dating platform. It’s modular, dockerized, and optimized for love at first request 💘
| Layer | Tech |
|---|---|
| Framework | Sinatra (modular style) |
| Language | Ruby 3.2 |
| Database | PostgreSQL 14 |
| Persistence | Raw SQL + SQLHelper |
| Auth | JWT (handrolled) |
| Container | Docker + Compose |
| Testing | RSpec + Rack::Test |
| Docs | api_doc DSL (custom) |
| Console | IRB via bin/console |
| Tasks | Rake + Makefile |
- 🔐 Authentication: Email/password & social (Google, Facebook, Snapchat)
- 🧪 TDD-first with RSpec specs for everything
- 🧼 Clean architecture: Helpers, controllers, and models separated
- 🔒 JWT-based sessions (no gem dependencies)
- 🧠 Robust validation with reusable DSL-based
Validator - 🌍 RESTful routes:
/auth,/me,/users/:username, etc. - 🚫 Ban & Confirm logic: No banned or unconfirmed user can access the API
- 💾 Smart SQL helper:
SQLHelper.create,update,find_by, etc. - 🧾 API docs: Exportable via
make docs - 🐳 Fully dockerized
- 💬 Friendly, readable logs
.
├── app/
│ ├── controllers/ # Modular Sinatra apps (AuthController, UsersController)
│ ├── helpers/ # Validators, SQLHelper, Request parsing, Auth, Database
│ ├── models/ # Models (User, ...)
│ ├── lib/ # Shared error classes, doc
├── config/
│ └── database.yml # Database settings
│ └── environment.rb # Loads everything
├── db/
│ ├── migrate/ # DB migrations
│ └── seeds.rb # (optional)
├── spec/ # RSpec suite
├── docker-compose.yml
├── Rakefile
├── Makefile
├── .env
├── config.ru
└── README.md
Visit the Postman Colleciton to run all the API endpoints.
git clone https://github.com/pulgamecanica/matcha
cd matcha
# Build containers
make buildRSpec tests live in spec/, with:
- Integration tests for endpoints
- Unit tests for helpers
- Full TDD on auth, validation, sessions, and core models
make testmake create # db:create
make migrate # db:migrate
make seed # db:seed
make test # run all specs (you can provide a file)
make console # open IRB console
make logs # see the docker logs
make docs # export route documentation
make re_db # recreate database (empty)
make seed # generate database and seed dataStateless JWT (no libraries!) via SessionToken.
SessionToken.generate(user_id) # => "encoded.jwt.token"
SessionToken.decode(token) # => { "user_id" => 42, ... }Each route is documented inline with the api_doc DSL.
To export to markdown:
make docs➡ Output: docs/exported.md
Example:
api_doc "/auth/register", method: :post do
description "Register a new user"
param :email, String, required: true
param :username, String, required: true
param :password, String, required: true
response 201, "User created"
endVisit the API Colleciton to see all the API endpoints.
- JWT session system
- Login, Register, Social Auth
- Patch & Delete
/me - Ban, confirm & protect endpoints
- Public profiles
/users/:username - API Docs via DSL
- Validation system
- SQLHelper abstraction
- Tag system
- Connections, Likes
- Notifications
- Commonly used English words should not be accepted as passwords.
- If user unlikes, make sure to delete connection. (cascades all connection relationships such as messages).
- Limit up to 5 pictures.
- Real-time messaging (WebSocket or polling)
- Limit actions if user does not have a profile picture set: [connection is not possible]
- Notification when "matching" for the other user
- Add city and country to the user
- Email acitons (confirm register / reset password)
- VideoCalls
- Report account as fake
- Deploy with NGINX
📜 Everything documented
🧪 Everything tested
🚫 No unhandled JSON
💥 No silent failures
💎 Code should read like Ruby poetry