Roq Advanced Stuff

Pagination

Adding pagination to your Roq site is an easy way to improve content navigation. Let’s walk through how to implement pagination and customize its behavior in your site.

Step 1: Iterate on the paginated collection

First, include the following in your FrontMatter header on the page which will iterate on the paginated collection:

paginate: posts

Next, in your template, loop through the paginated posts using:

{#for post in site.collections.posts.paginated(page.paginator)} (1)
<article class="post">
  ...
</article>
{/for}

{#include includes/pagination.html/}
1 Calling .paginated(page.paginator) will resolve to the posts for the computed page.

Step 2: Including Pagination Controls

To add pagination controls, use the provided fm/pagination.html in your own _includes/pagination.html:

{#include fm/pagination.html}
{#newer}<i class="fa fa-long-arrow-left" aria-hidden="true"></i>{/newer}
{#older}<i class="fa fa-long-arrow-right" aria-hidden="true"></i>{/older}
{/include}
If you want to write your own controls, find inspiration in the FM sources fm/pagination.html.

Just by doing so, Roq will generate a bunch of pages based on the pagination setting. For example with a pagination size of 4 and with 9 posts, you would get:

  • index.html (posts 1 to 4)

  • posts/page-2 (posts 5 to 8)

  • posts/page-3 (post 9)

the first page uses the declaring page link.

You can further customize your pagination by setting the page size and link format:

paginate:
  size: 4
  collection: posts
  link: posts/page-:page

With these steps, you can create a flexible pagination system to improve your site’s navigation.

SEO

Incorporating search engine optimization (SEO) is as simple as inserting this tag into your <head> section:

<head>
{#seo page site /}
</head>

It will automatically use the FrontMatter data to fill the tags.

<title>My Blog Post</title>
<meta name="author" content="ia3andy" />
<meta name="generator" content="Quarkus Roq v1.0.0" />
<meta property="article:author" content="ia3andy" />
<meta property="article:published_time" content="2024-09-23T12:00Z[Etc/UTC]" />
<meta property="og:image" content="https://images.unsplash.com/photo.webp" />
<meta property="og:locale" content="en-US" />
<meta property="og:type" content="article" />

RSS

Incorporating and RSS feed of your posts is as simple as inserting this tag into your <head> section:

<head>
{#rss site /}
</head>

It will automatically use the FrontMatter data generate an RSS feed link.

<link rel="alternate" type="application/rss+xml" title="Your Blog" href="/rss.xml"/>

It will automatically utilize the Frontmatter data from all your blog posts to generate a valid Atom RSS feed link at rss.xml. Ensure you create an rss.xml file at the root of your site and include this single line of code:

{#include fm/rss.html}

Themes

Overriding theme layouts

In Roq, you can override theme layouts by inserting an extra layout layer. This allows you to override only specific sections of the theme layout, without duplicating the entire layout structure.

Roq layouts are leveraging Qute includes under the hood. It is possible to define insert sections which can define overridable default content.

For example, let’s override the roq-default theme’s main layout so that our customizations apply everywhere it is used.

templates/layouts/roq-default/main.html
---
layout: theme-layouts/roq-default/main (1)
---

{#insert /} (2)

{#description} (3)
Here I can override the description section
{/}

{#footer}
<footer>
And here the footer
</footer>
{/}
1 Inherits from the theme layout: This layout uses the original theme layout (roq-default/main) as a base.
2 Inheritance mechanism: {#insert /} ensures that this layout will inherit sections defined in the theme layout.
3 Override specific sections: You can override individual sections such as description and footer without affecting other parts of the layout.

Now, everywhere layouts: :theme/main (even in the theme), your override will be used.

Developing a theme

To develop a theme, create a Maven module which will contain the theme layouts, partials, scripts and styles.

.
└── main
    ├── resources
    │   ├── application.properties
    │   └── templates
    │       ├── partials
    │       │   └── roq-default (1)
    │       │       ├── head.html
    │       │       ├── pagination.html
    │       │       ├── sidebar-about.html
    │       │       ├── sidebar-contact.html
    │       │       ├── sidebar-copyright.html
    │       │       └── sidebar-menu.html
    │       └── theme-layouts (2)
    │           └── roq-default
    │               ├── default.html
    │               ├── index.html
    │               ├── main.html
    │               ├── page.html
    │               ├── post.html
    │               └── tag.html
    └── web
        ├── roq.js
        ├── roq.scss
1 You can add partials for your theme, they need to be located in a directory with the theme name.
2 Layouts needs to be declared in the theme-layouts so that they can be overridden by consuming websites.

Same as for a site, script and styles can either be added to src/main/resoucres/META-INF/resources or bundled using Maven esbuild plugin:

pom.xml
             <plugin>
                <groupId>io.mvnpm</groupId>
                <artifactId>esbuild-maven-plugin</artifactId>
                <version>0.0.2</version>
                <executions>
                    <execution>
                        <id>esbuild</id>
                        <goals>
                            <goal>esbuild</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <entryPoint>roq.js</entryPoint> (1)
                </configuration>
                <dependencies> (2)
                    <dependency>
                        <groupId>org.mvnpm.at.fortawesome</groupId>
                        <artifactId>fontawesome-free</artifactId>
                        <version>6.6.0</version>
                    </dependency>
                    <dependency>
                        <groupId>org.mvnpm.at.fontsource</groupId>
                        <artifactId>pt-serif</artifactId>
                        <version>5.1.0</version>
                    </dependency>
                </dependencies>
            </plugin>
1 Add your esbuild entrypoint from src/main/resources/web
2 Add mvnpm or webjars dependencies

This bundle will be available in /static/bundle/roq.js and /static/bundle/roq.css which can be used in your theme html <head>

Create an application.properties:

src/main/resources/application.properties
site.theme=roq-default (1)
1 Thanks to this, all call to layout: :theme/…​ will automatically refer to this theme.

The output location of pages and documents is determined by the FrontMatter link key. This link value can include placeholders, which will be dynamically replaced with relevant values for routing.

Those links are also available in the Qute data to allow Creating links between your pages.
Type of page Placeholder Description Example Output

All

:path

The file path of the page, slugified (converted to a URL-friendly format) without the extension.

my-page, search or docs/my-doc

All

:slug

The slugified title of the page, derived from the title. Defaults to the slug property in data, if available or using the slugified title, falling back to the file name.

my-page-title

All

:ext

The file extension with the dot. Empty for all files with html output (md, asciidoc, html, …​).

.json

All

:ext!

Force the output file extension.

.html, .json

All

:year

The year of the page’s date or the current year if the date is not available.

2024

All

:month

The month (formatted as two digits) of the page’s date or the current month if the date is not available.

10

All

:day

The day (formatted as two digits) of the page’s date or the current day if the date is not available.

28

Document

:collection

Represents the collection to which the document belongs, such as a specific category or folder name.

blog, articles, recipes

Paginated

:page

Represents the current page.

1, 2

Default link value:

  • for pages: /:path:ext.

  • for documents: /:collection/:slug/.

  • for paginated page: /:collection/page:page/.

You can define link in a layout to affect all the pages using that layout.

Creating links between your pages

The pages links are automatically converted to urls by Roq, they are available in the site.url and the page.url variables. This makes creating links very easy:

<a href="{site.url}">Back to main page</a>

or to get the next page url in a document:

<a href="{page.next.url}">{page.next.title}</a>

or when iterating on documents:

{#for post in site.collections.posts}
  <a href="{post.url}">{post.title}</a>
{/for}

or also to manually retrieve a page url with site.page(sourcePath):

<a href="{site.page('foo.html').url}">{site.page('foo.html').title}</a>
By default, url will be rendered as relative from the site root. You can also get the full absolute url (i.e. from http(s)://) by using absolute on any url (e.g. {site.url.absolute}).

Manual linking

Sometimes, you want to create a link for a page without holding the variable, in this case, you can use site.url(relativePath) which will be automatically resolved from the site root path.

Site Configuration

Site configuration is done in config/application.properties (or src/main/resources/application.properties):

Configuration property fixed at build time - All other configuration properties are overridable at runtime

Configuration property

Type

Default

The root path of your site (e.g. /blog) relative the quarkus http root path. This is to be used only when the site is living next to a Quarkus application. Use quarkus.http.root-path for GitHub Pages relative url.

Environment variable: SITE_ROOT_PATH

string

/

the base hostname & protocol for your site, e.g. http://example.com

Environment variable: SITE_URL

string

The order of the route which handles the templates. <p> By default, the route is executed before the default routes (static resources, etc.).

Environment variable: SITE_ROUTE_ORDER

int

1100

The ignored files in the site directory (you can use glob expressions).

Environment variable: SITE_IGNORED_FILES

list of string

/,,.

The layout to use for normal html pages if not specified in FM. When empty, the page will not use a layout when it doesn’t specify it in FM. ":theme/" is removed if no theme is defined.

Environment variable: SITE_PAGE_LAYOUT

string

:theme/page

The directory which contains content (pages and collections) in the Roq site directory.

Environment variable: SITE_CONTENT_DIR

string

content

The directory (dir name) which contains static files to be served (with 'static/' prefix).

Environment variable: SITE_STATIC_DIR

string

static

The directory which contains public static files to be served without processing (dir name)

Environment variable: SITE_PUBLIC_DIR

string

public

The path containing static images (in the public directory)

Environment variable: SITE_IMAGES_PATH

string

images/

When enabled it will select all FrontMatter pages in Roq Generator

Environment variable: SITE_GENERATOR

boolean

true

Show future documents

Environment variable: SITE_FUTURE

boolean

false

This will be used to replace :theme when resolving layouts (e.g. layout: :theme/main.html)

Environment variable: SITE_THEME

string

Show draft pages

Environment variable: SITE_DRAFT

boolean

false

Format for dates

Environment variable: SITE_DATE_FORMAT

string

yyyy-MM-dd[ HH:mm][:ss][ Z]

The default timezone

Environment variable: SITE_TIME_ZONE

string

document timezone if provided or system timezone

If this collection is enabled

Environment variable: SITE_COLLECTIONS__COLLECTIONS_MAP_

boolean

true

Show future documents (overrides global future for this collection)

Environment variable: SITE_COLLECTIONS__COLLECTIONS_MAP__FUTURE

boolean

false

If true, the collection won’t be available on path but consumable as data.

Environment variable: SITE_COLLECTIONS__COLLECTIONS_MAP__HIDDEN

boolean

false

The layout to use if not specified in FM data. When empty, the document will not use a layout when it doesn’t specify it in FM. ":theme/" is removed if no theme defined.

Environment variable: SITE_COLLECTIONS__COLLECTIONS_MAP__LAYOUT

string