Skip to content

Narvi User Guide

Installation

Narvi is open source software released under the MIT License and is installable as a Python package. For installation instructions and to view the source code, see https://codeberg.org/visual-topology/narvi.

Using Narvi

Narvi is a web application server written in python. It supports applications with two parts:

  • a backend application service, written in python
  • a frontend application, written in html/javascript/css

Narvi also provides:

  • the concept of workspaces, separating groups of application service/applications
  • service_ids, allowing different instances of an application service to be accessed
  • session_ids, allowing a single instance of an application service to be accessed by multiple application instances
  • messaging, allowing messages to be sent between application and application service instances

Narvi applications are available at end-points, typically:

http://host:port/narvi/workspace-name/application-name/service-id

or:

http://host:port/narvi/workspace-name/application-name

Narvi application services are available at end-points:

http://prefix/workspace/application-service-name/service-id/connect

Narvi does not implement authentication/authorisation support.
This should be provided by an external security layer which restricts access to the URLs.

Simple Example:

Project Layout

root/
    src/
        echo_app/
            __init__.py
            static/
                index.html
            echo_service.py
    run_server.py

All application and application service files are located within python packages, so your PYTHONPATH should include root/src

The application service (echo_service.py):

class EchoService:

    def __init__(self, services):
        self.services = services
        # route messages to the message handler method
        self.services.add_message_listener(lambda msg, sid: self.message_handler(msg, sid))

    def message_handler(self, msg, from_session_id):
        # send back a message echoing the received message...
        self.services.send("echo:" + msg, for_session_id = from_session_id)

Now the application (index.html):

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Narvi Echo Example</title>
    <script src="narvi/narvi.js"></script>
    <script>
        class EchoApp {
            constructor(services, parameters) {
                let message_content = document.getElementById("message_content");
                let send_message = document.getElementById("send_message");
                let recieved_message = document.getElementById("received_message");

                services.add_message_listener(msg => {
                    recieved_message.innerText = msg;
                });
                send_message.addEventListener("click", evt => {
                    services.send(message_content.value);
                });
            }
        }

        window.addEventListener("load",(evt) => {
            start_narvi(EchoApp);
        })

    </script>
    <style>
        * {
            margin: 10px;
        }
    </style>
</head>
<body>
    <h2>Narvi Example App - Echo</h2>
    <input type="text" id="message_content" value="">
    <input type="button" id="send_message" value="Send Message">
    <div>Message Received: <span id="received_message"></span></div>
</body>
</html>

Create and run the service using the Narvi server API (run_server.py)

# script to run the Narvi Echo Service and Application

from narvi.api.narvi_server import NarviServer

server = NarviServer()

# register the backend service implemented by the EchoService app
app_service = server.register_service(workspace="workspace0",
     app_cls_name="echo_app.echo_service.EchoService",
     app_service_name="echo_service",
     fixed_service_id="echo_service_id", shared_service=True)

# register the frontend application which will connect to the service
server.register_app(application_service=app_service, app_name="echo_app",
    app_parameters={},
    resource_roots={
        "index.html": server.get_path_of_resource("echo_app.static", "index.html")
    })

# print the URLs for all applications
for service in server.list_app_urls():
    print(service)

server.run()

Something like the following output will be printed:

('workspace0', 'echo_app', 'http://localhost:8999/narvi/workspace0/echo_app/index.html')

Paste the URL into your browser to load the app

Echo App