Static content

As nice as it is to write everything in Rust, you will, in web development, undoubtedly have to have some static content eventually. This is usually in the form of stylesheets, or images, or even binaries that your users can download, but there will be something. This is where Perseus' static content system comes into play. The simplest way to use this is through a static/ directory in the root of your project, which Perseus will serve at /.perseus/static. For example, if you create static/index.css, that will be available in a <link rel="stylesheet" /> tag at href=".perseus/static/index.css". Notice the lack of a leading forward slash! This is because it's unnecessary: Perseus implants a <base /> tag that makes it so, and this makes your app flexible to being served at relative paths (like framesurge.sh/perseus).

Here's an example of how you might link a CSS file (in static/index.css in your project):

#[engine_only_fn]
fn head(cx: Scope) -> View<SsrNode> {
    view! { cx,
        title { "Page Title" }
        link(rel="stylesheet", href=".perseus/static/index.css") {}
    }
}

Sometimes, however, you'll want static content from outside static/, which is where static aliases come into play. These allow you to link in arbitrary files hosted at arbitrary paths, which will be served unquestioningly by Perseus. You can declare static aliases on your PerseusApp like so:

mod templates;

use perseus::prelude::*;

#[perseus::main(perseus_axum::dflt_server)]
pub fn main<G: Html>() -> PerseusApp<G> {
    PerseusApp::new()
        .template(crate::templates::index::get_template())
        .error_views(ErrorViews::unlocalized_development_default())
        .static_alias("/static/test.txt", "test.txt")
}

The first argument to .static_alias() is the path at which the file should be hosted, and the second is the path to the file, relative to the root of your project. Importantly, Perseus will reject any files outside the root of your project, simply because this can be a major security risk: static aliases are resolved at runtime, so if you set a ../../passwd static alias, and that happens to map to an innocuous file on your local system, but a sensitive file on your server, that's a big problem! If you need access to such files, use symbolic links (which Perseus will begrudgingly work with).

Generated static content

Usually, when static content is generated by an external tool, like a CSS bundler, or a plugin, it's better to put it in dist/, where it will be ignored by the the -w part of perseus serve -w and similar commands. This will also be exempt from version control, keeping your Git repos a bit more lightweight.