Skip to content

ibonn/tatami

Repository files navigation

Tatami Logo

Build Status Docs Status PyPI - Downloads PyPI - Version


The clean, modular Python web floorplan.

Tatami is a minimal, convention-powered web framework that builds your application from the ground up — guided by your directory structure, not boilerplate or ceremony.

Like traditional tatami mats that structure a Japanese room, Tatami lets you define the shape and flow of your web app naturally, simply by laying things out.


✨ Features

  • 🔁 Automatic routing from file and folder structure
  • 📦 Service injection via convention
  • 🧩 Auto-loaded middleware, templates, and static assets
  • 📖 Live OpenAPI docs (ReDoc, Swagger, RapiDoc)
  • 🧠 Auto-generated endpoint documentation from docstrings and README
  • Zero-config startup — just run your app directory

🚀 Quick Start

pip install tatami

Create a new project:

tatami create myproject

Run your project:

tatami run myproject

Your API will be available at http://localhost:8000 with automatic docs at /docs/swagger.

🧠 Philosophy

Tatami is designed for:

  • Structure-first design: Routes and services emerge from file layout.
  • Simplicity: Eliminate configuration and glue code.
  • Alignment: Your docs, code, and architecture reflect each other.

It's like FastAPI and Flask had a minimalist, Spring Boot-inspired child.

📚 Documentation

You can access the whole documentation for Tatami here

By the way, Tatami automatically generates your application’s documentation at the following endpoints:

  • /openapi.json - OpenAPI specification
  • /docs/swagger - Swagger UI
  • /docs/redoc - ReDoc
  • /docs/rapidoc - RapiDoc

🔌 Example

Using decorators (recommended):

from tatami import get, post, router
from pydantic import BaseModel

class User(BaseModel):
    name: str
    age: int

class Users(router('/users')):
    @get('/')
    def list_users(self):
        """Returns all users in the system."""
        return [{"id": 1, "name": "Alice", "age": 30}]

    @post('/')
    def create_user(self, user: User):
        """Creates a new user."""
        return {"message": f"Created user {user.name}"}

    @get('/{user_id}')
    def get_user(self, user_id: int):
        """Get a specific user by ID."""
        return {"id": user_id, "name": "Alice", "age": 30}

Using convention-based routing:

# In routers/users.py
class Users:
    def get_users(self):
        """List all users"""
        return [{"id": 1, "name": "Alice"}]
    
    def post_user(self, user: User):
        """Create a new user"""
        return {"created": user.name}

This automatically creates:

  • GET /users/
  • POST /users/
  • GET /users/{user_id}

...with full OpenAPI schemas generated automatically.

🌱 Still Early

Tatami is experimental. Expect breaking changes, rapid iteration, and exciting ideas.

Contributions, feedback, and issue reports are more than welcome.

About

The clean, modular Python web floorplan

Topics

Resources

License

Stars

1 star

Watchers

0 watching

Forks

Contributors