Last updatedMay 15, 2019

Write a simple Confluence Space blueprint

Applicable:

This tutorial applies to Confluence 5.9.1 and higher.

Level of experience:

Beginner.

Time estimate:

It should take you less than 1 hour to complete this tutorial.

In this tutorial, you will learn how to create a very simple space blueprint plugin (without writing any Java classes) that can only be installed on Confluence Server. To create a blueprint for Confluence Cloud head to Multi-page blueprints with Confluence Connect.

Before you begin

To complete this tutorial, you should:

  1. Work through the Atlassian Plugin SDK tutorial.
  2. (optional) Complete the Write a simple Confluence blueprint plugin tutorial.

Plugin source

We encourage you to work through this tutorial. If you want to skip ahead or check your work when you have finished, you can find the plugin source code on Atlassian Bitbucket. To clone the repository, run the following command:

1
git clone git@bitbucket.org:atlassian_tutorial/confluence-space-blueprint.git

About these Instructions

You can use any supported combination of operating system and IDE to create this plugin. These instructions were written using Intellij IDEA 2017.2 on macOS Sierra. If you are using another operating system or IDE combination, you should use the equivalent operations for your specific environment. This tutorial was last tested with Confluence 6.7.1 using the Atlassian SDK 6.3.10.

Step 1. Create and prune the plugin skeleton

