FastAPI React Toolkit
A set of extensions for FastAPI and a React component library for building modern web applications with Mantine, Zustand, TanStack Query, and JsonForms.
Concept
FastAPI React Toolkit bootstraps a web API with FastAPI and provides a React component library for building a SPA frontend. It supports automatic CRUD API generation, RBAC, OAuth2/JWT authentication, database migrations, and i18n.
Features
- Automatic CRUD API generation from SQLAlchemy models
- Role-Based Access Control (RBAC)
- Database migrations (Alembic)
- OAuth2/JWT authentication
- Modular backend and frontend
- React hooks and components for API, Auth, Language, DataGrid, UserMenu, etc.
- Built-in i18n for backend and frontend
Getting Started
You can use fastapi-rtk create-app command to quickly set up a new project with the recommended structure and example code.
AI coding agents
If you work with an AI coding agent, run this inside your project to teach it the framework:
fastapi-rtk agent install
It installs the guide at docs/agents/fastapi-rtk/, then one entry point per agent:
.claude/skills/rtk-developer/SKILL.mdfor Claude Code, when the project has a.claudedirectory or aCLAUDE.md, orclaudeis on your PATH.--claudewrites it regardless,--no-claudeskips it.- A section in
AGENTS.md, read by Codex, Cursor and others following that convention, when no other entry point was written.--agents-mdwrites it regardless,--no-agents-mdskips it.
The guide ships inside the installed package, so re-run with --force after an upgrade. fastapi-rtk agent uninstall removes it all again, keeping your own text in AGENTS.md and any file you added under the guide directory. Every file that gets overwritten or removed is copied to <name>.<YYYYmmdd-HHMMSS>.bak first.
Recommended Project Structure
project/
├── app/
│ ├── __init__.py # Configuration loading
│ ├── app.py # FastAPI app initialization
│ ├── config.py # Settings
│ ├── models.py # Database models
│ └── apis.py # API endpoints
├── webapp/
│ ├── src/
│ │ ├── main.jsx # React app entry point
│ │ ├── App.jsx # Main app component
│ │ ├── constants.js # Constants for the frontend, like BASE_PATH
│ │ └── ... # Other React components and hooks
│ ├── index.html # HTML template
└── run.py # Entry point for development server
Backend
-
Install FastAPI React Toolkit:
pip install fastapi-rtk mkdir -p app touch run.py app/__init__.py app/app.py app/config.py app/models.py app/apis.py
-
Project files:
app/__init__.py
from fastapi_rtk import g g.config.from_pyfile("./app/config.py")
app/app.py
from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware from fastapi_rtk import FastAPIReactToolkit app = FastAPI(docs_url="/openapi/v1") app.add_middleware( CORSMiddleware, allow_origins=["http://localhost:5173"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) toolkit = FastAPIReactToolkit( app, create_tables=True, # Dev: auto-create tables upgrade_db=False, # Prod: run migrations ) from .apis import * # noqa: E402, F403
app/config.py
See more configuration here.
import os basedir = os.path.abspath(os.path.dirname(__file__)) # Required settings SECRET_KEY = "your-secure-secret-key" SQLALCHEMY_DATABASE_URI = "sqlite+aiosqlite:///" + os.path.join(basedir, "app.db") # Optional settings APP_NAME = "My FastAPI-RTK App"
app/models.py
from fastapi_rtk import Model, Mapped, mapped_column, relationship from sqlalchemy import String, ForeignKey class Category(Model): __tablename__ = "categories" id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True) name: Mapped[str] # Automatically set the column to String items: Mapped[list["Item"]] = relationship(back_populates="category") def __repr__(self): return self.name class Item(Model): __tablename__ = "items" id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True) name: Mapped[str] = mapped_column(String(100)) # Can also be explicitly given description: Mapped[str | None] category_id: Mapped[int | None] = mapped_column(ForeignKey("categories.id")) category: Mapped[Category | None] = relationship(back_populates="items") def __repr__(self): return self.name
app/apis.py
from fastapi_rtk import ModelRestApi, SQLAInterface, g from .models import Item, Category class ItemApi(ModelRestApi): resource_name = "items" datamodel = SQLAInterface(Item) class CategoryApi(ModelRestApi): resource_name = "categories" datamodel = SQLAInterface(Category) g.current_app.add_api(ItemApi) g.current_app.add_api(CategoryApi)
It will create the following CRUD endpoints automatically, all under the resource prefix
/api/v1/items:GET /api/v1/items/_image/{filename}- Serve image files (If image column is present)GET /api/v1/items/_file/{filename}- Serve file downloads (If file column is present)GET /api/v1/items/_info- Get metadata about the model, including which columns can be added, edited, filtered, etc.POST /api/v1/items/bulk/{handler}- Bulk operations, if set on the API classGET /api/v1/items/download- Download items as CSVGET /api/v1/items/- List itemsPOST /api/v1/items/- Create itemGET /api/v1/items/{id}- Get item by IDPUT /api/v1/items/{id}- Update item by IDDELETE /api/v1/items/{id}- Delete item by ID
Frontend
-
Install React dependencies:
pnpm install @mantine/core @mantine/dates @mantine/form @mantine/hooks dayjs react react-dom react-router fastapi-rtk
-
Project files:
webapp/index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <base href="%VITE_BASE_PATH%" /> <link rel="icon" type="image/svg+xml" href="" /> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" /> <title>YOUR_APP_NAME_HERE</title> <script src="%VITE_BASE_PATH%server-config.js"></script> <script nonce="{{nonce}}"> window.nonce = "{{nonce}}"; </script> </head> <body> <div id="root"></div> <script type="module" src="/src/main.jsx"></script> </body> </html>
src/main.jsx
import "@mantine/core/styles.css"; import "@mantine/dates/styles.css"; // Other Mantine styles can be imported here if needed import "fastapi-rtk/styles.css"; import "./index.css"; import { MantineProvider } from "@mantine/core"; import { Provider } from "fastapi-rtk"; import { StrictMode } from "react"; import { createRoot } from "react-dom/client"; import { BrowserRouter } from "react-router"; import App from "./App.jsx"; import { BASE_PATH } from "./constants.js"; createRoot(document.getElementById("root")).render( <StrictMode> <MantineProvider> <Provider baseUrl={BASE_PATH + "api/v1"}> <BrowserRouter basename={BASE_PATH}> <App /> </BrowserRouter> </Provider> </MantineProvider> </StrictMode>, );
src/constants.js
export const BASE_PATH = new URL(document.baseURI).pathname;
Platform Adapters (React Native)
The frontend package is split in two: a Mantine/DOM-free package published as the fastapi-rtk/api subpath, and the Mantine-based web package (fastapi-rtk / fastapi-rtk/core). Every place the library touches the platform (storage, HTTP, cookies/tokens, file downloads, OAuth popups, FormData) goes through six small adapter interfaces (plus an optional localization adapter), grouped into an Adapters object. fastapi-rtk ships web defaults built on the DOM (cookie auth, localStorage, fetch, ...), so existing web apps need no changes.
An optional fastapi-rtk/react-native-adapters package provides factory functions (createReactNativeAdapters, plus per-adapter factories) that build the same six adapters on top of React Native / Expo primitives, using bearer JWT auth (auth/jwt/login) instead of the web's cookie auth (auth/login):
import { ApiProvider, Provider, useAuth } from "fastapi-rtk/api";
import { useApi } from "fastapi-rtk/contexts";
import { createReactNativeAdapters } from "fastapi-rtk/react-native-adapters";
const rnAdapters = createReactNativeAdapters({
asyncStorage,
fileSystem,
sharing,
webBrowser,
});
<Provider baseUrl="https://api.example.com/api/v1" adapters={rnAdapters}>
<ApiProvider resource_name="items">
{/* your own RN UI, driven by useApi()/useAuth() */}
</ApiProvider>
</Provider>;
A single adapter can also be swapped on the web Provider via adapters={{ storage: mine }} (merged per-key over the web defaults; the rest stay web defaults).
See the wiki page React Native and Adapters for the full adapter reference (interfaces, per-adapter web/RN table, auth transports).
License
FastAPI-RTK is licensed under the MIT license.
Contributing
Contributions are welcome! Please open an issue or submit a pull request.
For more details, see the Wiki and the example app.
Metadata
Release files for fastapi-rtk 2.18.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| fastapi_rtk-2.18.1.tar.gz | 617.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| fastapi_rtk-2.18.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 983.8 kB
Release files / fastapi_rtk-2.18.1.tar.gz
| Download URL | fastapi_rtk-2.18.1.tar.gz |
|---|---|
| Size | 617.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
9115ec122a2c0bfc798c02f82ffadf8901c02e4be12147fb32e99209a7944787
|
|
BLAKE2b-256 checksum How to use checksums |
e8f3bb6cbea02995f414ab5a7498910800ec227ff2053fcc2dc891fc47153ce2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.13 {"installer":{"name":"uv","version":"0.12.13","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / fastapi_rtk-2.18.1-py3-none-any.whl
| Download URL | fastapi_rtk-2.18.1-py3-none-any.whl |
|---|---|
| Size | 366.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
c72da2060e6f63f083b0c2b7e5e32e5e31ce4bc740833e88e0ba94d0004ef824
|
|
BLAKE2b-256 checksum How to use checksums |
445bda4b83e215fd3184ba90da527c81921087f0a14cd9f76d604510e44e0c6a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.13 {"installer":{"name":"uv","version":"0.12.13","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|