CLI tool
piercefreeman/mountaineer avatar
piercefreeman/mountaineer

Mountaineer: a Python and React web framework with a Rust core

🏔️ Mountaineer is a batteries-included webapp framework for Python.

872 stars14 forksPythonMIT

At a glance

What is it?
Mountaineer is a batteries-included webapp framework for Python that pairs a FastAPI backend with a React frontend and adds typehints across the whole stack, server rendering, and static analysis of your pages. The unusual part is the implementation language, since the server rendering, file watching and hot reload machinery are written in Rust and compiled into the Python package with maturin.
Who is it for?
Mountaineer suits a team that wants one project instead of a Python API and a separate Node frontend, and that values typehints carried all the way to the database and the page. It does not suit a project that wants to stay in a single language or avoid a native build step, since the package is built with maturin and the Rust source is part of the distribution.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 2 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

One project instead of an API and a frontend

Mountaineer is a framework to easily build webapps in Python and React, and the pitch in the readme is that if you have used either of those languages before for development you will be right at home. The project generator sets up a directory that contains both halves, with controllers, models and views, and the views directory is where the React project lives, complete with its own package.json and tsconfig.json. So the idea is that a route is a Python file in the controllers folder and a set of React files in the views folder, and the framework wires them together. The main features list is short and specific: typehints up and down the stack across the frontend, the backend and the database, trivially easy client to server communication with data binding and function calling, optimised server rendering for better accessibility and search engine visibility, static analysis of web pages for strong validation of things like link validity and data access, and the ability to skip the API or a separate Node.js server just to serve frontend clients. The stated priority is developer productivity above all else, with production speed a close second.

The generator, and the directory shape it produces

Starting a project is one command, run through pipx so it does not pollute your environment:

bash
$ pipx run create-mountaineer-app

The result is a folder called my_webapp with a fixed structure:

code
my_webapp
  /controllers
    /home.py
  /models
    /mymodel.py
  /views
    /app
      /home
        /page.tsx
      /layout.tsx
    /package.json
    /tsconfig.json
  /app.py
  /cli.py
pyproject.toml

Two conventions fall out of that layout. Every service file is nested under the my_webapp root package, and views are defined in a disk-based hierarchy where nested routes live in nested folders, so the folder structure is the route structure. Controllers sit beside them in a flat folder with one file per route, and everything else is ordinary Python you modify as you need it. The views folder doubles as the React project, which is where the frontend requirements and build parameters are declared.

The dev loop, and the two commands you will use most

Mountaineer watches your project and does progressive compilation, and two native commands cover the cases. The first runs the whole development server with a warm reload:

bash
$ uv run mountaineer-dev

Found 4 Python libraries for warm reload: click, fastapi, mountaineer, pydantic
Started Python backend in 2.05s
Local http://127.0.0.1:5006

Note what it reports: the libraries it found to watch, the startup time, and the local address. The second command watches the source tree without hosting the server, and watching alone is what lets your frontend pick up the API definitions from your backend controllers:

bash
$ uv run mountaineer-watch

Both commands are installed with the package and discover the project automatically, so there is no configuration file to point at your source. The project scripts in the manifest show the third one, mountaineer-prod, alongside the dev and watch commands, so the same entry point names cover the three modes.

A Rust core compiled into the Python package

The implementation detail that makes this project unlike other Python web frameworks is that a lot of it is Rust. The Cargo workspace has a members list pointing at the crates under crates/lib, and the main package depends on pyo3 with the extension-module and abi3-py310 features, on serde, on tokio with the full feature set, and on five local crates with revealing names. mountaineer-ssr is the server side rendering, mountaineer-vite is the Vite integration, mountaineer-file-monitor is the file watching, mountaineer-hot-reload-discover finds what needs reloading, and mountaineer-terminal handles the terminal output. There are also platform-specific crates, mountaineer-hot-reload-fork on unix and mountaineer-hot-reload-pool on windows, which suggests the reload strategy differs per platform rather than being a single implementation. The Python package is built with maturin, which is why the build requirements are maturin rather than setuptools, and why the manifest has a tool.maturin section. So the install of this package involves compiling Rust, and that is the price of the developer experience.

