6 Static Files
Web applications frequently need to deliver assets which do not change on every request: HTML pages, CSS stylesheets, JavaScript bundles, images, fonts, or other files stored on disk.
Ambiorix provides a straightforward way to expose such files via the app$static() method, without extra routing logic or additional handlers.
6.1 Serving a Directory
Expose a folder on disk and map it to a URL prefix:
app$static(path = "public", uri = "static")path: <String>, <Required>. Path pointing to the directory on your filesystem.uri: <String>, <Optional>. The URL prefix under which the folder becomes publicly accessible. If not specified, defaults to “www”.
With the example above, any file placed in public/ becomes available at:
/static/filename
For example:
| File System | Mapped URL |
|---|---|
public/styles.css |
/static/styles.css |
public/main.js |
/static/main.js |
public/images/logo.png |
/static/images/logo.png |
6.2 Multiple Static Directories
If you need to serve multiple directories as static content, simply call app$static() multiple times with different path & uri values.
For example:
app$static(path = "public", uri = "static")
app$static(path = "assets", uri = "assets")6.3 Example App
Say you have lots of photos of your cats. Let’s build a photo gallery.
6.3.1 Setup
Create a new directory for the project and switch to it:
mkdir photo-gallery cd photo-galleryIn the project directory, create a new directory called
public/:mkdir publicCreate an
images/directory inpublic/.mkdir public/imagesPlace the photos of your cats in the
public/images/dir.We’ll want some minimal styling for the images, so create the file
styles.cssin thepublic/dir:touch public/styles.cssFinally, create an
index.Rfile in the root dir of the project:touch index.R
At this point, your file tree structure should look something like this:
.
├── index.R
└── public
├── images
│ ├── 0.jpeg
│ ├── 1.jpeg
│ ├── 2.jpeg
│ ├── 3.webp
│ ├── 4.webp
│ ├── 5.avif
│ ├── 6.jpeg
│ ├── 7.jpg
│ ├── 8.jpeg
│ └── 9.webp
└── styles.css
6.3.2 index.R
Load {ambiorix} and {htmltools}, instantiate a new Ambiorix application, and set the static directory:
library(ambiorix) library(htmltools) app <- Ambiorix$new() app$static(path = "public", uri = "static")Define a generic UI
Page():#' Generic UI page #' #' @param ... [htmltools::tags] Passed to the HTML #' document body. #' #' @return [htmltools::tagList] #' #' @export Page <- function(...) { tagList( HTML("<!doctype html>"), tags$html( lang = "en", tags$head( tags$title("Photo Gallery"), tags$link( rel = "stylesheet", href = "/static/styles.css" ) ), tags$body( ... ) ) ) }Define a handler for
GETrequests at/(the “home page”):#' Handle GET at '/' #' #' @export home_get <- function(req, res) { img_names <- list.files(path = file.path("public", "images")) img_src <- paste0("/static/images/", img_names) img_tags <- lapply( X = img_src, FUN = \(src) { tags$img( src = src, loading = "lazy" ) } ) img_content <- tags$div( class = "img-content", img_tags ) html <- Page(img_content) res$send(html) }Attach the handler and start the app on port 8000:
app$get("/", home_get) app$start(port = 8000L)
Up to this point, you should be able to run the app and see the photo gallery.
It looks a bit ugly and unstructured, let’s add a wee bit of styling to it.
6.3.3 public/styles.css
For the document body:
- Remove all default outer margin applied by browsers.
- Set an all-round padding inside the body.
- Use a dark background
body { margin: 0; padding: 40px; background: #0f1117; }For the container of the images:
- Turn the container into a CSS Grid layout, enabling structured rows/columns.
- Create 3 equal-width columns.
1frmeans 1 fraction of the available space. - Insert a gap between all grid items (both rows & columns).
.img-content { display: grid; grid-template-columns: repeat(3, 1fr); gap: 5px; }Finally, for the images in that container:
- Make each image fill the full width of its grid column.
- Set a fixed height.
- Crop the image as needed to maintain aspect ratio while filling the width/height box.
- Slightly round the image corners.
.img-content img { width: 100%; height: 300px; object-fit: cover; border-radius: 5px; }
6.3.4 Results
When you hard-refresh the browser, the photo gallery will be more palatable to the eye.