This page explains how you can integrate your play application with the play-cms. Each method has its advantages and disadvantages.

Method 1: Integrate non-cms pages

Pro: You can use full power of play's mvc and routing mechanisms

Con: Many cms features such as modifying the virtual path or automatic inclusion in search are not available

Choose this if you need the full power of play's controllers and routing.

Sharing layout templates between cms and non-cms pages

You can share the main layout template(s) between cms and non-cms pages. For this, you use the Page interface as parameter in your main template. The CMS' PageBlock implements Page, and in non-cms pages you instantiate a StandalonePage object, which contains general page info like title, description, and alternate language urls. 

The language urls are optional and will enable language switching on non-cms-pages just like for cms pages. If you skip this, the default language selector will point to the selected language's homepage instead.


StandalonePage page = new StandalonePage("", "")
        .addAlternateLanguageUrl("en", "/products")
        .addAlternateLanguageUrl("de", "/produkte");
return ok(productList.render(products, page));


@(products: List[product], page: ch.insign.cms.models.StandalonePage)
@import ch.insign.cms.models.StandalonePage
@main(page) {
    ... your template code ...


Adding non-cms-pages to the cms navigation

You can add your application pages to the cms navigation by adding a LinkBlock to the navigation tree. Just like adding a cms page, but it will only link to your application page. The admin still can name, and translate the link text, move it around etc. 

Important: The LinkBlock has the usual permissions and time-control settings, but this only covers the navigation entry: Your application page is cms-independent, you need to protect access yourself.

Process (filter) output of non-cms-pages

The output of cms pages is passed through the filter framework, which allows processing/modifying content. Most notably, this is used for processing <a> tag href targets (internally they're stored with a pointer to the target page, e.g.  <a >. The filter will convert them to a valid tag on output).

To process your non-cms page's content by the cms filter framework, use this in your controllers:

return ok(CMS.getFilterManager().processOutput(views.html.mytemplate.render(), null));

Method 2: Integrate into cms pages

Pro: All cms features like search indexing, permission/time controls etc. will work. The admin can create multiple page instances and configure them through your block edit template.

Con: You cannot use Play's controllers and routes

Choose this if your application does not require extensive interaction through different routes or if the interaction is done by ajax. Or if the admin should be able to create multiple pages with different settings.

  • Create a cms block which extends PageBlock and its frontend and edit form templates.
  • Override Html render() and return the page's content
  • Override Html editForm(Form editForm) and return the page's edit form (optional)
  • Override boolean isSearchable() (or use setSearchable()) to set whether your page should appear in the search index
  • To use an external controller, you could also override Result routeRequest(NavigationItem navItem), but at the expense of some cms features (not recommended).

Method 3: Integrate into cms blocks

Creating a cms block instead of a cms page means you / the admins can and and place your application content blocks freely, multiple times, on every page (that is configured to take this block type as subcontent), like other cms blocks. Technically, do the same steps as described above.

Hint: You can configure which blocks can be added where:

cms.context.frontend.excludedSubblocks = [BackendLinkBlock]
cms.context.backend.allowedSubblocks = [BackendLinkBlock, GroupingBlock]

Method 4: Integrate cms content into non-cms pages

To use cms-managed content into your application, simply use the cms' API to get the desired object and its content. It's suggested to use a key to identify them.

Example from code:

Example from a template:

Note: This method will create an empty block if no block with this key exists.