Introduction

What FastFort is, what it gives a FastAPI project on install, and the constraints it was built under.

Available since v0.1.0

FastFort is an admin and authentication framework for FastAPI. It gives a project the things Django ships and FastAPI does not: a model admin, sessions and JWTs, roles, an audit trail — installed as one wheel.

uv add "fastfort[sqlalchemy,postgres]"

Nothing else. No Node.js, no build step, no CDN, no scaffolding tool that writes files you then have to read.

What you get on install

Register a model and open /admin:

from fastfort import admin

from app.models import Product


@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
    list_display = ("id", "name", "category", "price", "stock", "is_active")
    list_filter = ("is_active", "category", "price")
    search_fields = ("sku", "name", "description")
    ordering = ("-created_at",)
    select_related = ("category",)

That produces a table with sortable columns, a search box, a filter panel, numbered pagination, row selection with bulk actions, and working create, edit and delete pages. Foreign keys become searchable pickers — backed by an autocomplete endpoint once the target table outgrows a dropdown — and many-to-many fields become removable chips.

Every one of those controls works with JavaScript switched off. Sorting is a link, filtering is a form, and the browser-side script upgrades them in place rather than owning them.

The constraints it was built under

These are not preferences. Each one closed off a class of problem, and the test suite fails when one is broken.

No Node.js, anywhere

The admin’s CSS, JavaScript, icons and templates are hand-written files served straight out of the package. A project installs one wheel and has a working admin. There is no npm install in a FastFort deployment, no node_modules in a Docker image, and no CDN request from a page that shows your data.

The front end has a size budget enforced by a test — currently 24 KB of CSS and 29 KB of script, gzipped. Raising it is allowed and has happened three times; each raise names the feature that caused it.

The admin never sees your ORM

Nothing above fastfort/orm/ may import SQLAlchemy or Tortoise, and a test fails the build on a violation. Introspection turns a model into a ModelSpec — plain, immutable, JSON-serialisable data — and every layer above works from that.

The payoff was concrete: a second ORM adapter was added without changing a line of the admin, and a conformance suite asks both backends the same questions over identical model shapes, so “the second one behaves the same” is a test rather than a claim.

Configuration errors happen at start-up

A typo in list_display is not a 500 the first time somebody opens that page. It is a start-up error naming every problem at once:

ConfigurationError: ProductAdmin is misconfigured:
  - list_display names 'pirce', which shop.product has no
  - list_filter names 'description'; free-text and multi-valued fields
    cannot be offered as a filter
  - ordering names 'rank', which is not sortable
Hint: Fields available on shop.product: category, cost, created_at, ...

Mass assignment has one gate

FieldSpec.editable is the single source of truth. A submitted value for a field whose spec says editable=False is discarded, whichever form or endpoint it arrived through. There is deliberately no second flag that could disagree with it.

Adapters never commit

They flush. The UnitOfWork context manager commits on a clean exit and rolls back on an exception, so a half-failed request leaves nothing behind — including a bulk action that fails on its fortieth row.

What it is not

  • Not a CMS. It edits rows in your tables. It does not own a content model, a page tree or a publishing workflow.
  • Not a REST framework. It is an admin. Your API is yours; FastFort mounts under one URL prefix and stays there.
  • Not stable yet. 0.3.0 is pre-1.0 and the public API is not frozen. A minor release may contain breaking changes, each listed under a Breaking heading in the changelog. Pin a version.

Where to go next

  • Quickstart — an empty directory to a signed-in admin.
  • Model admin — every option, and what each one changes on screen.
  • Screen by screen — each admin page beside the code that produces it.