Layouts are used in conjunction with regions to organize the various component parts that will be placed on the page via live edit drag and drop. Layouts can be dropped into the page regions and then parts can be dragged into the layout. This allows multiple layouts (two-column, three-column, etc.) on the same page and web editors can change things around without touching any code. Layouts can even be nested. Making a layout is similar to making pages and part components.

Layout contains - like pages and parts - a descriptor, a view and a controller, and should be placed in under the layouts-folder in the module: layouts/<layoutname>/


The layout descriptor defines regions within the layout where parts can be placed with live edit.

    <region name="left"/>
    <region name="right"/>


The layout controller composes the view of the layout based on http-requests.

exports.get = function(req) {

  // Find the current component.
  var component = execute('portal.getComponent');

  // Resolve the view
  var view = resolve('./layout-70-30.html');

  // Define the model
  var model = {
    component: component,
    leftRegion: component.regions["left"],
    rightRegion: component.regions["right"]

  // Render a thymeleaf template
  var body = execute('thymeleaf.render', {
    view: view,
    model: model

  // Return the result
  return {
    body: body,
    contentType: 'text/html'



A layout view defines the markup for the layout-component. The sample view below is created in Thymeleaf, but you could create it in any view that’s supported.

<div class="row" data-th-attr="data-portal-component-type=${component.type}">
  <div data-portal-component-type="region" class="col-sm-8">
    <div data-th-each="component : ${leftRegion.components}" data-th-remove="tag">
      <div data-portal-component="${component.path}" data-th-remove="tag" />

  <div data-portal-component-type="region" class="col-sm-4" >
    <div data-th-each="component : ${rightRegion.components}" data-th-remove="tag">
      <div data-portal-component="${component.path}" data-th-remove="tag" />


For a layout to have any meaning, some styling must be applied to the view. Depending on preferences, the needed css should be placed in the /assets-folder of the module, and included in the page where the layout should be supported, e.g the view my-first-page.html should support bootstrap layouts:

  <meta charset="utf-8"/>
  <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
  <link data-th-href="${portal.assetUrl({'_path=css/bootstrap.min.css'})}" href="../assets/css/bootstrap.min.css" rel="stylesheet"/>