Your starting base: play-cms-demo

To bootstrap your project, you should use the play-cms-demo as your starting point. Once it's up and running, continue with the steps below.


Setup and initialize the cms

To setup the cms programatically (wire up your own provider classes), you implement the ch.insign.cms.CMSApiLifecycle interface or override the ch.insign.cms.CMSApiLifecycleImpl class to change runtime settings, and implement the ch.insign.cms.models.Bootstrapper interface or override the ch.insign.cms.models.DefaultBootstrapper class to change the initial database content.

Main setup options 

Registering Blocks

play-cms allows to change set of enabled blocks without modifying code. To do so you need to update application.conf of your play-cms instance and modify following settings


Both these settings accepts array of fully qualified block class names. By default following blocks are enabled:


Adding additional entries to the list of enabled blocks looks like following:

// Enable ReviewBlock
cms.blocks.enabled += "ch.insign.cms.blocks.reviewblock.models.ReviewBlock"

Similarly, disabling of any block might be done like this:

// Disable JotForms
cms.blocks.disabled += "ch.insign.cms.blocks.jotformpageblock.JotFormPageBlock"

Sometimes there might be situations when block availability should be controlled at runtime. For such cases play-cms provides BlockManager class. It allows to enable blocks by calling BlockManager#register() method. Here is an example of usage:


public void registerNewyearWidgetBlock() {
    LocalDate currentDate =;

    if (currentDate.isAfter(LocalDate.of(currentDate.getYear(), 12, 1))
            && currentDate.isBefore(LocalDate.of(currentDate.getYear(), 12, 31))) {

Create your own error pages
Error pages are treated as normal cms pages. Create and return them initially form code - the admins can then modify them using the cms.

Add example data
This helps greatly during development of your project: Create some demo pages and content using your own blocks and design, and matching the final project's desired content. During development, you can then easily reset the db (call yourdomain.ext/reset) and will find your example content again.

Add your own content filters
Content filters are a great tool to let the user add e.g. variables freely inside any content, e.g. [[currentUserCount]] which your filter resolves to the current value when displaying the page.

CMSApiLifecycle example


public class MyCMSApiLifecycle extends CMSApiLifecycleImpl {
    private final MyAuthenticationListener myAuthenticationListener;
    private final PlayAuthApi playAuthApi;

    public MyCMSApiLifecycle(
            JPAApi jpaApi,
            ActorSystem actorSystem,
            PlayAuthApi playAuthApi,
            MyAuthenticationListener myAuthenticationListener
    ) {
        super(jpaApi, actorSystem);
        this.myAuthenticationListener = myAuthenticationListener;
        this.playAuthApi = playAuthApi;

    public void onStart(CMSApi cmsApi) {

        // set your own authentication listener

        // change other settings here...

    protected void registerContentFilters(CMSApi cmsApi) {
        // Add your own content filters.


Bootstrapper example


public class MyCMSBootstrapper extends DefaultBootstrapper implements Bootstrapper {

    private PartyManager pm;
    private PartyRoleManager prm;
    private JPAApi jpaApi;

    public MyCMSBootstrapper(
            AccessControlManager accessControlManager,
             CMSApi cmsApi,
             PartyManager partyManager,
             PartyRoleManager partyRoleManager,
             JPAApi jpaApi
    ) {
        super(accessControlManager, cmsApi, partyRoleManager, jpaApi); = partyManager;
        this.prm = partyRoleManager;
        this.jpaApi = jpaApi;

     * Load essential data which is required for all configured sites to function properly.
     * Used to perform an initial project bootstrap or to reload it to the initial state.
    public synchronized void loadEssentialData() {

     * Load example data for all configured sites.
    public synchronized void loadExampleData() {

    /* Override DefaultBootstrapper methods:
     *   The DefaultBootstrapper defines more fine grained methods
     *   which are called by DefaultBootstrapper.load*Data methods
     *   so it may be easier to override them if small changes required.

     * Delete data created by loadEssentialData
    protected void deleteEssentialData() {

     * Delete data created by deleteExampleData
    protected void deleteExampleData() {

     * Add navigation entries in the backend
    protected void createBackendNavigation() {

    protected ErrorPage createErrorPageNotFound(Sites.Site site) {
        return super.createErrorPageNotFound(site);

    protected ErrorPage createErrorPageUnavailable(Sites.Site site) {
        return super.createErrorPageUnavailable(site);

    protected ErrorPage createErrorPageInternalServerError(Sites.Site site) {
        return super.createErrorPageInternalServerError(site);

    protected ErrorPage createErrorPageForbidden(Sites.Site site) {
        return super.createErrorPageForbidden(site);

    protected void createPartyRoles() {
        // add more user roles

    protected void createParties() {
        // add more users


The CMSApiLifecycle and Bootstrapper implementations are configured as DI bindings in ch.insign.cms.inject.CmsApiModule and ch.insign.cms.inject.BootstrapperModule correspondingly, so they should also be overridden by implementing custom play.api.inject.Module, enabling them in the application.conf and also disabling the overridden modules, e.g.:


# Override CmsApiModule
play.modules.disabled += "ch.insign.cms.inject.CmsApiModule"
play.modules.enabled += "my.CmsApiModule"

# Override BootstrapperModule
play.modules.disabled += "ch.insign.cms.inject.BootstrapperModule"
play.modules.enabled += "my.BootstrapperModule"



The cms uses configuration values defined in play-cms/conf/application.conf. You can override them in your global application.conf.

# play-cms default configuration
# CMS config values.
# Always access these using Cms.getConfig().*
cms.deleteWithoutTrashBin = false
cms.enableResetRoute = false

From code, config values can be accessed using CMSApi#getConfig().*