This version of the documentation is outdated, and features documented here may work differently now. You can see the latest stable version of the docs here.
Hello World!
Let's get started with Perseus!
To follow along here, you'll want to be familiar with Rust, which you can learn more about here. You should also have it and cargo
installed.
To begin, create a new folder for your project, let's call it my-perseus-app
. Now, create a Cargo.toml
file in that folder. This tells Rust which packages you want to use in your project and some other metadata. Put the following inside:
[package]
name = "my-perseus-app"
version = "0.1.0"
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
perseus = { version = "0.3.6", features = [ "hydrate" ] }
sycamore = "0.7"
What are those dependencies doing?
perseus
-- the core module for Perseussycamore
-- the amazing system on which Perseus is built, this allows you to write reactive web apps in Rust
Note that we've set these dependencies up so that they'll automatically update patch versions, which means we'll get bug fixes automatically, but we won't get any updates that will break our app!
Don't I need an `index.html` file?
With versions of Perseus before v0.3.4, an index.html
file was required for Perseus to know how to display in your users' browsers, however, this is no longer required, as Perseus now has a default index view built in, with the option to provide your own through either index.html
or Sycamore code!
For the requirements of any index views you create, see below.
Now, create a new directory called src
and add a new file inside called lib.rs
. Put the following inside:
use perseus::{Html, PerseusApp, Template};
use sycamore::view;
#[perseus::main]
pub fn main<G: Html>() -> PerseusApp<G> {
PerseusApp::new().template(|| {
Template::new("index").template(|_| {
view! {
p { "Hello World!" }
}
})
})
}
How does that work?
First, we import some things that'll be useful:
perseus::{Html, PerseusApp, Template}
-- theHtml
trait, which lets your code be generic so that it can be rendered on either the server or in a browser (you'll see this throughout Sycamore code written for Perseus); thePerseusApp
struct
, which is how you represent a Perseus app; theTemplate
struct
, which represents a template in Perseus (which can create pages, as you'll soon learn -- this is the fundamental unit of Perseus)sycamore::view
-- Sycamore'sview!
macro, which lets you write HTML-like code in Rust
Perseus used to use a macro called define_app!
to define your app, though this has since been deprecated and replaced with a more modern builder struct
, which has methods that you can use to add extra features to your app (like internationalization). This is PerseusApp
, and here, we're just adding one template with the .template()
call (which you'll run each time you want to add a new template to your app). Here, we create a very simple template called index
, a special template name that will bind this template to the root of your app, this will be the landing page. We then define the view code for this template with the .template()
method on the Template
struct
, to which we provide a simple closure that returns a Sycamore view!
, which just renders an HTML paragraph element (<p>Hello World!</p>
in usual HTML markup). Usually, we'd provide a fully-fledged function here that can do many more things (like access global state stores), but for now we'll keep things nice and simple.
In most apps, the main things you'll define on PerseusApp
are Template
s, though, when you move to production, you'll also want to define ErrorPages
, which tell Perseus what to do if your app reaches a nonexistent page (a 404 not found error) or similar. For rapid development though, Perseus provides a series of prebuilt error pages (but if you try to use these implicitly in production, you'll get an error message).
Also notice that we define this PerseusApp
in a function called main
, but you can call this anything you like, as long as you put #[perseus::main]
before it, which turns it into something Perseus can expect (specifically, a special function named __perseus_entrypoint
).
Now install the Perseus CLI with Perseus is a very complex system, and, if you had to write all that complexity yourself, that Hello World! example would be more like 1200 lines of code than 12! The CLI lets you abstract away all that complexity into a directory that you might have noticed appear called When you run The first time you run this command, it can take quite a while to get everything ready, but after that it'll be really fast. And, if you haven't changed any code (at all) since you last ran it, you can run cargo install perseus-cli --locked
(you'll need wasm-pack
to let Perseus build your app, use cargo install wasm-pack
to install it) to make your life way easier, and deploy your app to http://localhost:8080 by running perseus serve
inside the root of your project! This will take a while the first time, because it's got to fetch all your dependencies and build your app.Why do I need a CLI?
.perseus/
. If you take a look inside, you'll actually find three crates (Rust packages): one for your app, another for the server that serves your app, and another for the builder that builds your app. These are what actually run your app, and they import the code you've written. They interface with the PerseusApp
you define to make all this work.perseus serve
, the .perseus/
directory is created and added to your .gitignore
, and then three stages occur in parallel (they're shown in your terminal):.perseus/dist/static
, which makes your app lightning-fast (your app's pages are ready before it's even been deployed, which is called static site generation, or SSG)perseus serve --no-build
to run the server basically instantaneously.
Once that's done, hop over to http://localhost:8080 in any modern browser (not Internet Explorer...), and you should see Hello World! printed on the screen! If you try going to http://localhost:8080/about or any other page, you should see a message that tells you the page wasn't found.
Congratulations! You've just created your first ever Perseus app! You can see the source code for this section here.
Moving Forward
The next section creates a slightly more realistic app with more than just one file, which will show you how a Perseus app is usually structured.
After that, you'll learn how different features of Perseus work, like incremental generation (which lets you build pages on-demand at runtime)!
Alternatives
If you've gone through this and you aren't that chuffed with Perseus, here are some similar projects in Rust:
- Sycamore (without Perseus) -- A reactive library for creating web apps in Rust and WebAssembly.
- Yew -- Rust/Wasm framework for building client web apps.
- Seed -- A Rust framework for creating web apps.
- Percy -- Build frontend browser apps with Rust + WebAssembly. Supports server side rendering.
- MoonZoon -- Rust Fullstack Framework.