Controllers

Controllers are the heart of Mountaineer. They are the Python classes that define the logic for your views, layouts, and apps. They are responsible for rendering the view, handling side effects, and managing the state of your application.

View Controller

CLASSmountaineer.controller.ControllerBase

One Controller should be created for every frontend page in your webapp. The controller is where you place all logic that's necessary for this one page - the data that's pushed from the frontend and the data that's received from the page.

All data from render is passed to the frontend and usable with automatically generated typehints.

Class Constructor

  • Name
    slow_ssr_threshold
    Type
    float
    Description

    Default: 0.1

    Each python process has a single V8 runtime associated with it, so SSR rendering can become a bottleneck if it requires processing. We log a warning if we detect that an SSR render took longer than this threshold.

  • Name
    hard_ssr_timeout
    Type
    float | None
    Description

    Default: 10.0

    If the SSR render takes longer than this threshold, we will automatically kill the V8 runtime and return an error to the client. This is useful for avoiding blocking the reset of the server process if the React render logic hangs.

Class Attributes

  • Name
    url
    Type
    str
    Description

    The URL that this controller will be mounted at. This can contain dynamic path parameters, e.g. /user/{user_id}. Each parameter will be passed to your render function as a keyword argument, so this function would have a signature like async def render(self, user_id: str) -> RenderBase.

  • Name
    view_path
    Type
    str | ManagedViewPath
    Description

    Typically, view paths should be a relative path to the local project root. Paths are only used if you need to specify an absolute path to another file on disk.

  • Name
    slow_ssr_threshold
    Type
    float
    Description

    If a server-side rendering operation takes longer than this threshold, we will log the time and path parameters as a warning to help debugging.

  • Name
    hard_ssr_timeout
    Type
    float | None
    Description

    If a server-side rendering operation takes longer than this threshold, we will automatically kill the V8 runtime and return an error to the client. This helps avoid blocking other server render handlers if the React render logic hangs.

  • Name
    source_map
    Type
    SourceMapParser | None
    Description

    During development, we will load server-side source maps alongside the raw javascript code. This parser controls converting stack traces from the minified code to the original source code.

  • Name
    initialized
    Type
    Description
  • Name
    script_name
    Type
    Description

    The short-hand name of the controller, used to resolve the SSR script and other dependencies from disk.

Class Methods

  • Name
    render
    Return type
    RenderBase | None | Coroutine[Any, Any, RenderBase | None]
    Description

    Render provides the raw data payload that will be sent to the frontend on initial render and during any sideeffect update. In most cases, you should return a RenderBase instance. If you have no data to display you can also return None.

    This function must be explicitly typehinted with your response type, which allows the AppController to generate the correct TypeScript types for the frontend:

    Code

    class MyServerData(RenderBase): pass class MyController: def render(self) -> MyServerData: pass

    If you don't intend to sync any data from server->client you can typehint this function with an explicit None return annotation:

    Code

    class MyController: def render(self) -> None: pass

    Render functions accept any number of arguments and keyword arguments, following the FastAPI route parameter style. This includes query parameters, path parameters, and request bodies.

    Code

    class MyController: url = "/my-url/{path_param}" def render( self, query_param: str, path_param: int, dependency: MyDependency = Depends(MyDependency), ) -> MyServerData: ...
  • Name
    resolve_paths
    Return type
    bool
    Description

    Typically used internally by the Mountaineer build pipeline. Calling this function sets the active view_base of the frontend project, which allows us to resolve the built javascripts that are required for this controller.

Code

from mountaineer import ControllerBase, RenderBase class MyControllerRender(RenderBase): value: int class MyController(ControllerBase): url = "/my-page" view_path = "/app/my-page.tsx" async def render(self) -> MyControllerRender: return MyControllerRender(value=10)

Code

import { useServer } from "./_server"; const MyPage = () => { const serverState = useServer(); return <div>{serverState.value}</div>; } export default MyPage;

Layout Controller

CLASSmountaineer.controller_layout.LayoutControllerBase

Base class for layouts. Layout controllers are used to generate the HTML that wrap a regular view controller. They support all actions that a regular controller does (@sideeffect and @passthrough).

Their limitations:

  • They are run in an isolated dependency injection context, they don't share dependency injected values with the given page
  • The current page Request is not supported within render()
  • Sideeffect updates to the layout don't affect the page state, and vice-versa
  • Layout controllers can't be mounted as a URL route

App Controller

CLASSmountaineer.app.AppController

Main entrypoint of a project web application.

Class Constructor

  • Name
    name
    Type
    str
    Description

    Default: 'Mountaineer Webapp'

  • Name
    version
    Type
    str
    Description

    Default: '0.1.0'

  • Name
    view_root
    Type
    Path | None
    Description

    Default: None

  • Name
    global_metadata
    Type
    Metadata | None
    Description

    Default: None

    Metadata that's injected into every page. This is useful for setting global stylesheets and scripts. It's also useful for setting fallback metadata if it isn't overloaded by individual pages like setting a page title.

  • Name
    custom_builders
    Type
    list[APIBuilderBase] | None
    Description

    Default: None

  • Name
    config
    Type
    ConfigBase | None
    Description

    Default: None

    The configuration object for the application. This is the main place to place runtime configuration values that might be changed across environments. One instance is registered as a global singleton and cached within the AppController class as well.

  • Name
    fastapi_args
    Type
    dict[str, Any] | None
    Description

    Default: None

    Override or add additional arguments to the FastAPI constructor. See the FastAPI documentation for the attributes of this constructor.

