In this beginner tutorial, you will create a simple web page based on a custom-built light module called hello-magnolia. Your light module will provide a page template and a custom quotation component for a web page. You will learn how to get content from a repository and display it on the page. You will develop the page using Magnolia CLI, an npm package which facilitates light development with Magnolia.

Magnolia CLI is available in several release versions. This tutorial has been checked against Magnolia CLI version 3.1.0.

(warning) Are you planning a 'headless' project? Start with the My first content app tutorial.

Getting Magnolia

For development and testing you need a running instance of Magnolia. In this tutorial, we suppose that it is installed in a directory called magnolia.

If you don't have Magnolia installed and running, go to the page called Installing Magnolia through npm CLI and complete the steps described on it. Then, return and proceed from here.

Creating the light module

In this section, you create the hello-magnolia module.

  1. Open a terminal.
  2. Go to the light-modules folder of your Magnolia installation:
  3. Run the following command:

    mgnl create-light-module hello-magnolia

    The created structure:

    hello-magnolia/
    ├── decorations/
    ├── dialogs/
    │   ├── components/
    │   └── pages/
    ├── i18n/
    │   └── hello-magnolia-messages_en.properties
    ├── includes
    │   └── README.txt
    ├── README.md
    ├── templates/
    │   ├── components/
    │   └── pages/
    └── webresources/

This is a typical Magnolia module structure.

When creating a name for a module, do not use spaces, accented characters such as é, à, ç, ä, öü or special characters such as slashes /\ and so on.

Magnolia continuously scans the file system folder defined by the magnolia.resources.dir property. In this case, it looks inside the light-modules folder, and registers your module(s) automatically. It detects new and modified templates, dialogs and (web)resources.
Open the Resource Files app from the App launcher and check that the hello-magnolia module structure has been registered:

The  icon in the Origin column indicates that the resource is loaded from the file system.

Creating the page template

You can create a working page template instantly with a CLI command called create-page, but we'll make the first template by hand for educational reasons.

In the steps that follow, you create:

  • A CSS-based styling for the page.
  • A page template script file containing FreeMarker directives. The directives make it possible to retrieve the content of some parts of the page from the JCR repository.
  • A page template definition. It makes the template available to Magnolia's authoring system.
  • dialog definition. A dialog definition defines the editable page properties.

