https://github.com/sembeimx/nori
A batteries-included async Python web framework built on Starlette and Tortoise ORM.
https://github.com/sembeimx/nori
async jinja2 mvc python starlette tortoise-orm web-framework
Last synced: 13 days ago
JSON representation
A batteries-included async Python web framework built on Starlette and Tortoise ORM.
- Host: GitHub
- URL: https://github.com/sembeimx/nori
- Owner: sembeimx
- License: mit
- Created: 2026-04-06T06:21:59.000Z (about 1 month ago)
- Default Branch: main
- Last Pushed: 2026-04-27T07:09:36.000Z (16 days ago)
- Last Synced: 2026-04-27T07:23:24.023Z (16 days ago)
- Topics: async, jinja2, mvc, python, starlette, tortoise-orm, web-framework
- Language: Python
- Homepage: https://nori.sembei.mx
- Size: 642 KB
- Stars: 1
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
- Security: docs/security.md
- Roadmap: docs/roadmap.md
- Agents: AGENTS.md
Awesome Lists containing this project
README
# Nori
[](https://github.com/sembeimx/nori/actions/workflows/tests.yml)
[](LICENSE)
[](https://www.python.org)
[](https://github.com/sembeimx/nori/releases)
**The async Python framework where server-rendered pages and JSON APIs are first-class peers.**
Built on Starlette and Tortoise ORM. Nori is for apps that live in both shapes at once — a SaaS dashboard with an HTMX UI and a JSON endpoint for the mobile client, an admin panel and a public API, a marketing site and a webhook handler. One auth system, one ORM, one validation layer, one testing setup. Nothing to stitch together.
---
## Quick Start
> **Platform**: Nori is tested on Linux and macOS. Windows users should run inside [WSL2](https://learn.microsoft.com/en-us/windows/wsl/install).
```bash
curl -fsSL https://nori.sembei.mx/install.py | python3 - my-project
cd my-project
source .venv/bin/activate
python3 nori.py migrate:init # one-time: generate framework + user tables for your engine
python3 nori.py serve
```
Open `http://localhost:8000`.
The installer pulls the latest release, copies only what belongs in a fresh project (no framework dev artifacts), creates a `.venv`, installs dependencies, copies `.env`, and runs `git init`. Pass `--no-venv` or `--no-install` to opt out, or `--version 1.10.0` to pin a release.
> **Contributing to Nori itself?** Clone the repo: `git clone https://github.com/sembeimx/nori.git`. The installer is for project creation, not framework development.
### Configuration (.env)
**SQLite** (quickest for development):
```env
DEBUG=true
SECRET_KEY=my-secret-key
DB_ENGINE=sqlite
DB_NAME=db.sqlite3
```
**MySQL / PostgreSQL:** see the [deployment guide](https://nori.sembei.mx/deployment/).
### Docker
```bash
cp .env.example rootsystem/application/.env
# Set DB_ENGINE=mysql and DB_HOST=db in .env
docker compose up -d --build
```
---
## CLI
All commands run from the project root. Built-in commands live in `core/cli.py` (updated with `framework:update`). Custom commands go in `commands/*.py` — they survive updates.
| Command | Description |
|---------|-------------|
| `python3 nori.py serve` | Dev server with hot reload |
| `python3 nori.py shell` | Async REPL with Tortoise + registered models loaded |
| `python3 nori.py make:controller Name` | Scaffold a controller |
| `python3 nori.py make:model Name` | Scaffold a model |
| `python3 nori.py make:seeder Name` | Scaffold a seeder |
| `python3 nori.py migrate:init` | Initialize migration system |
| `python3 nori.py migrate:make ` | Create a migration |
| `python3 nori.py migrate:upgrade` | Run pending migrations |
| `python3 nori.py migrate:downgrade` | Roll back last migration |
| `python3 nori.py db:seed` | Run database seeders |
| `python3 nori.py queue:work` | Start the job queue worker |
| `python3 nori.py audit:purge` | Purge old audit log entries |
| `python3 nori.py framework:update` | Update Nori core from GitHub |
| `python3 nori.py framework:version` | Show current version |
---
## Project Structure
```
nori/
├── nori.py ← CLI bootstrap (delegates to core/cli.py)
├── requirements.txt
├── tests/
└── rootsystem/
├── static/ ← CSS, JS, images
├── templates/ ← Jinja2 views
└── application/
├── asgi.py ← ASGI entry point and middleware stack
├── settings.py ← Configuration via environment variables
├── routes.py ← Named routes with Mount grouping
├── commands/ ← Custom CLI commands (survive framework:update)
├── models/ ← Application models
│ └── framework/ ← Framework-owned models (AuditLog, Job)
├── modules/ ← Controllers
├── seeders/ ← Database seeders
└── core/ ← Framework engine (updated via framework:update)
├── cli.py ← CLI commands + plugin loader
├── conf.py ← Config provider
├── registry.py ← Model registry (IoC)
├── testing.py ← Test utilities (client, factories, auth)
├── collection.py ← NoriCollection
├── pagination.py ← Async paginator
├── queue.py ← Job queue (memory/database/redis drivers)
├── queue_worker.py ← Queue worker with retry and dead letters
├── auth/ ← Sessions, JWT, CSRF, OAuth2, ACL decorators
├── http/ ← @inject DI, declarative validation
└── mixins/ ← NoriModelMixin, NoriSoftDeletes, NoriTreeMixin
```
---
## Documentation
Full documentation at **[nori.sembei.mx](https://nori.sembei.mx)**.
- [Routing](https://nori.sembei.mx/routing/) — HTTP verbs, path params, reverse routing
- [Controllers](https://nori.sembei.mx/controllers/) — Class-based handlers, `@inject` DI
- [Database](https://nori.sembei.mx/database/) — Tortoise ORM, migrations, soft deletes, tree models
- [Templates](https://nori.sembei.mx/templates/) — Jinja2 views, layouts, static files
- [Authentication](https://nori.sembei.mx/authentication/) — Sessions, JWT, OAuth2, ACL
- [Validation](https://nori.sembei.mx/forms_validation/) — Declarative pipe-separated rules
- [Collections](https://nori.sembei.mx/collections/) — NoriCollection with filtering, sorting, pagination
- [Security](https://nori.sembei.mx/security/) — CSRF, rate limiting, security headers
- [Background Tasks](https://nori.sembei.mx/background_tasks/) — Volatile tasks and persistent job queues (database + Redis)
- [Services](https://nori.sembei.mx/services/) — Email, file storage, search, audit logging
- [WebSockets](https://nori.sembei.mx/websockets/) — Real-time with session/JWT auth
- [Testing](https://nori.sembei.mx/testing/) — Test client, factories, auth helpers, assertions
- [Deployment](https://nori.sembei.mx/deployment/) — Gunicorn, systemd, Nginx, Docker, Redis
- [CLI Reference](https://nori.sembei.mx/cli/) — All commands and plugin system
---
## Testing
```bash
pip install -r requirements-dev.txt
DEBUG=true pytest tests/ -v
```
Tests boot the full ASGI app against an in-memory SQLite database using `httpx.AsyncClient`. No external services required. Nori includes `core.testing` with helpers for testing your own app — see the [testing docs](https://nori.sembei.mx/testing/).
---
## Updating
Projects built with Nori can update the framework core with a single command:
```bash
python3 nori.py framework:update
```
This downloads the latest release from GitHub, backs up the current core, and replaces it. See the [CLI docs](https://nori.sembei.mx/cli/) for options.
---
## Contributing
See [CONTRIBUTING.md](CONTRIBUTING.md).
---
## License
MIT — see [LICENSE](LICENSE).