The Python side, and what the framework depends on

The Python dependencies are the interesting part of the contract. pydantic is there for data binding and models, FastAPI is the server, uvicorn with the standard extra is the ASGI server, click is the CLI, pydantic-settings reads configuration, inflection does the pluralisation and inflection work that a framework like this needs for route and function names, and rich is the terminal output. The two mountaineer-prefixed packages are separate distributions for the exceptions and for dependency injection, so those pieces can be used independently. The manifest requires Python 3.10 or newer with an upper bound of 3.15, which is a narrower range than most projects state and is worth checking against your interpreter. The comment on the rich dependency explains why it is not an extra, which is a nice piece of honesty: the release configurations do not need it, but including it by default avoids forcing regular development builds to install an extras for basic CLI functionality.

The database, the compose file and the local environment

For a new application you typically need to create the database tables, and the readme says to make sure you have postgres running, with a compose file bundled for convenience. The development commands are:

bash
docker compose up -d
uv run createdb

And of course you can point at an existing database instead, configuring it in the .env file in the project root. The repository carries a docker-compose.test.yml for the test environment, and a separate Dockerfile whose comment says it is there to help test builds on linux while developing locally. That image is a good picture of what the toolchain expects, since it installs python3.14 with its venv module, build-essential, the Rust toolchain through rustup, uv through its install script, and Node.js 18 through nvm, and then it verifies rustc, node and npm are all present. The build copies the package sources, the create_mountaineer_app generator and the Makefile into the image.

Benchmarks, tests and the shape of the repository

The Cargo manifest declares three benchmarks with their own harness setting: a source map benchmark, an SSR benchmark and a lexers benchmark, which tells you that source maps and tokenising are the operations the author thought worth measuring. The release profile is tuned, with opt-level at 3, debug off, link time optimisation on and incremental compilation off, which is what you would expect for a library that ships as a compiled extension. On the Python side the Makefile has separate lint and test targets for the library, the generator and the scripts, matching the three sub-projects the manifest excludes from the package, namely fixtures, the CI webapp, the generator, the media directory, the docs website and the benchmarking directory. There is also a lint-validation target set, which suggests the project checks its own configuration as well as its code. The licence is MIT, the last push was on 2026-09-23, and the most recent release is v0.20.0.

Editorial conclusion

Mountaineer suits a team that wants one project instead of a Python API and a separate Node frontend, and that values typehints carried all the way to the database and the page. It does not suit a project that wants to stay in a single language or avoid a native build step, since the package is built with maturin and the Rust source is part of the distribution. Before you start, note that the project is young, the version in the manifest is 0.1.0 while the released versions are 0.20.0, and the Python floor is 3.10 with an upper bound of 3.15, so check the interpreter you have.

Frequently asked questions

What is Mountaineer?

It is a batteries-included webapp framework for Python that pairs a FastAPI backend with a React frontend in one project, with typehints carried across the frontend, the backend and the database, optimised server rendering, and static analysis of pages for validation of links and data access.

How do I start a new Mountaineer project?

Run pipx run create-mountaineer-app, which asks a short set of questions and writes a my_webapp folder containing controllers, models and a views directory that doubles as the React project with its own package.json and tsconfig.json, plus app.py, cli.py and a pyproject.toml.

Why does Mountaineer need Rust?

The server side rendering, the Vite integration, the file watching, the hot reload discovery and the terminal handling are all local Rust crates under crates/lib, and the Python package is built with maturin using pyo3 with the extension-module and abi3-py310 features. Installing the package therefore involves compiling Rust.

Which Python versions does Mountaineer support?

Python 3.10 or newer with an upper bound of 3.15. The dependencies are pydantic, FastAPI, uvicorn, click, pydantic-settings, inflection, rich and two separate mountaineer packages for exceptions and dependency injection.

Official sources

  1. License: MIT
  2. piercefreeman/mountaineer on GitHub
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/piercefreeman-mountaineer.svg)](https://hysenlabs.com/projects/piercefreeman-mountaineer)

Was this useful?