Create a styling for the page

  1. Create a new css folder in /hello-magnolia/webresources/.

  2. Copy the CSS below and save it as /hello-magnolia/webresources/css/hello-style.css. We will reference this stylesheet in a FreeMarker template script.

    /hello-magnolia/webresources/css/hello-style.css
    @import url(//fonts.googleapis.com/css?family=Raleway);
    body {
       padding: 20px;
       font-family: Raleway, Helvetica, Arial, Tahoma, Verdana, sans-serif;
       background-color: #1e5799;
       background-attachment: fixed;
    }
    .container {
       width: 100%;
       max-width: 960px;
       margin: 0px auto;
       padding: 20px;
       box-sizing: border-box;
       background-color: white;
    }
    main {
       padding: 20px;
       margin-bottom: 40px;
    }
    h1 {
       font-size: 4em;
       font-family: Raleway, Helvetica, Arial, Tahoma, Verdana, sans-serif;
       font-weight: normal;
       background-color: #f6f6f6;
       padding: 30px 0 30px 15px;
       margin: 0;
    }
    blockquote {
       margin-bottom:40px;
       margin-top: 65px;
    }
    blockquote cite {
       padding-left:20px;
       font-size: 1.3em;
       color: #333;
    }
    blockquote p {
       border: 5px solid #0066aa;
       border-radius: 12px;
       padding: 25px 15px;
       position: relative;
       background-color: #fff;
       margin-bottom: 30px;
    }
    /** Add the bottom triangle for the quote bubble using CSS **/
    blockquote p:before, blockquote p:after {
       position: absolute;
       display: block;
       border-style: solid;
       content: "";
       height: 0;
       width :0;
       box-sizing: border-box;
    }
    blockquote p:before {
       left: 20px;
       bottom: -30px;
       border-color: transparent #0066aa transparent transparent;
       border-width: 0 30px 30px 0;
    }
    blockquote p:after {
       left: 29px;
       bottom: -15px;
       border-color: transparent #fff transparent transparent;
       border-width: 0 15px 15px 0;
    }

Create a page template script

A template script defines the output, typically HTML, and is interpreted by a page renderer. The script below uses a templating language called FreeMarker.

  1. Go to the /hello-magnolia/templates/pages/ folder.
  2. In there, create a file called hello.ftl and save it with the following content:

    /hello-magnolia/templates/pages/hello.ftl
    <!DOCTYPE html>
    <html xml:lang="${cmsfn.language()}" lang="${cmsfn.language()}">
      <head>
        [@cms.page /]
        <title>${content.windowTitle!content.title!}</title>
        <link rel="stylesheet" type="text/css" href="${ctx.contextPath}/.resources/hello-magnolia/webresources/css/hello-style.css" media="all" />
      </head>
      <body>
    
        <div class="container">
          <h1>${content.windowTitle!content.title!} works!</h1>
        </div>
    
      </body>
    </html>
    • Line 2: The ${cmsfn.language()} function sets the value of the lang attributes. This will make sure that the primary language of the page will be rendered correctly if you decide to localize your web page(s) into more languages.
    • Line 4: The [@cms.page /] directive adds toolbars and makes the page properties dialog available. You will create the definition for this dialog immediately after creating a page template definition.
    • Line 5: The ${content.windowTitle!content.title!} directive retrieves the content of the <title> element from the JCR repository.
    • Line 6: The ${ctx.contextPath} directive creates a reference to the CSS file. When the page is rendered, we need to know the absolute path to the CSS resource. This directive ensures that the path to the resource is full and correct on both the author and the public instances.
    • Line 11: The ${content.windowTitle!content.title!} directive renders the first part of the page title dynamically using the content of page properties.

Create a page template definition

template definition gives the template a name and makes it available to the system. It also tells the system which script renders the content.

We use YAML to create template definitions.

  1. Copy the template definition code below.

    /hello-magnolia/templates/pages/hello.yaml
    title: hello
    templateScript: /hello-magnolia/templates/pages/hello.ftl
    renderType: freemarker
    dialog: hello-magnolia:pages/hello
    visible: true
  2. Save it to a new file /hello-magnolia/templates/pages/hello.yaml.

Create a dialog definition for page properties

Copy the following code to a file named hello.yaml in /hello-magnolia/dialogs/pages/:

/hello-magnolia/dialogs/pages/hello.yaml
form:
  properties:
    title:
      $type: textField
      i18n: true
    windowTitle:
      $type: textField
      i18n: true

A dialog defined like this allows content authors to add and edit the values of page properties such as windowTitle and title fields. The content of these properties is stored in the Magnolia JCR repository.

Provide English labels for dialog fields

Dialog fields and other UI elements can be displayed with labels and descriptions. For the fields of the page properties dialog, provide the labels in form of an i18n language bundle.

Go to the /hello-magnolia/i18n/ folder, edit and save the hello-magnolia-messages_en.properties file with the following content:

/hello-magnolia/hello-magnolia-messages_en.properties
hello-magnolia.pages.hello=Page properties
hello-magnolia.pages.hello.title=Title
hello-magnolia.pages.hello.windowTitle=Window title

hello-magnolia.components.quotation=Quotation
hello-magnolia.components.quotation.quotation=Quotation
hello-magnolia.components.quotation.citedPerson=Cited person

Lines 1 to 3 define field labels for the Page properties dialog. Lines 5 to 7 define labels for the fields of the quotation component, which you will create further below.

Creating a page based on the template

Now you can use the page template to create a page in the Author instance. You can then publish the page to the Public instance.

  1. Go to the App launcher and click the Pages tile to open the Pages app:
  2. Create a new page called hello. Start this by clicking Add page from the Action bar on the right-hand side.
  3. In the Add page dialog that appears, choose the hello template as the page template. Click Next:
     
  4. In the Page properties dialog, enter Hello Magnolia into the Title and Window title fields. 
  5. Click Save changes.
  6. In the Pages app, select the Hello Magnolia page and click Preview page on the right to preview it.
  7. Click Publish. You can then access the page on the Public instance of your Magnolia installation via the URL
    http://localhost:8080/magnoliaPublic/hello.html.

(thumbs up) Congratulations! You've created your first Magnolia page built on a page template.

Now let's enhance the content of the page by adding an editable custom-built quotation component to the area just below the "Hello Magnolia works!" heading.

Creating an area and the quotation component

Areas and components help modularize a project and structure pages. Once areas and components are defined, you can reuse them in many page templates.

Let's create an area with one component to add quotations. At the end, the whole page should look like this:

What is ...

An area is a place on a template where an author can add components. The area specifies which types of components can be added, and whether only one, or multiple components can be added. Both page templates and component templates can contain areas. For example, a page template could contain a main area for placing primary page content, and a sidebar area for related content.

A component is the smallest block of content that authors can create, edit, delete, and move as a single unit in the Magnolia Page Editor. The following are typical examples of a component:

Creating an area

Areas are defined in the page template definition. 

The main area for the quotation component is defined and created when you execute the create-component  command. You'll create the area in the next section .

Creating the quotation component

Make sure you are at the root of your module (/magnolia/light-modules/hello-magnolia). Use the following CLI command to create the quotation component and make it available in the main area of the page template:

mgnl create-component quotation -a pages/hello@main

The command creates the following files:

  • /hello-magnolia/dialogs/components/quotation.yaml
    This definition configures the elements of the dialog.
  • /hello-magnolia/templates/components/quotation.yaml
    This definition gives the component a name and makes the component available to the system.
  • /hello-magnolia/templates/components/quotation.ftl
    The template script renders the content of the component.

The command also modifies the /hello-magnolia/templates/pages/hello.yaml file, in which it creates the main area and adds the availability of the quotation component by appending the following piece of code to it:

areas:
  main:
    availableComponents:
      quotation:
        id: hello-magnolia:components/quotation

Specify the location of the main area on the page

With @main, the mgnl create-component command also adds [@cms.area name="main"/] to end of the hello.ftl page template script.

We want the main area just below the page heading. For this, edit the /hello-magnolia/templates/pages/hello.ftl template script and add a <div/> element with the area just below the <h1/> element:

<!DOCTYPE html>
<html xml:lang="${cmsfn.language()}" lang="${cmsfn.language()}">
  <head>
    [@cms.page /]
    <title>${content.windowTitle!content.title!}</title>
    <link rel="stylesheet" type="text/css" href="${ctx.contextPath}/.resources/hello-magnolia/webresources/css/hello-style.css" media="all" />
  </head>
  <body>

    <div class="container ">
      <h1>${content.windowTitle!content.title!} works!</h1>
      <div class="main">
         [@cms.area name="main"/]
      </div>
    </div>

  </body>
</html>

Configure the dialog fields

The CLI command mgnl create-component creates a dialog definition with field types which you do not need. Open the dialog definition file /hello-magnolia/dialogs/components/quotation.yaml for editing, and edit it to appear as follows:

form:
  properties:
    quotation:
      $type: richTextField
      i18n: true
    citedPerson:
      $type: textField
      i18n: true

Be careful with the type of whitespace in this code. All the whitespace to the left of the text should be formed using the SPACE character, not the TAB character. For more details on this topic, see the 6.1. Indentation Spaces section in YAML v1.2 specification.

The key content elements in the above dialogue definition – quotation (lines 3 to 5) and citedPerson (lines 6 to 8) – are stored in the JCR repository and rendered in the page by the following code, the component's script.

Edit the component's template script

Replace the quotation.ftl template script with the following code:

/hello-magnolia/templates/components/quotation.ftl
[#if content.quotation?has_content]
<blockquote>
    ${cmsfn.decode(content).quotation}
    [#if content.citedPerson?has_content]<cite>${content.citedPerson}</cite>[/#if]
</blockquote>
[/#if]

The final structure of your hello-magnolia module in the light-modules folder should look like this:

hello-magnolia/
├── decorations/
├── dialogs/
│   ├── components/
│   │   └── quotation.yaml
│   └── pages/
│       └── hello.yaml
├── i18n/
│   └── hello-magnolia-messages_en.properties
├── README.md
├── includes
│   └── README.txt
├── templates/
│   ├── components/
│   │   ├── quotation.ftl
│   │   └── quotation.yaml
│   └── pages/
│       ├── hello.ftl
│       └── hello.yaml
└── webresources/
    └── css/
        └── hello-style.css

Adding the component to the page

Now, a content author can add a quotation component to the hello page with the text and the author of a quotation.

  1. Open the hello page in the Pages app.
  2. Click the New Main Component + button.
  3. Add the quotation component and click Next.
  4. Enter your favorite quotation in the dialog and Save changes:
     
  5. Preview the page and publish it.

Seeing the result on the public instance

Finally, access the web page on the Public instance: http://localhost:8080/magnoliaPublic/hello.html.

Other editors, with appropriate permissions configured in the Security app, can now also change the content of the quotation component on the Author instance.

(thumbs up) Congratulations.

You now know the basics of Magnolia templating. With these techniques, you can build websites where non-technical authors can manage content using dialogs.

Further reading


#trackbackRdf ($trackbackUtils.getContentIdentifier($page) $page.title $trackbackUtils.getPingUrl($page))