Props

Any content in your app has access to a basic set of information shared between pages and its respective layouts when rendering to generate the final HTML document.

This information is stored in the props variable.

While part of this information comes directly from the app router (like uri and params) that can be used to retrive information or generate data, other props can be configured throught magic methods defined in page.js and layout.js when needed (like title, icons, metadata, styles and scripts). This information will be used to generate the <head> tag in th HTML document.

The content prop is very important to the renderer, it contains the generated HTML from the page to the layouts following the nesting process in a route. See more about nesting.

Using Props

As we saw in rendering, layout.js and page.js have a content function returning the generated HTML part.

This function will always receive all these props:

PROP TYPE Description
title string The Page Title
icons object List of Favicons
metadata object All metadata
styles array List of css files
scripts array List of javascripts files
content array Current rendered content
params object URL params
uri string Current URI
data object Request Data

So you can use this information to create the content in any way.

For example, if using a dynamic route we can use the dynamic part of the segment in params prop to create the content.

return {
  content: (props) => {
    const article = getArticle(props.params.id);
    if (!article) {
      return { redirect: "/not-found" };
    }
    return `
      <article>
        <h1>${article.title}</h1>
        <div class="summary">${article.summary}</div>
        <div class="author">${article.author}</div>
        <div class="published">${article.published}</div>
        <div class="content">${article.content}</div>
      </article>
    `;
  }
}

When using layout.html and page.html this props can be accessed by ${props.*} tokens directly written into the HTML.

return {
  title: (props) => {
    return "Dashboard";
  }
}
...
<h1>
  <a href="${props.uri}">
    ${props.title}
  </a>
</h1>
...

Good to know

You can add custom props to extend this functionality in many ways. Learn how to do it in Custom Props section.

Setting Props

To modify the <head> HTML elements such as <title> and <meta> tags Previous.js provides these magic methods.

Method Return Description
title string Sets the page title.
icons object Sets the favicon and other icons.
styles array Add a list of stylesheet files.
sctipts array Add a list of javascript files.
metadata object Sets any other metadata. For example all SEO content like description, author, viewport, etc.
type string Define the content type.

All these methods can be used in pages and layouts and its props will be updated by the renderer using the nesting from pages to layouts.

This means any prop set in a page can be used in the layout too.

return {
  title: (props) => {
    return 'My First Page';
  }
}
return {
  title: (props) => {
    return 'My App :: ' + props.title;
  }
}

In the example above we set the title in page and the layout use this title adding a prefix to it. So the final document title will looks like:

<html>
<head>
  ...
  <title>My App :: My First Page</title>
  ...
</head>
<body>
  ...
</body>
</html>

Good to know

Some of these magic methods (like styles and scripts) will append the list sequentially in a determinated order. See more in Styles and Scripts sections.

Title

Any page or layout can manage its title by extending the returning object with the method title.

return {
  title: (props) => {
    return 'My First Page';
  },
  content: ({ title }) => {
    return `<h1>${title}</h1>`;
  }
}

Good to know

You should not manually add <head> tags such as <title> and <meta> to root layouts.

This method will always receive all the page props to process any information before returning the final title.

When using Layouts you can use nesting to generate a composed title:

return {
  title: (props) => {
    return 'My App - ' + props.title;
  }
}

The resulting HTML will looks like this:

<html>
<head>
  ...
  <title>My App - My First Page</title>
  ...
</head>
<body>
  ...
  <h1>My First Page</h1>
  ...
</body>
</html>

Icons

Use this method to add a favicon or other icons to your Web App that appear in places like web browser tabs, phone home screens, and search engine results.

The returning object must have a key with the icon you want to add and a value with the public path to an icon resource in your project or an external URL.

return {
  icon: (props) => {
    return {
      'icon': '/favicon.ico',
      'shortcut icon': '/shortcut-icon.png',
      'apple-touch-icon': '/apple-icon.png'
    };
  }
}