Class Attributes

  • Name
    builders
    Type
    list[APIBuilderBase]
    Description
  • Name
    app
    Type
    FastAPI
    Description

    Internal FastAPI application instance used by Mountaineer. Exposed to add API-only endpoints and middleware.

  • Name
    live_reload_port
    Type
    int
    Description

    Port to use for live reloading of the webserver. This will be used to create a websocket connection to the browser to trigger a reload when the frontend has updates. By default we will bind to port 0 to guarantee an open system port.

  • Name
    controllers
    Type
    list[ControllerDefinition]
    Description

    Mounted controllers that are used to render the web application. Add a new one through .register().

  • Name
    internal_api_prefix
    Type
    str
    Description

    URL prefix used for the action APIs that are auto-generated through @passthrough and @sideeffect decorators.

  • Name
    hierarchy_paths
    Type
    dict[Path, LayoutElement]
    Description

    Mapping of disk paths to file-system metadata about the controller. This internally builds up a DAG of the layout hierarchy to be used for rendering nested pages and layouts.

  • Name
    development_enabled
    Type
    Description

Class Methods

  • Name
    register
    Return type
    Description

    Register a new controller. This will:

    • Mount the html of the controller to the main application service
    • Mount all actions (ie. @sideeffect and @passthrough decorated functions) to their public API
  • Name
    invalidate_view
    Return type
    Description

    After an on-disk change of a given path, we should clear its current script cache so we rebuild with the latest changes. We should also clear out any nested children - so in the case of a layout change, we refresh all of its subpages.

  • Name
    compile_html
    Return type
    Description

    Compiles the HTML for a given page, with all the controller-returned values hydrated into the page.

  • Name
    update_hierarchy
    Return type
    Description

    When we register a new element, we need to:

    • Find if there are any on-disk layouts that have been defined. We add these greedily, before we know if they're backed by a layout controller
    • Add the controller as a LayoutElement if it's new. Otherwise update the existing element

    This function is built to be invariant to the order of the updates, so we can call it multiple times and call it progressively as more controllers are added. It will be valid at any given state for the current webapp mounting.

  • Name
    merge_render_signatures
    Return type
    Description

    Collects the signature from the "reference_controller" and replaces the active target_controller's render endpoint with this new signature. We require all these new parameters to be kwargs so they can be injected into the render function by name alone.

  • Name
    generate_openapi
    Return type
    Description

    Bundle custom user exceptions in the OpenAPI schema. By default endpoints just include the 422 Validation Error, but this allows for custom derived user methods.

  • Name
    get_build_metadata
    Return type
    Description

    Will cache the build metadata in production but not in development, since we expect production developments will compile their metadata once and then use it for all endpoints.


Render

CLASSmountaineer.render.RenderBase

Base class for all renderable data models. Subclass this model when defining your own component data schema.

Class Attributes

  • Name
    metadata
    Type
    Metadata | None
    Description
  • Name
    model_config
    Type
    Description

Metadata

We provide support for all header tags that you'll find within an html <head>. These won't be rendered by your browser but are where you'll place style imports and page metadata for SEO.

We have passthrough classes for all the common tags so they align to what's outputted in HTML. These are defined and referenced below as ScriptAttribute, LinkAttribute, MetaAttribute, etc. We also provide some convenient shortcuts for more complicated, common meta tags.

CLASSmountaineer.render.Metadata

Metadata lets the client specify the different metadata definitions that should appear on the current page. These are outside the scope of React management so are only handled once on the initial page render. But because they still receive the initial render request, you can add any dynamic logic that you want to customize the behavior of the page metadata. This includes templating the page title depending on a remote value, modifying the scripts injected depending on the user, etc.

Class Attributes

  • Name
    title
    Type
    str | None
    Description
  • Name
    metas
    Type
    list[MetaAttribute]
    Description
  • Name
    links
    Type
    list[LinkAttribute]
    Description
  • Name
    scripts
    Type
    list[ScriptAttribute]
    Description
  • Name
    explicit_response
    Type
    Response | None
    Description
  • Name
    ignore_global_metadata
    Type
    bool
    Description
  • Name
    model_config
    Type
    Description

Class Methods

  • Name
    merge
    Return type
    Metadata
    Description
  • Name
    build_header
    Return type
    list[str]
    Description

    Builds the header for this controller. Returns the list of tags that will be injected into the

Code

class MyController(Controller): async def render( self, user_name: str, ): return MyControllerRender( metadata=Metadata( title=f"Welcome, {user_name}!", ) )

