fastapi-rtk
v2.13.1
Published
A React component library for FastAPI in combination with FastAPI React Toolkit backend, built with Mantine, JsonForms, and Zustand.
Downloads
4,893
Maintainers
Readme
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.
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 serverBackend
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.pyProject 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, F403app/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.nameapp/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-rtkProject 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.