In this step, you'll create a plugin skeleton using atlas- commands. Because you won't need some of the files created in the skeleton, you'll also delete them in this step.

  1. Open a Terminal and navigate to your workspace directory.

  2. To create a Confluence plugin skeleton, run the following command:

    1
    atlas-create-confluence-plugin
  3. To identify your plugin enter the following information :

    group-id

    com.example.plugins.tutorial.confluence

    artifact-id

    space-blueprint

    version

    1.0-SNAPSHOT

    package

    com.example.plugins.tutorial.confluence

  4. Confirm your entries when prompted with Y or y.

  5. Navigate to the project directory created by the previous step.

    1
    cd space-blueprint/
  6. Delete the test directories.

    Setting up testing for your plugin isn't part of this tutorial. Run the following commands to delete the generated test skeleton:

    1
    2
    rm -rf ./src/test/java
    rm -rf ./src/test/resources/
  7. Delete the unneeded Java class files.

    1
    rm -rf ./src/main/java/com/example/plugins/tutorial/confluence/*

Step 2. Add your space blueprint definition

In this step, you will define your space blueprint and have a simple create space dialog wizard.

  1. To create a web item for the create space dialog, in the src/main/resources/atlassian-plugin.xml file, add the following:

    1
    2
    3
    4
    5
    <web-item key='example-space-blueprint-item' i18n-name-key='confluence.blueprints.space.example.name'
              section='system.create.space.dialog/content'>
        <description key='confluence.blueprints.space.example.description'/>
        <param name='blueprintKey' value='example-space-blueprint'/>
    </web-item>

    The section='system.create.space.dialog/content' attribute is what makes the dialog available in the create space pop-up window.

  2. Add the space blueprint definition and a wizard with one page. Note that the category is an optional attribute, which essentially adds a label to all spaces created via this blueprint. This will show an "Examples" category listed in the space directory with all the spaces created with our example space blueprint.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <space-blueprint key="example-space-blueprint" i18n-name-key="confluence.blueprints.space.example.name" category="examples">
        <dialog-wizard key="example-space-blueprint-wizard">
            <dialog-page id="exampleSpaceId"
                         template-key="Confluence.SpaceBlueprints.Example.dialogForm"
                         title-key="confluence.blueprints.space.example.dialog.create.title"
                         description-header-key="confluence.blueprints.space.example.dialog.create.heading"
                         description-content-key="confluence.blueprints.space.example.dialog.create.description"
                         last="true"/>
        </dialog-wizard>
    </space-blueprint>

    The key attribute for <space-blueprint> should be the same as the value attribute for <param key=”blueprintKey”> inside <web-item>

Step 3. Add your space dialog wizard 

  1. Update the web-resources to include the dialog-page.soy for your wizard form (note we will need the transformers soyTransformer and jsI18n). Also, add some contexts to ensure your resources are included inside Create space dialog.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    ``` xml
        <transformation extension="soy">
            <transformer key="soyTransformer">
                <functions>com.atlassian.confluence.plugins.soy:soy-core-functions</functions>
            </transformer>
        </transformation>
        <transformation extension="js">
            <transformer key="jsI18n"/>
        </transformation>
     
        <resource type="download" name="dialog-page.js" location="/soy/dialog-page.soy"/>

      com.atlassian.confluence.plugins.confluence-create-content-plugin:space-blueprints create-space

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    ```
    
    The following code snippet shows the full file including the previous example.
    
    ``` xml
    <atlassian-plugin key="${atlassian.plugin.key}" name="${project.name}" plugins-version="2">
        <plugin-info>
            <description>${project.description}</description>
            <version>${project.version}</version>
            <vendor name="${project.organization.name}" url="${project.organization.url}" />
            <param name="plugin-icon">images/pluginIcon.png</param>
            <param name="plugin-logo">images/pluginLogo.png</param>
        </plugin-info>
        <!-- add our i18n resource -->
        <resource type="i18n" name="i18n" location="space-blueprint"/>
    
        <!-- add our web resources -->
       <web-resource key="space-blueprint-resources" name="space-blueprint Web Resources">
               <transformation extension="soy">
                   <transformer key="soyTransformer">
                       <functions>com.atlassian.confluence.plugins.soy:soy-core-functions</functions>
                   </transformer>
               </transformation>
               <transformation extension="js">
                    <transformer key="jsI18n"/>
               </transformation>
    
               <resource type="download" name="space-blueprint.css" location="/css/space-blueprint.css"/>
               <resource type="download" name="space-blueprint.js" location="/js/space-blueprint.js"/>
               <resource type="download" name="images/" location="/images"/>
               <resource type="download" name="dialog-page.js" location="/soy/dialog-page.soy"/>
    
               <context>create-space</context>
               <dependency>com.atlassian.auiplugin:ajs</dependency>
           </web-resource>
    
        
        <web-item key='example-space-blueprint-item' i18n-name-key='confluence.blueprints.space.example.name'
                      section='system.create.space.dialog/content'>
                <description key='confluence.blueprints.space.example.description'/>
                <param name='blueprintKey' value='example-space-blueprint'/>
        </web-item>
     
        <space-blueprint key="example-space-blueprint" i18n-name-key="confluence.blueprints.space.example.name" category="examples">
                <dialog-wizard key="example-space-blueprint-wizard">
                    <dialog-page id="exampleSpaceId"
                                 template-key="Confluence.SpaceBlueprints.Example.dialogForm"
                                 title-key="confluence.blueprints.space.example.dialog.create.title"
                                 description-header-key="confluence.blueprints.space.example.dialog.create.heading"
                                 description-content-key="confluence.blueprints.space.example.dialog.create.description"
                                 last="true"/>
                </dialog-wizard>
        </space-blueprint>
    
    </atlassian-plugin> 
    ```
  2. Create a soy folder for your dialog wizard template under src/main/resources (or use your IDE):

    1
    mkdir src/main/resources/soy
  3. In that folder, create a file called dialog-page.soy. This calls a generic space form (with space key and name fields) already available for you.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    ``` xml
    {namespace Confluence.SpaceBlueprints.Example}
    /**
     * Dialog form template
     *
     * @param atlToken the XSRF token to send with the form
     * @param? fieldErrors the map of errors to display keyed by field name
     * @param? name initial value for the name field
     * @param? key initial value for the key field
     */
    {template .dialogForm}
    <form action="#" method="post" id="decisions-form" class="common-space-form aui">
        {call Confluence.Templates.Blueprints.CreateSpace.createSpaceFormFields}
            {param showSpacePermission: false /}
            {param fieldErrors: $fieldErrors /}
            {param name: $name /}
            {param key: $key /}
        {/call}
        <input type="hidden" name="atl_token" value="{$atlToken}" />
    </form>
    {/template}
    ```

    The template-key attribute in the plugin definition must match the namespace and template name in the soy template. In this case, our namespace is Confluence.SpaceBlueprints.Example, and our template is .dialogForm, so the template-key must be Confluence.SpaceBlueprints.Example.dialogForm.

  4. In the src/main/resources/js/space-blueprint.js file, hook into the wizard APIs. They are similar to the blueprint ones. In our example here, we update the space home page title to be the space name and a suffix of "Home Page".

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    AJS.bind("blueprint.wizard-register.ready", function () {
        function submitExampleSpace(e, state) {
            state.pageData.ContentPageTitle = state.pageData.name + " " + AJS.I18n.getText("confluence.blueprints.space.example.home.title.suffix");
            return Confluence.SpaceBlueprint.CommonWizardBindings.submit(e, state);
        }
        function preRenderExampleSpace(e, state) {
            state.soyRenderContext['atlToken'] = AJS.Meta.get('atl-token');
            state.soyRenderContext['showSpacePermission'] = false;
        }
        Confluence.Blueprint.setWizard('com.example.plugins.tutorial.confluence.space-blueprint:example-space-blueprint-item', function(wizard) {
            wizard.on("submit.exampleSpaceId", submitExampleSpace);
            wizard.on("pre-render.exampleSpaceId", preRenderExampleSpace);
            wizard.on("post-render.exampleSpaceId", Confluence.SpaceBlueprint.CommonWizardBindings.postRender);
        });
    });
  5. Add the i18n strings to src/main/resources/space-blueprint.properties:

    1
    2
    3
    4
    5
    6
    confluence.blueprints.space.example.name=Example Space Blueprint
    confluence.blueprints.space.example.description=An example of a space blueprint
    confluence.blueprints.space.example.dialog.create.title=Create your Example Space
    confluence.blueprints.space.example.dialog.create.heading=About Example Spaces
    confluence.blueprints.space.example.dialog.create.description=The example space is a way of demonstrating the features of space blueprints
    confluence.blueprints.space.example.home.title.suffix=Home Page

Step 4. Create a home page for your space blueprint

Space blueprints let you define a custom home page template to use when creating the space. 

  1. Create an xml folder for your home page template

    1
    mkdir src/main/resources/xml
  2. In the folder that includes the children macro, create a new file called example-space-home.xml:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    <ac:layout>
        <ac:layout-section ac:type="single">
            <ac:layout-cell>
                <h2><at:i18n at:key="confluence.blueprints.space.example.home.children.heading" /></h2>
                <p>
                   <ac:macro ac:name="children">
                       <ac:parameter ac:name="page"></ac:parameter>
                       <ac:parameter ac:name="all">true</ac:parameter>
                   </ac:macro>
                </p>
            </ac:layout-cell>
        </ac:layout-section>
    </ac:layout>
  3. Add the content template to the atlassian-plugin.xml file:

    1
    2
    3
    4
    <content-template key="example-space-homepage-template" i18n-name-key="confluence.blueprints.space.example.homepage.name">
        <description key="confluence.blueprints.space.example.homepage.desc"/>
        <resource name="template" type="download" location="/xml/example-space-home.xml"/>
    </content-template>
  4. Add the content template reference to the space blueprint definition:

    1
    2
    3
    <space-blueprint key="example-space-blueprint" i18n-name-key="confluence.blueprints.space.example.name" category="examples">
        <content-template ref="example-space-homepage-template"/>
        ....

    The following code snippet shows the full atlassian-plugin.xml file including previous example.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    <atlassian-plugin key="${atlassian.plugin.key}" name="${project.name}" plugins-version="2">
        <plugin-info>
            <description>${project.description}</description>
            <version>${project.version}</version>
            <vendor name="${project.organization.name}" url="${project.organization.url}" />
            <param name="plugin-icon">images/pluginIcon.png</param>
            <param name="plugin-logo">images/pluginLogo.png</param>
        </plugin-info>
        <!-- add our i18n resource -->
        <resource type="i18n" name="i18n" location="space-blueprint"/>
    
        <!-- add our web resources -->
        <web-resource key="space-blueprint-resources" name="space-blueprint Web Resources">
            <transformation extension="soy">
                <transformer key="soyTransformer">
                    <functions>com.atlassian.confluence.plugins.soy:soy-core-functions</functions>
                </transformer>
            </transformation>
            <transformation extension="js">
                <transformer key="jsI18n"/>
            </transformation>
    
            <resource type="download" name="space-blueprint.css" location="/css/space-blueprint.css"/>
            <resource type="download" name="space-blueprint.js" location="/js/space-blueprint.js"/>
            <resource type="download" name="dialog-page.js" location="/soy/dialog-page.soy"/>
            <resource type="download" name="images/" location="/images"/>
            <dependency>com.atlassian.confluence.plugins.confluence-create-content-plugin:space-blueprints</dependency>   <!-- This dependency is not required for confluence 5.4+ -->
            <context>create-space</context>
        </web-resource>
    
        <content-template key="example-space-homepage-template" i18n-name-key="confluence.blueprints.space.example.homepage.name">
            <description key="confluence.blueprints.space.example.homepage.desc"/>
            <resource name="template" type="download" location="/xml/example-space-home.xml"/>
        </content-template>
        
        <web-item key='example-space-blueprint-item' i18n-name-key='confluence.blueprints.space.example.name'
                  section='system.create.space.dialog/content'>
            <description key='confluence.blueprints.space.example.description'/>
            <param name='blueprintKey' value='example-space-blueprint'/>
        </web-item>
     
        <space-blueprint key="example-space-blueprint" i18n-name-key="confluence.blueprints.space.example.name" category="examples">
            <content-template ref="example-space-homepage-template"/>
            <dialog-wizard key="example-space-blueprint-wizard">
                <dialog-page id="exampleSpaceId"
                             template-key="Confluence.SpaceBlueprints.Example.dialogForm"
                             title-key="confluence.blueprints.space.example.dialog.create.title"
                             description-header-key="confluence.blueprints.space.example.dialog.create.heading"
                             description-content-key="confluence.blueprints.space.example.dialog.create.description"
                             last="true"/>
            </dialog-wizard>
        </space-blueprint>
    
    </atlassian-plugin> 
  5. Add the new keys to the i18n properties file:

    1
    2
    3
    confluence.blueprints.space.example.homepage.name=Example Space Homepage
    confluence.blueprints.space.example.homepage.desc=Example Space Homepage Description
    confluence.blueprints.space.example.home.children.heading=Child pages will be shown here

Step 5. Run your plugin

At this point, you have created a skeleton space blueprint plugin. 

  1. To start a local Confluence instance, run the following command:

    1
    atlas-run
  2. Log in to the instance as user admin using a password of admin.

  3. Click SpacesCreate Space in the header, and then select your space blueprint.  It should take you through a wizard with a basic space form to create a space and see your home page with a children macro pre populated.

    1
    <img src="/server/confluence/images/create-example-space.png" class="confluence-thumbnail" width="300" />

Step 6. Add new fields to the create space dialog

During the creation of your new space, you might want to ask the user for some information in the create dialog. In our example here, we will add a space description field. We will also add a custom heading field to display it on the space home page.

  1. Add description and home page heading fields to your dialog-page.soy template:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    <fieldset>
        <div class="field-group">
            <label for="space-description">{getText('confluence.blueprints.space.example.dialog.label.description')}</label>
            <textarea id="space-description" class="textarea long-field" rows="3" type="text" name="description"
                placeholder="{getText('confluence.blueprints.space.example.dialog.label.description.placeholder')}"></textarea>
        </div>
    </fieldset>
    <fieldset>
        <div class="field-group">
            <label for="space-homepage-heading">{getText('confluence.blueprints.space.example.dialog.label.heading')}</label>
            <textarea id="space-homepage-heading" class="textarea long-field" rows="3" type="text" name="spaceHomepageHeading"
                placeholder="{getText('confluence.blueprints.space.example.dialog.label.heading.placeholder')}"></textarea>
        </div>
    </fieldset>

    Here is full template including example above.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    {namespace Confluence.SpaceBlueprints.Example}
    /**
     * Dialog form template
     *
     * @param atlToken the XSRF token to send with the form
     * @param? fieldErrors the map of errors to display keyed by field name
     * @param? name initial value for the name field
     * @param? key initial value for the key field
     */
    {template .dialogForm}
    <form action="#" method="post" id="decisions-form" class="common-space-form aui">
        {call Confluence.Templates.Blueprints.CreateSpace.createSpaceFormFields}
            {param showSpacePermission: false /}
            {param fieldErrors: $fieldErrors /}
            {param name: $name /}
            {param key: $key /}
        {/call}
        <fieldset>
            <div class="field-group">
                <label for="space-description">{getText('confluence.blueprints.space.example.dialog.label.description')}</label>
                <textarea id="space-description" class="textarea long-field" rows="3" type="text" name="description"
                    placeholder="{getText('confluence.blueprints.space.example.dialog.label.description.placeholder')}"></textarea>
            </div>
        </fieldset>
        <fieldset>
            <div class="field-group">
                <label for="space-homepage-heading">{getText('confluence.blueprints.space.example.dialog.label.heading')}</label>
                <textarea id="space-homepage-heading" class="textarea long-field" rows="3" type="text" name="spaceHomepageHeading"
                    placeholder="{getText('confluence.blueprints.space.example.dialog.label.heading.placeholder')}"></textarea>
            </div>
        </fieldset>
        <input type="hidden" name="atl_token" value="{$atlToken}" />
    </form>
    {/template}
  2. Add the new keys to the i18n properties file:

    1
    2
    3
    4
    confluence.blueprints.space.example.dialog.label.description=Description
    confluence.blueprints.space.example.dialog.label.description.placeholder=Briefly describe this space
    confluence.blueprints.space.example.dialog.label.heading=Homepage Heading
    confluence.blueprints.space.example.dialog.label.heading.placeholder=Add a custom heading for the heading on the homepage

    There is some magic that injects form variables from the create dialog into a context that is provided in the home page template, so update the template to refer to the new heading:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    <ac:layout>
        <ac:layout-section ac:type="single">
            <ac:layout-cell>
                <h2><at:var at:name="spaceHomepageHeading"/></h2>
                <p>
                   <ac:macro ac:name="children">
                      <ac:parameter ac:name="page"></ac:parameter>
                      <ac:parameter ac:name="all">true</ac:parameter>
                   </ac:macro>
                </p>
            </ac:layout-cell>
        </ac:layout-section>
    </ac:layout>
  3. Reload your plugin and you should be able to see two additional fields, Description and Heading in the dialog wizard and have it passed through to the created space home page.

Next steps

Now that you know how to create Confluence Space blueprint plugin you’re ready to explore more about blueprints. Check out tutorial for intermediate blueprint plugin or try to write advanced blueprint plugin.