Publishing a Website or Web App

Publishing a website or web app is quite simple. There are helper functions to make this a one-line call if you have properly uploaded the relevant files from your development /pkg directory.

All of these functions expect you to place your index.html within a directory in /pkg. In the following examples, that directory would be /pkg/ui. All other files should be in a directory called assets inside of ui, so /pkg/ui/assets. The structure should look like this:

my_package
└── pkg
    └── ui
        ├── assets
        └── index.html

Serving Static Assets

The simplest way to serve a UI is using the serve_ui function from process_lib:

serve_ui(&our, "ui", true, false, vec!["/"]).unwrap();

This will serve the index.html in the specified folder at the home path of your process. If your process is called main:my_package:myusername.os and your Kinode is running locally on port 8080, then the UI will be served at http://localhost:8080/main:my_package:myusername.os.

serve_ui takes five arguments: the process' &Address, the name of the folder inside pkg that contains the index.html and other associated UI files, whether the UI requires authentication, whether the UI is local-only, and the path(s) on which to serve the UI (usually ["/"]). By convention, this is the ui directory inside of the pkg directory that will be uploaded when you install the process. There must be an index.html in the "ui" directory (or whatever your top-level directory is called).

Under the hood, serve_ui uses http_bind_static_path which caches files in memory with http_server to respond to HTTP requests more quickly. The signature for http_bind_static_path is below:

pub fn bind_http_static_path<T>(
    path: T,
    authenticated: bool,
    local_only: bool,
    content_type: Option<String>,
    content: Vec<u8>,
) -> anyhow::Result<()>

The two additional parameters are the content_type (an optional String) and the content (bytes). The content will be served at the named route with the Content-Type header set appropriately.

Note that serve_ui caches all files in http_server, so if your website or web app has hundreds of MBs of asset files (like high-res images), then you will want to use a different method to serve content. In this case, you would bind the index.html file to your main route, and then bind a given HTTP route to serve all of your assets like so:

serve_index_html(&our, "ui", true, false, vec!["/"]).unwrap();
bind_http_path("/assets/*", true, false).unwrap();

Then in your request handler, you can use handle_ui_asset_request to get the file whose path matches the HTTP route of the request:

let body = message.body();
if let Ok(http_request) = serde_json::from_slice::<HttpServerRequest>(body) {
    match http_request {
        HttpServerRequest::Http(IncomingHttpRequest { url, .. }) => {
            if url.contains(&format!("/{}/assets/", our.process.to_string())) {
                return handle_ui_asset_request(our, "ui", &url);
            }
        }
        _ => {}
    }
}

handle_ui_asset_request takes our (&Address), the top-level directory that contains the files, and the url of the incoming request. In this case, the /assets directory must be in the /ui directory which must be uploaded from pkg when the process is installed. So your project would look like this:

my_package
└── pkg
    └── ui
        ├── assets
        └── index.html
Get Help: