Adding dynamic pages

Modern web applications are often characterized by their ability to generate content dynamically, tailoring web pages based on user interactions, database queries, or other factors. This guide provides an overview of how to create web pages with dynamic content.

Dynamic content refers to the parts of a web page that change based on varying factors such as user input, database changes, or real-time data. Instead of serving static HTML files, the server generates the content of the page on-the-fly, often pulling from databases or other data sources.

Pages in a route

For simple pages displaying short messages or static content, you can add the page directly in the route definition with the do end syntax:

using Genie, Genie.Renderer.Html
route("/message") do
    $name = "John"
    h1("Welcome to Genie $name !")
end

Note that we are using Genie and not GenieFramework as we don't need the reactive features provided by the Stipple package.

Defining pages in a file

You can define the page's code in a file and include it as

route("/message") do
    name = "John"
    html(Genie.Renderer.filepath("message.jl"), name=name)
end
message.jl
h1("Welcome to Genie $name !")

The html function renders the code and adds information to the HTTP response header.

You can also use HTML by directly replacing the Julia code and files with HTML strings and files.

route("/message") do
    html(Renderer.filepath("pages/message.jl.html"))
end

message.jl.html
<h1>Welcome to Genie $name !</h1>

Executing Julia code in a page

It is possible to embed Julia code in a page's code that will be executed when the page is loaded. To do so, use the $ interpolation operator to wrap Julia code as

low-code
p("1+1 is: $(1+1)")
HTML
<p>1+1 is: $(1+1)</p>

To include multiline code blocks, use the <% and %> delimiters as

HTML
<p>
    <% for i in 1:3 %>
    $i
    <% end %>
</p>

Remember to always pass any variable to be printed to the html renderer.

Including static assets

To display static assets such as images, or include assets in the head of a page, place them first in the public folder. They will be automatically picked up by the server and served at the root path /. Then, the assets can be included in any page like in the example below.

.
├── app.jl
├── public/
│   ├── style.css
│   ├── meta.png
│   └── fig.png
app.jl

function assets()
[
    head([
        meta(charset="utf-8")
        meta(name="og:image", content="/meta.png")
        link(rel="stylesheet", href=("/style.css"))
        title("Including assets")
    ])
    body([
            img(src="/fig.png",alt="plot")
        ])
]
end
@page("/", assets)

Using layouts

A layout definition is useful to set a common structure across pages, such as when adding a navigation bar. You can define layouts and pass them to the html function as

function layout()
    #the layout kwarg takes a string, so we join the HTML strings
    join([head(title("Genie app")),
     body([h1("Welcome!"), "<% @yield %>"])])
end
ui() = p("Genie!")

@page("/layout", ui, layout=layout())

Here, @yield injects the page's content into the layout.