Skip to content

EndoCore

A file-based ASGI backend framework — the folder tree is the API.

No routers, no decorators, no registration config. Drop a file in the right folder and the endpoint exists. Routing, versioning and the CLI are all just operations over one directory tree.

Pure ASGI · one core dependency (uvicorn) · a secure ORM · DI · WebSockets · cache · OpenAPI · migrations · 1600+ tests.

Get started Tutorial vs FastAPI Discord


The idea in ten seconds

Api/
  v1/
    User/
      Role/
        Get.py      # GET  /v1/user/role
        Post.py     # POST /v1/user/role
      [id]/
        Get.py      # GET  /v1/user/42   ->  id = "42"
# Api/v1/User/Role/Get.py
from endocore import Request, Response

async def handler(request: Request) -> Response:
    return Response.json({"roles": ["admin", "editor", "viewer"]})
endo dev            # http://127.0.0.1:8000

The folder is the URL, the file name is the HTTP method, [id] captures a value, and the first vN folder is the API version. That's the entire routing model.


Why EndoCore

  • File = route

    Structure is the API. What you see in the tree is exactly what the server serves. No hidden registration, no drift between code and routes.

  • Secure ORM (SQLite + PostgreSQL)

    Django-flavoured, but security-first: every value is bound by the driver, identifiers are validated and quoted, lookups are whitelisted. Async-ready.

  • Dependency Injection

    FastAPI-style Depends(...) plus app-level providers — nested, cached per-request, resolved by type or name.

  • Batteries included

    WebSockets + pub/sub, cache (memory/Redis), CORS/CSRF/gzip/rate-limit middleware, cookies, background tasks, migrations with rollback, OpenAPI.


A taste of the ORM

from endocore.orm import Model, fields, configure, create_all, Count

class Author(Model):
    name = fields.CharField(max_length=100)

class Book(Model):
    title  = fields.CharField(max_length=200)
    author = fields.ForeignKey(Author, related_name="books")
    tags   = fields.ManyToManyField("Tag")

configure(backend="sqlite", database="app.db")
create_all(Author, Book)

Author.objects.create(name="Ada")
Book.objects.filter(author__name="Ada")             # cross-table lookup (JOIN)
Author.objects.annotate(n=Count("books"))           # aggregate over a relation
await Book.objects.aget(id=1)                        # async (non-blocking)

Install

pip install endocore
# extras: pip install "endocore[postgres,files,redis,pydantic]"

New here? Follow this path:

  1. Installation — one pip install.
  2. Quickstart — a working API in a minute.
  3. Tutorial — a small blog API end-to-end: models, services, middleware, versions, tests.

Status

EndoCore is 1.0 — the public API documented in the reference is now covered by semver. It ships with 2300+ tests covering routing, the ORM (both dialects, injection tests), migrations, middleware, DI, cache and WebSockets.

One core dependency

The core depends on a single external package: uvicorn. The resolver, Request/Response, middleware, CLI and ORM are standard library. PostgreSQL, encrypted files, Redis, Celery and pydantic are optional extras. More in Philosophy.