Ignore

Please note that your browser is not supported.

We recommend upgrading to the latest Firefox or Google Chrome.

Frontend: Composition

Pakyow lets you define frontend view templates and assets in separate parts that are composed together to build a complete interface. This guide explores the various types of view and asset templates and how they're composed together to build a complete view.

Pakyow implements a dynamic templating engine using native HTML. This means that you're to create complete interfaces just by defining templates. There's no coding required—in fact you'll never leave the frontend folder!

Organizing view templates

Pakyow builds the content, or view, for a request based on the request path. Frontend view templates, along with assets, are defined in a structure mirroring the request paths that your application will serve content for. These paths are called presentation paths.

For example, a simple chat app might have two presentation paths:

  1. Index, which presents a list of messages.

  2. Show, which presents a single message and its details.

Here's how the view templates for this application would be organized:

frontend/
  layouts/
    default.html
  pages/
    index.html
    messages/
      show.html

There are three types of view templates: pages, layouts, and partials.

Pages, located in the frontend/pages folder, define content for a specific page in your application. When the application receives a request, the page matching the request path is chosen for composition.

For example, a request to http://your-app.com/ will match the index page located at frontend/pages/index.html. When a matching page is found, it's composed with a layout to form a complete view.

Layouts, located in the frontend/layouts folder, define the common elements that are used across several pages—such as a header, footer, or sidebar. The default.html layout is used by default, or pages can define a specific layout to use (this is discussed more below).

Each layout defines one or more containers, each one defining where content from a page should be mixed in. Below is the default.html layout that you'll find in a generated project:

frontend/layouts/default.html
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
</head>

<body>
  <!-- @container -->
</body>
</html>

This layout defines a single, unnamed container. During composition, the <!-- @container --> comment, or directive is replaced with content from the matching page. Let's step through a complete example to be more clear about how.

Pakyow receives a request at http://your-site.com/ and chooses the frontend/pages/index.html page based on the presentation path. Here's the page content:

frontend/pages/index.html
<h1>
  Hello Web
</h1>

The fully composed view would look like this:

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
</head>

<body>
  <h1>
    Hello Web
  </h1>
</body>
</html>

The <!-- @container --> directive in the layout was replaced with the page content just as we expected. Pakyow sends the fully composed view in the response, which is presented in the user's web browser.

Advanced presentation paths

Presentation at nested paths are also supported. Looking at the previous example, requests to http://your-site.com/messages/show would match the frontend/pages/messages/show.html page. This page would be composed into the layout and then rendered as before.

In reality, the request path for a page like this will be based on the message that was to be presented. For example, the full url look like this:

In cases like this it's typical for same underlying template to be rendered for multiple requests, with only the data changing between requests. We'll cover this type of dynamic presentation in the next guide on data bindings.

Reusing content with partials

Partials are the third type of view template designed to break your frontend templates into even smaller, more reusable pieces. Using partials, you can move the common parts of a view template into its own file and then include it whenever you need it.

Partials are placed alongside pages in the frontend/pages folder, but are prefixed with an underscore. Here's an example view structure that contains a layout, page, and a partial named _messages.html:

frontend/
  layouts/
    default.html
  pages/
    _messages.html
    index.html

Here's the content of the _messages.html partial:

frontend/pages/_messages.html
<article>
  <h1>this is a message</h1>
</article>

Partials are included into other view templates using the @include directive. For example, the index.html page can include the partial like this:

<h1>
  Here are your messages:
</h1>

<!-- @include messages -->

The composed view would look like this:

<h1>
  Here are your messages:
</h1>

<article>
  <h1>this is a message</h1>
</article>

Partials can be included into any view template—pages, layouts, or even other partials. This simple feature gives you a lot of power to build a flexible frontend while reducing duplication.

Defining partials for nested presentation paths

Partials can be defined at any presentation path, including nested paths. More specific presentation paths will inherit partials from parent paths and can override specific partials as necessary.

The _messages.html partial from above can be redefined at the show path, making it available to any view template within the show path. Let's build up a complete example, starting with one top-level partial:

frontend/
  layouts/
    default.html
  pages/
    _messages.html
    show/
      index.html

The show path inherits the messages partial and can include it:

frontend/pages/show/index.html
<!-- @include messages -->

The show path can override the inherited partial by defining a view template at show/_messages.html. This more specific partial will be used when included by templates within the frontend/pages/show presentation path, while other presentation paths will include the frontend/pages/_messages.html partial.

Defining global partials

Partials can also be defined globally, making them includable into any view template, including layouts. Global partials are defined by creating a view template in the frontend/includes folder:

frontend/
  includes/
    messages.html
  layouts/
    default.html
  pages/
    index.html

Unlike other partials, filenames for global includes are not prefixed with an underscore. But otherwise they behave just like other partials and can be included with the same @include directive:

<!-- @include messages -->

Composing assets for view templates

Stylesheets and Scripts can be added to the frontend folder and composed together just like layouts, pages, and partials. Let's revisit the example from above and add in a few assets to illustrate how asset composition works:

frontend/
  layouts/
    default.html
    default.css
  pages/
    index.html
    messages/
      show.html
      show.js

Here we define two stylesheets, along with a single messages/show.js script. The default.css stylesheet will automatically be included into any page that uses the default layout. The show.js script will be included into the the messages/show.html page when rendered.

Composed assets are automatically included as an asset pack in the <head> section of the composed view.

Using multiple named containers

Layouts can define any number of containers, each with a unique name. Here's a layout that defines a footer container to go along with the standard default container:

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
</head>

<body>
  <!-- @container -->

  <footer>
    <!-- @container footer -->
  </footer>
</body>
</html>

Defining content for a named container happens with the @within directive in a page:

frontend/pages/index.html
<h1>
  Hello Web
</h1>

<!-- @within footer -->
  Custom Footer Content
<!-- /within -->

The composed view looks like this:

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
</head>

<body>
  <h1>
    Hello Web
  </h1>

  <footer>
    Custom Footer Content
  </footer>
</body>
</html>

Specifying the layout for a page

In cases where you want to use a layout other than default.html, the page can specify the layout in its front-matter. For example, here's how to use a layout named other.html for a page:

frontend/pages/index.html
---
layout: other
---

...

Directive reference

Here's a full list of frontend directives you'll use in your view templates:

  • @container: Defines a default or named container in a layout.
  • @within: Defines content for a named container in a page.
  • @include: Includes a partial into another view template.

Each directive is placed inside an HTML comment, like this:

<!-- @container -->
Next Up: Data Bindings