Skip to main content

Nestipy Logo

Version Python License

Description

Nestipy is a Python framework built on top of FastAPI that follows the modular architecture of NestJS

Under the hood, Nestipy makes use of FastAPI, but also provides compatibility with a wide range of other libraries, like Blacksheep, allowing for easy use of the myriad of third-party plugins which are available.

Getting started

Scaffold a full project (backend + a generated React/Vue/Svelte frontend) with the Nestipy CLI:

nestipy new myapp --fullstack --react   # or --vue / --svelte
cd myapp && uv sync && nestipy start --dev
cd inertia && npm install && npm run dev

Or add it to an existing project:

pip install nestipy-inertia

Full manual: https://nestipy.github.io/nestipy/technique/inertia.html

Features

Full latest Inertia.js protocol parity:

  • Partial reloads — only (X-Inertia-Partial-Data), except (X-Inertia-Partial-Except, takes precedence) and X-Inertia-Reset.
  • Prop helpers — optional(fn), defer(fn, group=..., merge=...), merge(fn), deep_merge(fn, match_on=[...]) (plus lazy alias).
  • Deferred props (deferredProps) and merge props (mergeProps / deepMergeProps / matchPropsOn).
  • History encryption — res.inertia.encrypt_history() / clear_history() (+ InertiaConfig(encrypt_history=True)).
  • Asset versioning with 409 (GET only) + X-Inertia-Location, and automatic 302 → 303 for PUT/PATCH/DELETE.
  • Shared props, session flash messages, and Pydantic validation-error handling with error bags.
  • SSR via an external Inertia SSR server, with template fallback.

Full example

main.py

  import os

import uvicorn
from nestipy.core import NestipyFactory
from nestipy.common import session
from app_module import AppModule, inertia_config
from nestipy_inertia import inertia_head, inertia_body, vite_react_refresh

app = NestipyFactory.create(AppModule)

# set view engine mini jinja and
app.set_base_view_dir(os.path.join(os.path.dirname(__file__), "views"))
# enable session
app.use(session())

if __name__ == '__main__':
    uvicorn.run('main:app', host="0.0.0.0", port=8000, reload=True)

app_module.py

import os.path

from nestipy.common import Module

from app_controller import AppController
from app_service import AppService
from nestipy_inertia import InertiaModule, InertiaConfig


@Module(
    imports=[
        InertiaModule.register(
            InertiaConfig(
                root_dir=os.path.join(os.getcwd(), "inertia")
            )
        )
    ],
    controllers=[AppController],
    providers=[
        AppService,
    ]
)
class AppModule:
    ...

vite.config.ts

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react-swc'
import nestipyVite from "./nestipy.inertia";

// https://vitejs.dev/config/
export default defineConfig({
    plugins: [
        react(),
        nestipyVite({
            entry: './src/main.tsx',
            ssr: './src/ssr.tsx'
        }),
    ],
})

nestipy.inertia.ts

import { PluginOption } from "vite";

type Input = {
    entry: string,
    ssr?: string,
    manifest?: string
}
type NestipyPlugin = (options: Input) => PluginOption
const nestipyVite: NestipyPlugin = ({entry, ssr, manifest = "manifest.json"}) => {
    return {
        name: "nestipy-vite-plugin",
        config: (config, env) => {
            return {
                ...config,
                build: {
                    manifest: env.isSsrBuild ? false: manifest,
                    outDir: env.isSsrBuild ? "dist/ssr" : "dist",
                    rollupOptions: {
                        input: env.isSsrBuild && ssr ? ssr : entry,
                    },
                },
                ssr: {
                    noExternal: ['@inertiajs/server']
                }
            }
        }
    }
}

export default nestipyVite

views/index.html

<!Doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8"/>
    <link rel="icon" type="image/svg+xml" href="/vite.svg"/>
    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
    <title>Nestipy + Vite + React + TS + Inertia + Mini jinja</title>
    {{ inertiaHead() }}
</head>
<body>
{{ viteReactRefresh() }}
{{ inertiaBody() }}
</body>
</html>

app_controller.py

from typing import Annotated

from nestipy.common import Controller, Get, Response, Post
from nestipy.ioc import Inject, Res, Body
from pydantic import BaseModel, EmailStr

from app_service import AppService
from nestipy_inertia import InertiaResponse, optional, defer


class UserLogin(BaseModel):
    email: EmailStr
    password: str


@Controller()
class AppController:
    service: Annotated[AppService, Inject()]

    @Get()
    async def get(self, res: Annotated[InertiaResponse, Res()]) -> Response:
        props = {
            "message": "hello from index",
            "details": optional(lambda: "loaded only on partial reload"),
            "stats": defer(lambda: {"users": 42, "online": 7}),
        }
        return await res.inertia.render("Index", props)

    @Get('/about')
    async def about(self, res: Annotated[InertiaResponse, Res()]) -> Response:
        return await res.inertia.render("About", {"framework": "Nestipy + Inertia.js"})

    @Post("/login")
    async def some_form(self, user: Annotated[UserLogin, Body()], res: Annotated[InertiaResponse, Res()]) -> Response:
        res.inertia.flash("form submitted", category="success")
        return await res.inertia.back()

Viw full example code here.

Support

Nestipy is an MIT-licensed open source project. It can grow thanks to the sponsors and support from the amazing backers. If you'd like to join them, please [read more here].

Stay in touch

License

Nestipy is MIT licensed.

Metadata

Release files for nestipy-inertia 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for nestipy-inertia 0.2.0
File Size Uploaded
nestipy_inertia-0.2.0.tar.gz 12.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for nestipy-inertia 0.2.0
File Interpreter ABI Platform
nestipy_inertia-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 29.2 kB

Release files / nestipy_inertia-0.2.0.tar.gz

Download URL nestipy_inertia-0.2.0.tar.gz
Size 12.6 kB
Tags Source
SHA-256 checksum
How to use checksums
90629c16f474ba75af59828396af60f98faea272f90e26a0195dbf762082ddbc
BLAKE2b-256 checksum
How to use checksums
bea32e1059c6ed429658c92031d798780c9d1a9331629d583239f8ffb3223a29
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.7.21

Release files / nestipy_inertia-0.2.0-py3-none-any.whl

Download URL nestipy_inertia-0.2.0-py3-none-any.whl
Size 16.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
30e779dc4f149d20d8e5efabd9c0a661e32f0af309b6ad1e2c884b4cae95be7d
BLAKE2b-256 checksum
How to use checksums
fc73085fbc399c9b3bac0224c0549b75a98c9698747371107026be0b6ec98f82
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.7.21

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files

0.1.6

2 release files

0.1.5

2 release files

0.1.4

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page