Code

Metadata( title="My Page", metas=[ MetaAttribute(...), ThemeColorMeta(...), ViewportMeta(...), ], links=[ LinkAttribute(...), ] )

CLASSmountaineer.render.ScriptAttribute

Inject a generic tag into the of the current page.

Class Attributes

  • Name
    src
    Type
    str
    Description
  • Name
    asynchronous
    Type
    bool
    Description
  • Name
    defer
    Type
    bool
    Description
  • Name
    optional_attributes
    Type
    dict[str, str]
    Description

Code

ScriptAttribute( src="https://example.com/script.js", asynchronous=True, optional_attributes={"defer": "true"}, defer=False, )

CLASSmountaineer.render.LinkAttribute

Inject a generic tag into the of the current page.

Class Attributes

  • Name
    rel
    Type
    str
    Description
  • Name
    href
    Type
    str
    Description
  • Name
    optional_attributes
    Type
    dict[str, str]
    Description
  • Name
    add_static_sha
    Type
    bool
    Description

Class Methods

  • Name
    set_sha
    Return type
    Description

    Updates the URL by adding or modifying the 'sha' query parameter. If a sha is already provided as part of href, will override the existing sha.

Code

LinkAttribute( rel="stylesheet", href="https://example.com/styles.css", optional_attributes={"media": "screen"}, )

CLASSmountaineer.render.MetaAttribute

Represents a meta tag that can be included in the head of an HTML document.

Class Attributes

  • Name
    name
    Type
    str | None
    Description
  • Name
    content
    Type
    str | None
    Description
  • Name
    optional_attributes
    Type
    dict[str, str]
    Description

Code

MetaAttribute( name="description", content="This is a description of the page.", optional_attributes={"lang": "en"}, )

CLASSmountaineer.render.ViewportMeta

Defines the bounds on the current page and how much users are able to zoom.

Class Attributes

  • Name
    width
    Type
    str
    Description
  • Name
    initial_scale
    Type
    float
    Description
  • Name
    maximum_scale
    Type
    float
    Description
  • Name
    user_scalable
    Type
    bool
    Description

Class Methods

  • Name
    create_attribute
    Return type
    Description

Code

ViewportMeta( initial_scale=1.0, maximum_scale=2.0, user_scalable=True, )

CLASSmountaineer.render.ThemeColorMeta

Customizes the default color that is attached to the page.

Class Attributes

  • Name
    color
    Type
    str
    Description
  • Name
    media
    Type
    str | None
    Description

Class Methods

  • Name
    create_attribute
    Return type
    Description

Code

ThemeColorMeta( color="white", media="light", )

SSR

Every page on Mountaineer is server-side rendered by default. Most SSR logic is handled in our embedded Rust layer. In Rust we spin up a V8 isolate, handle logging, catch and process exceptions, etc. This page only covers the client functions that are exposed to Python.

FUNCTIONmountaineer.ssr.render_ssr

render_ssr

Render the React component in the provided SSR javascript bundle. This file will be directly executed within the V8 runtime.

To speed up requests for the same exact content (ie. same react and same data) we cache the result of the render_ssr_rust call by default for a limited amount of previous calls. We limit the overall size of this cache to 5MB.

Parameters

  • Name
    script
    Type
    str
    Description

    The raw code of the javascript bundle to execute. Should be pre-compiled into an SSR compatible package with a single entrypoint.

  • Name
    render_data
    Type
    dict[str, Any]
    Description

    The data to inject into the SSR javascript bundle

  • Name
    hard_timeout
    Type
    int | float | None
    Description

    Default: None

    The maximum time to allow the render to take in seconds. If the render takes longer than this time, our thread supervisor will kick in and terminate the rust worker.

  • Name
    sourcemap
    Type
    str | None
    Description

    Default: None


CLASSmountaineer.ssr.V8RuntimeError

An exception thrown by the V8 runtime in the case of a permanent failure that involves the content of the script.


Source Maps

CLASSmountaineer.client_compiler.source_maps.SourceMapParser

Parse sourcemaps according to the official specification: https://sourcemaps.info/spec.html

Class Constructor

  • Name
    path
    Type
    str | Path | None
    Description

    Default: None

  • Name
    script
    Type
    str | None
    Description

    Default: None

Class Attributes

  • Name
    source_map
    Type
    SourceMapSchema | None
    Description
  • Name
    parsed_mappings
    Type
    dict[tuple[int, int], mountaineer_rs.MapMetadata] | None
    Description

Class Methods

  • Name
    find_common_prefix
    Return type
    str | None
    Description

    Find the common prefix among all non-anonymous paths. Caches results based on the set of input paths.

  • Name
    parse
    Return type
    Description

    Parse the source map file and build up the internal mappings. Common prefix calculation is deferred until needed.

  • Name
    get_original_location
    Return type
    Description

    For a compiled line and column, return the original line and column where they appeared in the pre-built file.

  • Name
    map_exception
    Return type
    str
    Description

    Given a JS stack exception, try to map it to the original files and line numbers