Remember! Do not forget to put '/' at start of the URL to refer a resource from public folder.

The resulting HTML will looks like this:

<html>
<head>
  ...
  <link rel="icon" href="/favicon.ico" />
  <link rel="shortcut icon" href="/shortcut-icon.png" />
  <link rel="apple-touch-icon" href="/apple-icon.png" />
  ...
</head>
...
</html>

Good to know

You should not manually add <link rel="icon" ...> tag.

Styles

This prop allows you to style your application with CSS.

Use this method to setup a list of stylesheet URLs you want to include in the final document.

return {
  styles: (props) => {
    return [
       '/vendor/library/custom.css',
       '/css/main.css',
    ];
  }
}

This prop will apend the list of CSS files in inverse order from route hierarchy but maintaining the order in the list.

This means CSS files from root layout will be loaded always before page CSS files.

This allows the web application to load the main dependencies first and in the same order.

Good to know

You should not manually add <link rel="..."> tag.

Important!

When navigating between pages, Previous.js will autoload stylesheets from diferent pages once. So the loading order will follow the navigation order and all previously loaded stylesheets will remain loaded. Ensure your page styles do not use generic selectors if you want to only work on that page.

Scripts

By default, Previous.js comes with jQuery so you do not need to include this library, but sometimes your app will need some aditional scripts to create an slider, control the UI of your App or add other interactions.

Use this method to create a list of scripts you want to include in the final page.

return {
  scripts: (props) => {
    return [
       'https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js',
       '/vendor/library/custom.js',
       '/js/app.js',
    ];
  }
}

Like the styles prop, this prop will apend the list of JS files in inverse order from route hierarchy but maintaining the order in the list.

This means JS files from root layout will be loaded always before page JS files.

This allows the web application to load the main dependencies first and in the same order.

Good to know

You should not manually add <script src="..."></script> tag.

If you need to run any script after the page is loaded, then you have to use the ready method.

return {
  ...
  ready: () => {
    console.log('Hello, page loaded!');
    // Call other methods...
  }
}

This script will be executed any time you enter the page.

Good to know

Do not use the onload jQuery function $(function() { ... }); on your scripts. Better use the ready function.

Important!

When navigating between pages, Previous.js will autoload scripts from diferent pages once. So this scripts will only run once.

Metadata

This method provides a way to write any type of Metadata different than described above.

This information could be interesting to powerup SEO descriptions in your Web App.

It must return an object with a key value-pair corresponding with name and content of a <meta> tag.

Here is an example of some of the porperties you can define with this methor.

return {
  metadata: (props) => {
    return {
      description: "My awesome description",
      keywords: "Previous.js,jQuery,JavaScript",
      author: "necro_txilok",
      viewport: "width=device-width, initial-scale=1",
      "prop:og:title": "Previous.js"
    };
  }
}

Good to know

You should not manually add <meta name="..." content="..."> tag.

Sometimes we need to add different metadata depending on the page we are navigating, so you can use this method in page.js to setup with the needed metadata.

If the same property is set in some of the wrapped layouts the page information will have preference over the layouts.

return {
  metadata: (props) => {
    return {
      description: "The Dashboard Page ;)"
    };
  }
}

Type

If you need to return a page in a different format than text/html use this method do change the content-type header in the returning response.

For example you can create a page in plain text like this:

return {
  type: 'text/plain',
  content: (props) => {
    return 'Hola Mundo!';
  }
}

Custom Props

Sometimes we need to add custom data to props for using later in content renderer even in parents layouts.

You can do this by defining the data method and returning an object with the extra data like this:

return {
  data: (props) => {
    return {
      year: (new Date()).getFullYear()
    };
  }
}

So you can use it in the page content:

...
<p>Created in ${props.year}.</p>
...


And in layout, for example:

return {
  metadata: (props) => {
    return {
      year: props.year
    };
  }
}

Learn more about using custom props in Components or Data sections.