Headless CMS: Enable In-Context Preview and Editing in an External Application

Do you have an existing application that has content in it that you want to manage but you don’t want to completely rebuild in a CMS? This use case is more common than you can imagine. Developers start building an application only much later to find it would benefit from CMS authoring capabilities like in-context editing and preview. What’s the solution? Rebuild the application? No. Crafter CMS is a headless CMS that’s front-end agnostic. It can plug into any application.

Let’s look at a very simple example. Just recently I posted a blog that used Node JS an external application that called Crafter CMS headless CMS capabilities for content via APIs.

In the screenshot above the content “Hi, I’m Editorial by HTML5 UP” is being served to the NodeJS application via APIs.

Content authors are used to working with in-context editing and preview as seen below:

In this blog, I’ll extend the example above to show how to enable those features for your content authors. The techniques shown in this blog are applicable to any web-based front-end technology. Crafter CMS provides additional help for specific frameworks like React JS. These are/will be covered in other blogs.

Getting Started

Follow the instructions in this blog to get an external application that pulls editable content from Crafter CMS via API. If you prefer to work the browser rather than Node JS, here is another example of a simple application that runs entirely in the browser. For this blog, I’ll use the Node JS example.

Once you have completed this step you should be able to:

  1. Make a change to the hero text in the editorial website via Crafter Studio
  2. See the change in your external application running in Node JS

Enabling Preview

The next step is to enable preview for content authors so they can see how the content will look in the external application. To keep things simple in our example I will change the Editorial site to preview the external application. In some cases, you may wish to leave the Editorial site/authoring experience as is and create a new project for the External app. Let’s keep to the basics.

Step 1: Configure the Site Preview

  1. In the Editorial site, click on the Sidebar to open the Sidebar menu.
  2. Click Site Config to go to site administration.
  3. On the Site Config console, click Configuration, then choose Site Configuration from the drop-down.
  4. Add the following line to the XML in the location shown and click Save.
    <previewServer>http://localhost:3000</previewServer>

  5. Click the Crafter logo to return to the content authoring for the site.
  6. Go to preview for the home page and you will see your Node JS application showing in preview.

With the configuration made, Crafter Studio now looks to the external application for its preview. As long as the external application is pointing to APIs running the Crafter Engine supporting preview you will be able to make edits and see them in the preview.

Enabling In-Context Editing

Crafter Studio makes it easy to get to the content you want to edit. The Sidebar, Dashboard and other UI elements make navigating to the content quick and easy. In-Context Editing is the ability to click on elements in your preview, edit them and see the change. This is a much more visual way of locating and editing content because its location in the information architecture doesn’t matter.

In Crafter Studio you turn on in-context editing by clicking on the pencil in the toolbar at the top of the screen. This enables pencils throughout your preview that allows you to edit the related elements directly as shown in the picture above.

In-Context editing is an integration with Crafter Studio, there’s a collaboration of sorts between the Studio application and the site/application being previewed that enables the in-context editing features like pencils and drag and drop. In this blog, we’re going to show a simple, framework agnostic way to support this integration. Crafter CMS has additional libraries for specific frameworks like React JS, Angular, Freemarker etc that encapsulate many of these details.

Step 1: Enable Communication

To enable communication between your application preview and Crafter Studio you must include a tiny piece of Javascript we call the “Guest” library.

To do this add the following include to the bottom of your page

<script src=”http:/studio/static-assets/libs/requirejs/require.js” data-main=”http:/studio/overlayhook?page=x&site=id&cs.js”></script>

In our Node JS example we’re going to edit directly though the application. To enable this, add the following to your package.json:

“proxy”: {
“/api”: { “target”: “http://localhost:8080” },
“/studio”: { “target”: “http://localhost:8080” },
“/static-assets”: { “target”: “http://localhost:8080” }
},

Step 2: Indicate Where the In-context Editing Regions “Pencils” Belong

To enable point and click editing on content you must indicate where the regions are and what content the regions relate to. To do this in HTML5 applications Crafter Studio (and the Guest library) uses HTML5 attributes.

The following attributes are used:

  • data-studio-ice: This property marks the element as the container for in-context editing. No value is required.
  • data-studio-component-path: This is the path of the content object. Example: “/site/products/a-component.xml”
  • data-studio-ice-path: This is the path of the content object. Example: “/site/products/a-component.xml”
  • data-studio-component: This is the content type name. Example: “/component/product”

Example Container element:

<div data-studio-component-path=”/site/products/a-component.xml”
data-studio-component=”/component/product”
data-studio-ice=””
data-studio-ice-path=”/site/products/a-component.xml”>
INNER HTML
</div>

Step 3: Try it!

Once you have marked elements in the application with the proper metadata you are ready to begin editing.

  1. Log in to Crafter Studio (for our example: http://localhost:3000/studio)
  2. Go to the preview for the application
  3. Turn on in-context editing by clicking on the pencil icon in the main navigation menu.

  4. Click the pencils and start editing🙂  It’s as easy as that.

Conclusion

Many times developers want to content enable an application that is external to their CMS. Either the application was built before it needed CMS features or the developers built outside a CMS to avoid being constrained by traditional CMS frameworks. Headless CMS platforms are Content / API first CMS architectures that loosely couple your application to the CMS. This new architecture has enabled a host of new content managed channels including native mobile apps and new user-friendly app frameworks like ReactJS and AngularJS. The problem is that almost no CMS out there supports preview and editing of the applications and channels that pull content from them. Here Crafter CMS is different. Crafter CMS has always been decoupled and its architecture has always been agnostic to the frontend. Crafter CMS is a headless CMS that supports the authoring experience your content authors are accustomed to.

CMS for SPAs Tutorial: Using React and Node JS with Crafter CMS

The most traditional, full-featured CMS platforms are not designed to handle headless content and most headless CMS platforms aren’t full-featured and have only basic authoring support.

Crafter CMS is both full-featured and fully supports headless CMS capabilities. That’s pretty unique. In this tutorial, you will learn how to create a content-rich, ReactJS-based Single Page Application (SPA) with in-context editing and other full-featured authoring capabilities.

Our React Application

We need an application to base our tutorial on. For our example we have the following criteria:

  • An existing, open source application that serves a content-rich use case where the content in the application is likely to be updated regularly by non-developers.
  • The application is sophisticated enough to be interesting but not too complex to be understood.
  • The application looks good and is responsive.
  • The application is based on React JS.

With these criteria in mind, I found this terrific open source React-based shopping cart application by Jefferson Ribeiro: https://github.com/jeffersonRibeiro/react-shopping-cart, Thanks, Jefferson!

We’re going to break our tutorial down into a number of broad steps:

Step 1: Download and run the application locally. First, thing’s first let’s get our local application development environment (React and NodeJS) up and running. Here we’ll see that the application already relies on a RESTful service to acquire its content.

Step 2: Create a project in Crafter CMS and set it up to preview our React application running in Node JS. Now that our application is running let’s get the CMS set up and previewing our application.

Step 3: Model a product in Crafter CMS. We have an application and we have a CMS. It’s time to connect them. Here we’ll learn how to model content and we’ll do some minor configuration along the way to customize the Studio UI for the use case.

Step 4: Create a basic RESTful service. Now that we have content, we can create a RESTful service to return the content from the CMS as JSON. Once our service is in place we’ll modify the application to consume our service instead of the service it uses out of the box.

Step 5: Extend the service to include images managed by authors. The out of the box application uses statically managed images and convention. We’ll add images to the CMS to demonstrate extending our content model and app.

Step 6: Add in-context editing to the solution. Now that the app’s content is driven by the CMS we want to make it easier for the content authors to find and edit their content. Making content editable directly through the app is one of the best ways. In this step, we’ll make the small modifications and configurations necessary to support this.

Step 7: Considerations for operationalizing the solution. Now that we have a working solution we’ll talk through some additional thoughts around development process integration and production operations.

Let’s get started!

Prerequisites for the Tutorial

  • NPM / Yarn installed
    • NPM will help you easily download the proper dependencies. You can also use NPM or Yarn to build and execute your application.
    • In our example, I will use Yarn to manage my package.json file and to assist me in building my application.
  • Access to a running Crafter Studio instance.
    • You will need access to create a site and modify its configuration.

Step 1: Download and run the application locally

The first step is to download the application and make sure we’ve got a local environment that will allow us to modify and run the application. This step does not involve the CMS. In many ways, it emulates a common real-world scenario in which the need for authors to modify content without the help of develops is discovered late in the development process or even post-launch. Let’s begin.

  1. On your local machine clone Jefferson Ribeiro’s project: https://github.com/jeffersonRibeiro/react-shopping-cart,
  2. Change directory into the react-shopping-cart folder that was created and run yarn install
    This will install the libraries necessary to run your application.
  3. Run the React application by executing yarn start.
    This will start a NodeJS and run the react application.
  4. Open your browser to http://localhost:3000

This application is pulling content for the product catalog in a JSON feed format from the following URL:https://react-shopping-cart-67954.firebaseio.com/products.json

Step 2: Create a project in Crafter CMS and set it up to preview our React application running in Node JS

Now that our application is running let’s get the CMS set up and previewing our application. The first thing that you need to accomplish this is a running instance of Crafter Studio, the authoring component of Crafter CMS. You can learn how to get this set up here.

  1. Log in to Crafter Studio as the administrator and on Site Dashboard, click the Create Site button.
  2. Following the picture above, populate the dialog. Give the site an ID and select “Empty” blueprint then click the Create button.  Once complete, you will see your empty site previewed in the Crafter Studio application.  Now we want to tell Crafter Studio that our application is not running in Crafter Engine, but instead on NodeJS @ port 3000.
  3. Open the sidebar by clicking the Sidebar button in the navigation.  Then navigate to the site configuration panel by clicking on the Site Config item in the Sidebar menu.

  4. Open the main Studio configuration for the site by clicking the Configuration menu item then selecting the Site Configuration option in the drop-down.
  5. Add the following tag (<previewServer>http://localhost:3000</previewServer>) to the configuration as shown below and then click the Save button.
  6. Click on the Crafter logo up in the upper left-hand corner to return to the dashboard.
  7. In the Sidebar, open Pages and click on Home Page and you will see your site that is running in NodeJS within the preview window of Crafter Studio. At this point, we have both our application (running in NodeJS) and our CMS running with the ability to preview our application.  That means we can continue to use our standard development tools and practices for the React application while integrating it into the CMS.

Step 3: Model a product in Crafter CMS

Now that the two main components (our app and our CMS) are up and running it’s time to connect them.  To start we need to describe the structure of our content, in this case, a product.  To understand what the app is looking for we can examine the UI or because we already know the application is reading a RESTful JSON API from Firebase we can look at that.

Step 3 A: model the content


It’s clear that each product has a title, a description, a style, a price and so on.  To model these in the CMS we must add a new content type.

  1. Open the Content Type administration tool by opening the Sidebar and clicking on the Site Config item within the Sidebar. In the Site Config panel, click the Content Types item, then click on Create New Type
  2. Fill out the dialog by labeling the content type “Product“, select “Component” for the type and then click the Create button.  Once you click create you will be taken to the schema editor.
  3. Drag and drop the controls and from the Controls area to model the product.
  4. Remember to set property values for each control including constraints. To configure a control: click on it and its properties will appear in the property sheet on the right.

  5. Note that for our product sizes I chose to give the author a list of sizes to click on.  Since a product may come in many sizes I’ve used a group checkbox control.
  6. Group checkboxes require a data source.  To keep things really simple let’s supply a static list of sizes with the key-value data source.  Drag the data source from Data Sources and drop it on the form editor under the purple data sources region.
  7. Click the Options property in the data source and then add a row for each option as shown above.
  8. Remember to hook the data source to the control.  To do this, click on the group checkbox control and find the Data Source property.  Select your data source.
  9. Once the model is complete, click the Save button at the bottom of the screen.
  10. Create a content and the sidebar config.

Step 3 B: Configure the UI for Products

Once you save your content type it will be available for content authors to use it.  Studio does this automatically. That said, the more tailored the UI is for your content authors, the easier it will be for them to use it.
Note that this step is not necessary to complete the integration but it does make a difference for authors.

  1. If you click the Crafter CMS logo, you will be taken to the dashboard.  Open the Pages folder on the Sidebar and note that you can right-click on the Home page.  In the drop-down menu, you will find an option for “New Content” as shown below.
  2. Click on the New Content option and you will see your new content type as shown below.A product doesn’t really map to any of the out-of-the-box content folders.  It’s not a page and it’s not a component.  What we want is a unique store just for products.  Cancel the create operation and let’s set up a folder for products and then tie the product content type to it.
  3. Using the Sidebar, navigate to the Site Config panel and then to the Configuration tool.
    Select the Sidebar Configuration tool.
  4. In the configuration, you will note the various modules shown in the Sidebar navigation.  Add a new module block as shown below for products.  You’ll note that at first, we’ll “root” the folder at “/site.”  We’re going to change this later but for now, setting it up this way will allow us to create additional folder structure within the CMS.  Add the module configuration snippet and click the Save button.

    <modulehook>
      <name>wcm-root-folder</name>
      <params>
        <label>Products</label>
        <path>/site</path>
        <showRootItem>true</showRootItem>
        <onClick>preview</onClick>
       </params>
    </modulehook>
  5. Once complete, navigate back out to the dashboard via the Crafter CMS logo and open the Sidebar.  You will find your new Products folder displayed.
  6. Open the products folder, right-click the site folder and then click the New Folder option.  When prompted for a name, enter products and click the Create button.
  7. Now, return to the Sidebar Configuration.  Let’s update the folder so that it shows only the products.  We do this by modifying the path parameter for the module.  Further, we’ll add some custom icons to help visually differentiate the folder within the sidebar.

    <modulehook>
      <name>wcm-root-folder</name>
      <params>
        <label>Products</label>
        <module-icon-open>
          <class>fa-shopping-bag</class>
        </module-icon-open>
        <module-icon-closed>
          <class>fa-shopping-bag</class>
        </module-icon-closed>
        <path>/site/products</path>
        <showRootItem>true</showRootItem>
        <onClick>preview</onClick>
      </params>
    </modulehook>
  8. Now let’s update the Studio Site config so that Studio better understands the content found under the /site/products path.  In the Configuration tool open Site ConfigurationAdd configuration under folders and patterns as shown below:
    
    
    <folders>
      <folder name="Pages" path="/website" read-direct-children="false" attach-root-prefix="true"/>
      <folder name="Products" path="/products" read-direct-children="false" attach-root-prefix="true"/>
      <folder name="Components" path="/components" read-direct-children="false" attach-root-prefix="true"/>
      <folder name="Assets" path="/static-assets" read-direct-children="false" attach-root-prefix="false"/>
      <folder name="Templates" path="/templates" read-direct-children="false" attach-root-prefix="false"/>
    </folders>
    ...
    <pattern-group name="component">
      <pattern>/site/components/([^&lt;]+)\.xml</pattern>
      <pattern>/site/products/([^&lt;]+)\.xml</pattern>
      <pattern>/site/system/page-components/([^&lt;]+)\.xml</pattern>
      <pattern>/site/component-bindings/([^&lt;]+)\.xml</pattern>
      <pattern>/site/indexes/([^&lt;]+)\.xml</pattern>
      <pattern>/site/resources/([^&lt;]+)\.xml</pattern>
    </pattern-group>
  9. Once you save this file and return to the dashboard or preview you will note that Products now has its own icon and when you open it, it is specifically rooted in the products folder in the repository.
  10. Modify the content types to tie them to the IA.  An author should not be able to create a product anywhere except under products.  Other content types may also be tied to specific folders.  Let’s look at how we can configure this.In the content type editor for a product, under the Basic Properties for the type, find the Configuration Property.  Click the pencil to open the editor for the configuration.
    Add the following XML snippet to the content type configuration:

    <paths>
      <includes>
        <pattern>^/site/products/.*</pattern>
      </includes>
    </paths>


    Open the other 2 content types and add the following snippet.  This snippet hides these types because it does not make sense for authors to be able to create new objects of these types.

    <paths>
      <includes>
        <pattern>^hidden</pattern>
      </includes>
    </paths>
  11. Navigate to the dashboard and try to create content in the products area.  If the previous steps were performed correctly the form for the Product content type will be automatically launched as soon as you click the New Content button.  Studio understands (based on the configuration) that this is the only type that is allowed to be used here and thus defaults to it.

    The form will automatically open:

 

Step 3 C: Create Product Content

Now that your authoring tools are set up to make it easy to add products it’s time to create some product content.  Using the New content option, and following the content on the site (or in the JSON response) create at least two products by right clicking on the product folder then filling out the product form and saving.


  1. You can easily create new content by right-clicking on the products folder and selecting the New Content option.
  2. Create as many products as you like by filling out the Product form and clicking the Save and Close button.  You will need at least 2 products for the example to work well.

Step 4: Create a basic RESTful service

Now that we have content, we can create a RESTful service to return the content from the CMS as JSON. Once our service is in place we’ll modify the application to consume our service instead of the service it uses out of the box.

Step 4-1: Create the Service

Crafter allows us to easily create RESTful services through scripting.  By putting the Groovy script in the right location with the right naming convention we define an RESTful endpoint. https://docs.craftercms.org/en/3.0/developers/projects/engine/api/groovy-api.html

  1. In the Sidebar, open the Scripts folder and then open the rest folder.
  2. On the rest folder right click and choose Create Controller option.
  3. Provide your service name and http method you want.  In our case our service is going to return products so our service name is “products” and the HTTP method the service will respond on is a GET so we append .get to the name.
    1. This is a convention in Crafter CMS.  Under the rest folder we can create any number of sub folders and the file name of the RESTful endpoint is named by the script as NAME.HTTPD_METHOD.groovy.
    2. all standard request methods are supported ex: get, post, put, delete,
  4. Click Create and then supply some basic code in your controller as shown below.
    This code will result in an object with an empty products array.  By returning the result value at the end of the script Crafter knows to marshal this object in to JSON for us when the service is invoked via the URL.
  5. Test the service.
    1. Go to http://localhost:8080/api/products.json in your browser and you will see the JSON representation of the object returned by the script.
  6. Now we that we see our service working we can update it to return the content we want in the structure we want.
    1. Right click on the controller and then click Edit.
    2. Update the code as show below.
def result = [:]

def queryStatement = 'content-type:"/component/product"'

def query = searchService.createQuery()
 query = query.setQuery(queryStatement)
 // limit returned fields if you like
 //query.addParam("fl", "localid:cmsId,sku,title,style,description,price,installments,freeShipping,sizes.item.key")

def executedQuery = searchService.search(query)
def itemsFound = executedQuery.response.numFound

result.products = []

executedQuery.response.documents.eachWithIndex { document, idx ->
 def product = [ 
 id: idx,
 cmsId: document.localId,
 sku: document.sku, 
 title: document.title, 
 style: document.style,
 description: document.description,
 price: getPrice(document),            // potentially get the price from external system
 installments: getInventory(document), // potentially get inventory from external system
 isFreeShipping: document.freeShipping,
 availableSizes: document["sizes.item.key"],
 currencyId: "USD", // hard code USD for now
 currencyFormat: "\$", // hard code currency format for now
 ]
 
 result.products.add(product)
}

return result

def getPrice(document) {
 // simple example of abstracting where price comes from
 return new Float(document.price)
}

def getInventory(document) {
 // simple example of abstracting where inventory comes from
 return new Integer(document.installments)
}

 

The code above makes a query to Crafter Search / Solr and then iterates over the results to format, structure and possibly embellish them with additional data.  Note, that if there is no need to restructure or augment the results differently than the Solr response the results could be returned directly without any additional code.  Simple field name mappings can be done with the fl query parameter.

7. Invoke the response and confirm it now meets the structure and contains the content that the application expects.

Go to http://localhost:8080/api/products.json in your browser and you will see the JSON representation of the object returned by the script.

Step 4-2: Modify the App to use the Service

Now that we have a service which dynamically provides the products that are created and edited/managed by the authors in the CMS we can update our React Application to use it.

To do this:

  1. Change line 5 in src/store/actions/productActions.js to

    const productsAPI = "/api/products.json"
  2. Add the following to package.json
    "proxy": {
      "/api": { "target": "http://localhost:8080" },
      "/studio": { "target": "http://localhost:8080" },
      "/static-assets": { "target": "http://localhost:8080" }
    },
  3. Preview the application at http://localhost:3000
    Note the content showing in the store is from the CMS

Step 5: Extend the service to include images managed by authors

The out of the box application uses statically managed images and convention. We’ll add images to the CMS to demonstrate extending our content model and app. This step is optional and is simply meant to show how you can extend the functionality if choose.

  1. In the product content model:
    1. Add image pickers for both large and small images
    2. Add a data source for picking images from the desktop.
    3. Configure the data source to put images in /static-assets/images
    4. Click on the image picker properties and connect the data sources to the image pickers
  2. Test the forms by updating your products with image content.
  3. Update your RESTful product service to return image values.

    def product = [ 
     id: idx,
     cmsId: document.localId,
     sku: document.sku, 
     title: document.title, 
     style: document.style,
     description: document.description,
     price: getPrice(document), // potentially get the price from external system
     installments: getInventory(document), // potentially get inventory from external system
     isFreeShipping: document.freeShipping,
     availableSizes: document["sizes.item.key"],
     currencyId: "USD", // hard code USD for now
     currencyFormat: "\$", // hard code currency format for now
     largeImage: document.largeImage,
     smallImage: document.smallImage
    ]
  4. Update the application to pull the images from the service rather than assume their location in the application.
    1. Update the file src/components/Product.js line 34
      <Thumb
       classes="shelf-item__thumb"
       src={product.largeImage}
       alt={product.title} />
    2. Update the file: src/components/Thumb.js
      import React from 'react';
      import PropTypes from "prop-types";
      
      
      const Thumb = props => {
       return (
       <div className={props.classes}>
       <img src={props.src} alt={props.alt} title={props.title} />
       </div>
       );
      };
      
      Thumb.propTypes = {
       alt: PropTypes.string,
       title: PropTypes.string,
       classes: PropTypes.string,
       src: PropTypes.string.isRequired,
      };
      
      export default Thumb;
  5. Preview the application at http://localhost:3000
    Note the content showing in the store is from the CMS

Step 6: Add in-context editing to the solution

Now that the app’s content is driven by the CMS we want to make it is easier for the content authors to find and edit their content. Making content editable directly through the app is one of the best ways. In this step, we’ll make the small modifications and configurations necessary to support this.

  1. Note that in our service we are returning a property called cmsId.  This property will be used by the app to identify the content that the editing tools will be associated with.



6.1 Indicate Where the In-context Editing Regions “Pencils” Belong

To enable point and click on content editing on content, you must indicate where the regions are and what content the regions relate to. To do this in HTML5 applications Crafter Studio (and the Guest library) uses HTML5 attributes.

The following attributes are used:

  • data-studio-ice: This property marks the element as the container for in-context editing. No value is required.
  • data-studio-component-path: This is the path of the content object. Example: “/site/products/a-component.xml”
  • data-studio-ice-path: This is the path of the content object. Example: “/site/products/a-component.xml”
  • data-studio-component: This is the content type name. Example: “/component/product”

Example Container element:

<div data-studio-component-path=”/site/products/a-component.xml”
data-studio-component=”/component/product”
data-studio-ice=””
data-studio-ice-path=”/site/products/a-component.xml”>
INNER HTML
</div>

  1. Update the application to pull the images from the service rather than assume their location in the application.
    1. Update the file src/components/Product.js line 34
      <Thumb
       classes="shelf-item__thumb"
       src={product.largeImage}
       alt={product.title}
       cmsId={product.cmsId} />
    2. Update the file: src/components/Thumb.js
      import React from 'react';
      import PropTypes from "prop-types";
      
      
      const Thumb = props => {
       return (
       <div className={props.classes} 
       data-studio-component-path={props.cmsId} 
       data-studio-component="/component/product" 
       data-studio-ice="" 
       data-studio-ice-path={props.cmsId}>
       <img src={props.src} alt={props.alt} title={props.title} />
       </div>
       );
      };
      
      Thumb.propTypes = {
       alt: PropTypes.string,
       title: PropTypes.string,
       classes: PropTypes.string,
       cmsId: PropTypes.string,
       src: PropTypes.string.isRequired,
      };
      
      export default Thumb;
  2. Preview the application at http://localhost:3000/studio
    Note the content showing in the store is from the CMS

  3. Turn the pencils on by clicking on the pencil in the main toolbar.
  4. Hover over each product content item.
  5. Click the pencils to edit and the user will get the form where they can edit the content.
  6. Update the content.
  7. Click the Save and Close button. On save the preview will update to reflect the changes.
  8. That’s it! The preview updates.


Conclusion

 

React has become the de facto way to build highly usable web-based applications.  React helps developers create Single Page Applications that are fast and extremely usable for end users.  When those applications need content that’s managed by business users, developers have turned to headless CMS solutions to supply the content.  Unfortunately, most Headless CMS platforms do not provide full-featured editing tools like in-context editing, preview, and drag-and-drop.  Content editors are used to these tools and when they are missing it can be frustrating.

With Crafter CMS, everybody wins.  Content authors get the experience they are used to.  Developers get the architecture and development frameworks and the process they want.

CMS for SPAs (1 of 4): Are Single Page Applications and Headless CMS a Slam Dunk?

From web-based applications like Gmail, Instagram, and Google Maps to websites like The New York Times and Facebook, real-world examples of Single Page Applications (SPA) are everywhere you look. Developers have been turning to SPA frameworks and architectures to create better, more usable, richer applications for their users.

Nearly every Content Management System (CMS) out there purports to support SPA frameworks and architectures. In this blog series, we’ll look at SPA use in the CMS space to learn more about what’s working, what’s not and what we can do about it. Let’s jump in.

SPAs are web-based applications built with rich UI frameworks that run client side and use partial page updates rather than full page refreshes to update data, content, and UI. SPAs have several advantages:

  • Great user experience: SPAs make the user experience more fluid with rich UI interactions that leverage asynchronous calls to the server for data and partial page refreshes.

  • Clean architecture: SPAs architecture promotes a clean separation of the frontend application and backend services and data. This approach makes development faster and more flexible.

  • Great frameworks: There are a lot of great frameworks that make developing SPAs faster and easier including React, Angular, Vue and others.

In the CMS space, SPA applications have been a win for developers but content authors have taken a major hit.


Developers have been keen to adopt SPA technology and CMS vendors have quickly responded with support for Headless CMS (also known as Content as a Service [CaaS]) support.

This shift has been highly promoted by CMS vendors because it has a number of advantages with respect to content management. Returning content as JSON or other presentation-less formats makes content more reusable within and across delivery channels. More importantly, by removing the consuming application from the CMS, the approach seems to solve one of the major challenges in the CMS space: development. It’s no secret that most developers have little interest in working within the toolsets and constraints of a CMS. Developers want control over their tools, frameworks, and process. CMS platforms are notoriously framework laden and don’t integrate well with DevOps tools and process.

The headless approach completely and neatly decouples development and content production workflows. On the surface, the headless approach appears to be a perfect evolutionary step for CMS. New delivery channels and integration opportunities show up all the time. In a customer experience driven market, anything that aids development and reduces time to market is seen as a winner.

However, the reality is that decoupling the CMS from the consuming application does not solve long-standing challenges such as refreshing content in lower environments — in fact, it complicates them. Worse, complete decoupling creates new problems. While software development and content production workflows are best divorced, their products: the code and content are not. There is a time/version specific relationship between the data model, the content and the code at any given moment. To illustrate the point: it’s often not possible to “point” an older version of an application at a newer version of the content and vice versa. It’s extremely difficult to troubleshoot or perform legal and regulatory audits without this capability. Yet, with the clear benefits of better products, a cleaner deployment architecture and faster, easier development in mind, the remaining issues are either unrecognized or a compromise many developers are willing to take. For developers, the SPA and headless approach have largely been a win.

The ironic and unfortunate “dirty little secret” in the CMS space of late is that the biggest losers of the headless CMS movement have been the content authors, CMS’s main stakeholder.

Today’s headless CMS options have the following drawbacks for authors:

  • There is no preview. Authors are used to in-context editing and preview. With headless, they are back to working in forms with no preview and are left to hope and a cumbersome process to ensure that the content will present properly.
  • There is no personalization. Marketers want to be able to target and personalize their messaging to the audience. Most headless CMS platforms don’t give them the capability to describe and execute targeting rules much less test and preview the various scenarios.
  • DevOps are still not supported: Despite investments in new technology, tools and process content authors see zero improvements in DevOps activities related to feature releases. Content freezes and outages are still commonplace during feature deployments with headless CMS.

It doesn’t have to be that way! With the right CMS architecture and platform content authors, developers and DevOps can work together on SPA based sites and applications at speed with the tools and processes they are accustomed to (like in-context editing) without stepping on each other’s toes.

A Better Approach to SPAs, CMS and DevOps

Crafter CMS is an open source CMS platform that takes a completely different approach to headless CMS, SPA development and DevOps. Crafter CMS has a very different architecture from traditional CMS platforms that are monolithic and rely on SQL databases and JCR repositories.

Crafter’s architecture is modular, flexible, and completely elastic with a repository and deployment design that is shared-nothing and based on Git. This architecture enables Crafter CMS the flexibility to support content authors, developers and DevOps to collaborate together to build and release new experiences with minimal friction while using the tools and workflows that work best for them.

Crafter CMS is an API first CMS that is:

  • UI agnostic and can support development and editing and preview for any UI framework
  • Capable of supporting rich, personalized headless CMS content
  • Git-based to support your development frameworks, tools, and process in a way that separates development and content production workflows without needing to separate the deployable (code and content) artifacts.

Conclusion

SPA applications combined with decoupled, headless CMS offer significant advantages in terms of end-user experience, development, and deployment. However, it’s clear that headless is not a silver bullet. Completely divorcing the CMS and the consuming application or site creates significant challenges for DevOps, support and other departments. More importantly, the SPA/headless pairing has left authors out in the cold by taking away the process and tools they have become accustomed to over the past decade.

These shortcomings can be addressed with a new breed of CMS architecture. What’s needed is a flexible headless CMS that support proper authoring tools and process regardless of front-end technology. Moreover, we need a CMS that embraces and integrates development tools and process rather than shunning them. That’s exactly what we’ve set out to do with Crafter CMS. Stay tuned for our next blogs in this series where we’ll dive deeper into these concerns and their solutions.

What has your experience been working with SPAs and your CMS?

Introducing Crafter CMS Javascript SDK

Crafter CMS is a headless CMS that provides all of it’s services and capabilities to consumers via RESTful APIs. This enables developers to easily build content support (externalized management of content, strings, media, etc) into any application written in any programming language.

Crafter CMS also supports language-specific (e.g. Java, Groovy, Javascript, .Net, etc) and framework-specific (Angular, React, Vue, etc) bindings. These bindings make the programming model not just simple but native to the language or framework. Using RESTful APIs is easy but native bindings further reduce programming time and complexity by simplifying and reducing the code required to get the job done.

In this blog, we will focus on the language-specific bindings for Javascript, the Crafter CMS Javascript SDK. These bindings can be used in any client side (e.g. a browser-based application) or server-side (e.g. Node.js) applications.

The High-level Architecture

Before we get into the specifics of the Javascript SDK let’s quickly review the architecture. Below is a diagram that illustrates how the SDK works in your Javascript application with Crafter Engine and other Crafter CMS components to deliver managed content to your application.

You can learn more about the overall architecture of Crafter CMS here. In the diagram above we illustrate the following:

  • Authors work in Crafter Studio (a web-based application) to create and manage content. Crafter Studio provides authors with the tools they need to make updates, perform workflows and publish. Approved updates can be published to Crafter Engine(s) for content delivery at any time via the UI without any technical assistance.
  • Crafter Engine exposes content, navigation, and structures via RESTful services that are available over HTTP(s). Content and data are returned to the caller as JSON.
  • The caller in this architecture is Crafter CMS’s Javascript bindings library which is making requests on behalf of the application.
  • The Crafter CMS Javascript SDK provides the application code with Javascript based interfaces and classes to interact with. There’s no need for the application code to concern itself with REST, JSON and other lower level concepts.

Pre-requisites for Using the Library

  • NPM / Yarn installed
    • The SDK releases are published to Node Package Manager (NPM.) Example: https://www.npmjs.com/package/@craftercms/content
    • NPM will help you easily download the proper dependencies. You can all so use NPM or Yarn to build and execute your application.
    • In our example, I will use Yarn to manage my package.json file and to assist me in building my application.
  • Access to a running Crafter Engine instance and site.
    • You may need to configure the site due to CORS (Cross-Origin Resource Sharing constraints within browsers) to allow requests from your application if the app and Crafter Engine are running from different base domains. We’ll explain this further later.

Building a Simple Javascript Application

The point of our application in this blog is to demonstrate how to include and use Crafter CMS’s Javascript SDK in an application and to use it to retrieve content from a running Crafter Engine instance.  We’re going to keep the application extremely bare bones in order to illustrate that this library is independent of any specific frameworks or platforms such as Node.js, React, Angular6, Vue etc.

For those looking to get right into the meat of the integration, use of the SDK starts at Step 4.

Step 1: Create a basic structure and build for the app

The first thing we want to do is to create a directory for our application source. I will call my directory simple-js. Inside that directory add a file called package.json with the following content:

{
 "name": "simple-js",
 "version": "1.0.0",
 "description": "Simple JS app that will use Crafter CMS Javascript SDK",
 "main": "index.js",
 "author": "Russ",
 "license": "MIT",
 "dependencies": {
 "@craftercms/classes": "^1.0.0",
 "@craftercms/content": "^1.0.0",
 "@craftercms/models": "^1.0.0",
 "@craftercms/search": "^1.0.0",
 "@craftercms/utils": "^1.0.0"
 },
 "scripts": {
 "test": "echo \"Error: no test specified\" && exit 1",
 "build": "webpack"
 },
 "devDependencies": {
 "webpack": "^4.17.1",
 "webpack-cli": "^3.1.0"
 }
}

 

This file describes our application, how to build it and what is needed to build it. In the content above we can see:

  • The application metadata.
  • The application dependencies we are requiring are the various Crafter CMS Javascript SDK dependencies ( “@craftercms/content”: “^1.0.0”, “@craftercms/search”: “^1.0.0”, etc.)
  • The application build/dev dependencies that help us compile the application for distribution ( “webpack”: “^4.17.1”, “webpack-cli”: “^3.1.0”.)

Step 2: Perform an initial build

Run yarn in your application directory. This will download all of your dependencies.

Step 3: Create an application Javascript

Note that in our package.json we’ve listed index.js listed as the main for the application. Let’s create the src directory and create an index.js in the src directory.

I’ll use the Unix touch command to create the index.js. This creates an empty file.

Once the file is in place you can run a yarn build command.  This will create a dist folder with a compiled main.js. The main.js file contains a minified, concatenated set of your dependencies and your script.js code (which is currently empty.)

Step 4: Create an application HTML

Now that our application is building, let’s create a page we can load in a browser and add some basic logic.

In your simple-js directory add a file called index.html with the following content:

 <!doctype html>
 <html>
   <head>
     <meta http-equiv="Content-Type" content="text/html;charset=ISO-8859-1">
     <title>Getting Started</title>
   </head>
   <body>
     <script src="./dist/main.js"></script>
   </body>
 </html>

As you can see, all this HTML does is declare the head and body of our page and call the main.js script file.

To make our application a little more interesting, let’s add some basic logic to our script.js file. Add the following code the src/script.js file:

function component() {
  var element = document.createElement('div');
  element.innerHTML = "Hello World";
  document.body.appendChild(element);
}
component();

Now rebuild your application using the yarn build command and open the index.html file in your browser to see your application running.

Step 4: Calling Crafter CMS API’s with our application

Now that we have a very basic, working application it’s time to use the Crafter CMS Javascript SDK.

Crafter Engine Instance

In order to use the Crafter CMS APIs, you will need a running Crafter Engine instance with a project set up that you have access to. It’s easy to get started. Here are some helpful links on getting things set up:

CORS: Cross-Site Scripting rules

If you are following this blog step-by-step you are likely running Crafer Engine on localhost and you are loading your HTML file from local disk (e.g. file:///Users/rdanner/code/simple-js/index.html.)

From a browser’s perspective, “http://localhost/…” and “file:///…” are different host domains.  A browser, by default, will stop you from making AJAX calls from code loaded in one domain to a different domain unless the receiving domain gives the browser an OK with the proper HTTP headers. This browser behavior is a protection against CORS (Cross-Origin Requests / Cross Site Scripting) type attacks.

In Crafter CMS, you can set up the proper headers for the receiving server (Crafter Engine) to support this example by taking the following steps:

  1. In Crafter Studio, for your site/project, go to Site Config (found in the Sidebar)
  2. Select the Configuration tool. In the drop-down select the Engine Site Configuration option.
  3.  Add the following configuration and click the Save at the bottom of the screen.
    <site>
     <!-- CORS Properties -->
     <cors>
       <enable>true</enable>
       <accessControlMaxAge>3600</accessControlMaxAge>
       <accessControlAllowOrigin>*</accessControlAllowOrigin>
       <accessControlAllowMethods>GET\, POST\, PUT</accessControlAllowMethods>
       <accessControlAllowHeaders>Content-Type</accessControlAllowHeaders>
       <accessControlAllowCredentials>true</accessControlAllowCredentials>
     </cors>
    </site>

Import the APIs into your application javascript

Add the following code at the very top of your index.js script file. Here we are declaring the classes we will use and indicating where they are imported from (the SDK.)

import { ContentStoreService, NavigationService, UrlTransformationService } from '@craftercms/content';
import { crafterConf } from '@craftercms/classes';

Configure the SDK for your Crafter Engine endpoint base URL (server name, port etc)

Now that you have declared the Crafter CMS SDK services you want to use you are almost ready to start retrieving content. Before we can, we need to make sure the SDK APIs know where Crafter Engine “endpoint” / server is and what site to pull the content from. To do that we have two options:

  • We can create a configuration object and pass it with each call
  • Or we can explicitly supply the endpoint configuration with each call

Since we’re going to use the same endpoint and site, we’ll set up a configuration object and pass it when we call the APIs. To configure the endpoint we add the following code to our script after the import statements:

crafterConf.configure({
 site: 'editorial'
});

The configuration above states that our API calls will reference the site in Crafter Engine that has the “editorial” ID. By default, the configuration assumes that Crafter Engine is running locally on port 8080. To change this, add the following:

baseUrl: “YOUR_PROTOCOL//YOUR_DOMAIN:YOUR_PORT ”

crafterConf.configure({
 site: 'editorial',
 baseUrl: "https://mydotcomsite"
});

If you want the system to assume that the app and the API endpoints are on the same server you can set base URL to an empty string (“”)

Call a Crafter CMS API and get content

Make the code changes:

Now that the library is imported and configured, we’re ready to use it. Let’s add the code to our example to make a request for content and put it on the screen for the user. Below is the entire index.js script for our application with changes:

import { ContentStoreService, NavigationService, UrlTransformationService } from '@craftercms/content';
import { crafterConf } from '@craftercms/classes';

crafterConf.configure({
 site: 'editorial'
})


function component() {

   ContentStoreService.getItem("/site/website/index.xml", crafterConf.getConfig()).subscribe((respItem) => {
      var element = document.createElement('div');
      element.innerHTML = respItem.descriptorDom.page['hero_title'];
      document.body.appendChild(element);
    })
}

component();

What we’ve done is replace the code in the component function that was hardcoded to write “Hello World” on the screen for the user with the code that calls Crafter CMS for content and write the retrieved content on the screen instead.

Let’s take a closer look at the API call; ContentStoreService.getItem

  • The first parameter is the path of the content item we want to return.  The example uses the home page of the editorial site.
  • The second parameter is our configuration object which supplies the site and endpoint base URL configuration.
  • Lastly, you will note the subscribe operation.The SDK makes asynchronous calls to the Crafter Engine component of Crafter CMS. Subscribe allows you to supply the code you want to execute when the call returns. In our example, this is where we create an element, get our content value (hero_title) from the returned response and then update the application with the content.

Compile the code

Once you have updated your code, rebuild the application.

Test the application

After you compile, if you refresh your application you should see content from your Crafter CMS project show up in the updated app!

Congrats! Your application’s content is now externalized and managed in the CMS.

Step 5: Update your content using the CMS

Now that our code is complete our content authors can update the content at any time via the CMS and we don’t need to rebuild or redeploy the application. Let’s use Crafter Studio to update the content for our app. You can find detailed how-to help here: Creating and working with your First Crafter Site

In Crafter Studio, find the content you want to edit

In our case, the content we’re consuming is the hero title. Let’s make an edit to that content:
In your site’s content preview, turn on the editing pencils and click the pencil for the Hero Title (as shown above.)


Note that the author has a preview of the content. This is something very different and ultimately much better than what you see with other Headless CMS systems.

With Crafter, it’s always possible to provide the user with a preview of the content they are editing regardless of the front end framework. Preview capability is key because it makes editing content easier for authors.

Make a content change and save

After you click the pencil for the Hero text make the change and then click the Save and Close button at the bottom of the form. You will see your update in the CMS right away.

Refresh the example application

Wow! Those changes in the CMS look great (if I do say so myself :D!) Now it’s time to see the changes in our application. Simple, just refresh your application in the browser. No code updates required!

It’s really just that simple! A few lines of code allows us to create applications with content, configuration and other strings that we can update at any time without needing to update or redeploy our application code.

What about workflow and publishing?

Good question! Most of the time you want a review and approval process before content updates to applications are made public. We call this process workflow and publishing. Crafter CMS has workflow and publishing capabilities right out of the box.

To keep our example as simple as possible I kept the architecture simple and we pointed our application directly to Crafter Studio and the preview server on localhost, port 80.

In the configuration above, the API will see updates immediately. The architecture in the High-Level Architecture section above shows a typical production topology in which updates go through approval workflow and publishing. Once the content is approved and published it is then available to the application.

Getting to know the SDK API

In our example application, we consumed a single service method from the SDK. Now that we know how to use the SDK let’s take a look at the various services and service methods the SDK provides:

Service Description
Content Service
(@craftercms/content)
This package contains services for retrieving content and navigation using APIs offered by Crafter CMS.

  • Get a content object and its associated content attributes
  • Get a tree of content objects (children, trees etc)
  • Get dynamic navigation and breadcrumb structures
  • Execute URL transformations

API Specification and examples:
https://www.npmjs.com/package/@craftercms/content

Search Service
(@craftercms/search)
This package contains tools for integrating your application with Crafter Search.

  • Create Crafter Search query objects
  • Execute Crafter Search queries

API Specification and examples:
https://www.npmjs.com/package/@craftercms/search

 Conclusion

Crafter CMS’s Javascript SDK gives front end and full stack developers who work in Javascript and Javascript related technology a native programming API to work with that makes building content-rich applications much easier to do.

When we stop an think about it, almost every application has content in it. If that content is easy to update and updating the content can be done by non-technical users at any time without a build or deployment everybody wins:

  • The content in the application is richer and much fresher
  • Developers spend time developing rather than making non-code related updates
  • Removing non-feature related deployment distractions gives us more time and makes our teams more agile.
  • Our business users can make their changes at any time which makes the business more agile.

Headless CMS capabilities provide non-technical users with the ability to update, workflow and publish an application’s content at any time without the involvement of developers and IT.

Crafter CMS’s headless capabilities go beyond traditional headless CMS systems by providing authors with an in-context preview for content editing and giving developers the freedom to use whatever front-end technology they want.

 

Integrate Crafter CMS with Jenkins to Automate DevOps: Code Forward, Content Back Process

Great DevOps helps us build better software products faster. One of the key elements of DevOps is automation within the development process across lower development environments.  Jenkins, Bamboo, Travis and many others platforms like them are used by DevOps teams to help automate the process of Continous Integration and Continous Delivery (CI/CD). To a large degree, real support for CI/CD and agile development is something that is woefully missing in Content Management, a core component of digital experience platforms.  The toolset and the architecture of today’s content management platforms make it difficult, sometimes near impossible to support let alone automate. How easy is it for your team to take content from the Production CMS and update content in lower environments like Dev, QA?  How easy is it to roll out new features?  Often times this process is not only laborious for the DevOps team, it also halts the content authoring process.    Crafter CMS’s, an open source CMS Git-based repository and Java/Spring and Groovy-backed stack are a game changer in this regard.  Further, Crafter integrates directly into to your CI/CD process.  In this article, using Jenkins as our example we’ll demonstrate how you can connect your production CMS to your developer workflow to facilitate Code Forward, Content Back(TM) workflow.
You can read more about this process in detail here:

Although our example is based on Jenkins, the scripts and flow used in this blog are applicable to nearly any automation

Understanding Where Code Forward, Content Back Automation Fits

The fact is that every step of your DevOps process is open to automation.  In this section, we’ll cover the common points of integration, specifically:

  • The point in the process where you want to move content from your production CMS “back” to lower environments to support development and testing.
  • The point where you want to promote code “forward” from the development process to the production CMS so it can be published.

Both of these points in the process are illustrated and addressed in the diagram below by the double-headed arrow labeled Code Forward, Content back.   With respect to the CMS, Code Forward, Content Back is the most important aspect of the DevOps automation.

Crafter CMS’s Git-based repository is the foundation of the automation.  Our automation running in Jenkins is going to leverage API’s within the authoring environment (Crafter Studio) to sync code and content with the development process.  APIs will also be used to publish code synced to authoring to the Production delivery infrastructure.

Implementing Code Forward, Content Back Sync

Now that we’ve established what integration we’re addressing here is, let’s focus on configuring it.  Take a look at the diagram below, this elaborates the previous diagram showing how the sync occurs.

Note that both the Production authoring and the Development “environment” has a repository.  In authoring, this is a local Git repository.  In development, this is most often a centrally hosted Git repository that supports workflow and review (like Bitbucket, Gitlab, Github, and others.)   You can think of the repository under authoring as the Content Repository and the repository supporting developers as the Code Repository.  These names (Content Repository, Code Repository) are simply labels to help describe their purpose and assist us in addressing them in the context of this article.

To facilitate this flow, the Content Repository under authoring/Crafter Studio declares the Code Repository as a remote. The primary way of “syncing” work between Git repositories is through pull and push operations.  Before you can push your work to a remote, you must first pull merge the updates (if any) from the remote.  Once done, you can push your changes to the remote.

Automating the Pull / Push of Code and Content

To help automate the process described above Crafter Studio, the authoring and repository component of Crafter CMS supports a set of APIs.  You can find a full listing of Crafter Studio APIs for Crafter 3.0 here: http://docs.craftercms.org/en/3.0/developers/projects/studio/index.html

These APIs are easily invoked by a script.   You can use the following example script in your own implementation:

codeforward-contentback-sync.sh

#!/usr/bin/env bash
studioUsername=$1
studioPassword=$2
studioserver=$3
project=$4
remote=$5
branch=$6

echo "Authenticating with authoring"
rm session.txt
curl -d '{ "username":"'$studioUsername'", "password":"'$studioPassword'" }' --cookie-jar session.txt --cookie "XSRF-TOKEN=A_VALUE" --header "X-XSRF-TOKEN:A_VALUE" --header "Content-Type: application/json"  -X POST $studioserver/studio/api/1/services/api/1/security/login.json

echo "Pull from remote (get code waiting to come to sandbox)"
curl -d '{ "site_id" :"'$project'", "remote_name":"'$remote'", "remote_branch":"'$branch'" }' --cookie session.txt --cookie "XSRF-TOKEN=A_VALUE"  --header "Content-Type: application/json" --header "X-XSRF-TOKEN:A_VALUE" -X POST $studioserver/studio/api/1/services/api/1/repo/pull-from-remote.json

echo "Push to remote (send content waiting to go to development)"
curl -d '{ "site_id" :"'$project'", "remote_name":"'$remote'", "remote_branch":"'$branch'" }' --cookie session.txt --cookie "XSRF-TOKEN=A_VALUE"  --header "Content-Type: application/json" --header "X-XSRF-TOKEN:A_VALUE" -X POST $studioserver/studio/api/1/services/api/1/repo/push-to-remote.json

Use of the script:

codeforward-contentback-sync.sh [USERNAME] [PASSWORD] [AUTHOR_SERVER_AND_PORT]  [SITE_ID] [REMOTE_NAME] [BRANCH_NAME]

USER_NAME is the Studio user (application account)
PASSWORD is the Studio user password (application account)
AUTHOR_SERVER_AND_PORT the protocol server name and port of Studio
SITE_ID the ID of the site
REMOTE_NAME the name of the upstream (typically origin)
BRANCH_NAME the name of the branch (typically master)

Example:
codeforward-contentback-sync.sh devops mydevopspw http://localhost myprojectID origin master

The script is quite simple.  It authenticates to Crafter Studio, performs a pull from the Remote Code Repository and then if there are no conflicts, performs a push.  These two operations move code updates forward to the production Sandbox (not yet live) and content back to the development process.  Only approved code that’s been moved to the “master” branch with the intention to release is moved forward.

Calling the Script in Jenkins

The first step is to create a project.  Give the project a clear name and select the Freestyle project then click OK to continue.

There is no Source Code Management (SCM) aspect of the project.  The most typical use case for Content back workflow is a scheduled event: Every hour, day, week etc.

 

The next step is to define build triggers.  Since you are calling APIs here and content back is most likely based on some schedule you define you want to indicate that there is no Source Code Management (SCM) aspect of the project.

Select “Build Periodically” and define your schedule.  Schedule definitions user standard Cron/Quartz configuration.

Finally, you must define that you want Jenkins to call your script:

Once you have done these steps you are ready to go.  Manually invoke this build any time you want directly through the Jenkins console.  I recommend testing it to make sure your parameters and schedule are correct.

Publishing Code That’s Been Sync’d to Sandbox

When you run the code forward, content back process code in the remote code repository is moved to the production authoring sandbox (content repository.)  This code is now staged for publishing.  It is not yet live.  Crafter Studio must publish the code, making it available to your delivery servers.  This in-and-of-itself is awesome: global, elastic deployment at the touch of a button.

So how is it done?  Crafter Studio provides an API that allows you to publish commit IDs.  You can provide a single commit ID or you can provide a list.  It’s typical as part of your release process to “Squash” all of the commits in a given release into a single commit ID.  This allows you to address all of the work as a single ID/moniker which makes it very easy to move, publish and roll back without missing anything.

These APIs are easily invoked by a script.   You can use the following example script in your own implementation:

publish-code.sh

#!/usr/bin/env bash
studioUsername=$1
studioPassword=$2
xsrf=AUTOMATED
studioserver=$3
project=$4
env="Live"
commit=$5

echo "Authenticating with authoring"
rm session.txt
curl -d '{ "username":"'$studioUsername'", "password":"'$studioPassword'" }' --cookie-jar session.txt --cookie "XSRF-TOKEN=A_VALUE" --header "X-XSRF-TOKEN:A_VALUE" --header "Content-Type: application/json"  -X POST $studioserver/studio/api/1/services/api/1/security/login.json

echo "Publishing Commit $commit"
curl -d '{ "site_id" :"'$project'", "environment":"'$env'", "commit_ids": ["'$commit'"] }' --cookie session.txt --cookie "XSRF-TOKEN=A_VALUE"  --header "Content-Type: application/json" --header "X-XSRF-TOKEN:A_VALUE" -X POST $studioserver/studio/api/1/services/api/1/publish/commits.json

Use of the script:

publish-code.sh [USERNAME] [PASSWORD] [AUTHOR_SERVER_AND_PORT]  [SITE_ID] [COMMIT_ID] 

USER_NAME is the Studio user (application account)
PASSWORD is the Studio user password (application account)
AUTHOR_SERVER_AND_PORT the protocol server name and port of Studio
SITE_ID the ID of the site
COMMIT_ID the squashed commit ID of the items coming from the release branch

Example:
publish-code.sh devops mydevopspw http://localhost myprojectID 378d0fc4c495b66de9820bd9af6387a1dcf636b8

The script is quite simple.  It authenticates to Crafter Studio and invokes a publish for the provided commit.  This op

Calling the Script in Jenkins

See configuration of sync script above.  The steps are exactly the same with the following differences:

  1. You will call the publish-code script instead of the codeforward-contentback script.
  2. You will ask the user for a parameter  value COMMIT_ID via the UI on each invocation and pass that to the command line as the COMMIT_ID parameter value

 

 

That’s it!  You can now publish your code releases via commits to your entire delivery infrastructure regardless of its size or distribution.

Conclusion

CMS platforms are notorious for refusing to play nice with CI/CD and agile development practices and process, automation and tools like Jenkins, Bamboo, Travis and others.  Databases and JCR repositories are one component of several fundamental, architectural limitations that make supporting CI/CD difficult for CMS platforms. Crafter is an open source, dynamic CMS with a unique Git based repository specifically designed to fit neatly in to your development practices and bring your authoring and development teams together in a way never before possible to improve and increase the rate and volume of innovation!

Integrating Crafter CMS with GitLab for Better DevOps

Content authoring and software development are both a major part of producing today’s digital experiences. Unfortunately, development support is not something traditional CMS platforms handle very well at scale. Crafter CMS, a 100% open source CMS platform that includes a Git-based repository designed to handle not only authoring but also DevOps seamlessly.

Many development teams use cloud hosted developer platforms like GitLab to assist with their development process.   Crafter’s Git based CMS supports developers working against remote repositories like GitLab, Github, Bitbucket, and others.

By supporting this kind of architecture, Crafter provides a very simple way to flow code forward from a developer and her team all the way up through the CI/CD process to production.  We also support a very simple way for any developer or any environment to easily update itself with the latest content from production.  DevOps and CMS have never been easy — until now. Crafter CMS’s CODE FORWARD, CONTENT BACK™ process makes this process simple and allows you to leverage awesome platforms like GitLab to support your team with the tools they know and love.

In this article, I’ll show you how to create a new project in GitLab and then start a new project in Crafter CMS in a way that connects to GitLab as an upstream remote repository so that GitLab can be used to support your development process with your CMS related development! 

Create a New Project and Connect it to GitLab

Step 1: Create a Project in GitLab

Figure 1: Create a project in GitLab 

  1. Select Blank Project to create a bare project
  2. Enter your project name
  3. Provide a project description
  4. Choose your security level
  5. Click create site

Once your repository is created you will see a screen similar to the one below.  You want to make note of the Git URL for the site.  You will need this URL in the next step.

Figure 2: New Project in GitLab 

Step 2: Create Your Project In Crafter Studio

Next, you want to log in to Crafter Studio as the admin user. The admin user has the rights to create new projects (called sites.) Click Create Site.

Figure 3: Create site via Crafter Studio

Clicking Create Site will present you with the Create Site dialog. This dialog changes depending on what you choose. Below is an example of the dialog filled out in a way that creates your project locally, set the Github repository as its upstream remote and pushes the initial project contents to the upstream repository.

Let’s walk through each part of the dialog:

Figure 4: Create Site Dialog in Crafter Studio, populating a bare upstream Git repository.

  1. The first thing you need to do is give your site an ID. The ID itself doesn’t matter in a sense. It doesn’t need to match anything per se, technically speaking the only requirement is that it’s unique. That said, it’s a best practice to provide an ID that is meaningful/recognizable to the team. If your website is called Sweet.com a good ID might be “sweetdotcom”
  2. Next, because you plan to connect this project to an upstream repository you want to click the plus (+) on “Link to upstream remote Git repository” This will open a number of new fields.
  3. In the “Remote Git Repository Name” field you want to provide a repository name that makes sense. It’s common to use “origin” or “upstream.”
  4. In the “Remote Git Repository URL” field you must provide the link to the Git repository discussed in Step #1: https://gitlab.com/russdanner/sweet-dotcom.git
  5. Provide your credentials in Git Remote Repository Username and Password
  6. Choose the option: “Create site based on blueprint then push to  remote bare repository.” This means that Crafter Studio will create a new site based on the blueprint you choose, link the remote repository as an upstream and then once the blueprint is installed in the local Repositories it will be pushed automatically to the upstream remote.
  7. Choose your blueprint. There are several out of the box blueprints provided by default. Choose one of these or one of your own. For our example, we’ll choose Editorial which is the simple Article style website/project template.
  8. Click Create. Crafter CMS will create the local repositories, Solr core and internal data structures required to support the project and install the blueprint. Once complete it will connect to the upstream and push the contents of the Sandbox repository to the remote.

Figure 5: Site is created and the contents of the sandbox are automatically pushed to the upstream repository.

Step 3: Check GitLab to Make Sure Your Site is There

Go back to your GitLab project and refresh the screen.  You will see the contents of your CMS project in the repository.

Your project is there!  Now you are ready to set up your entire development process and CI/CD automation.  To learn more about how this is configured check out these blogs:

Creating a Project in Crafter CMS Based on an Existing GitLab Project

Let’s consider for a moment that you’re a new developer joining the team. The topology above is already set up and you just want to get a local environment up and going. Simple. Follow these instructions.

  1. Install Crafter Studio locally (Source build or Binaries bundle)
  2. Login as Admin
  3. Click Create Site
  4. Fill out the Create Site Form as in a similar fashion described in Step 2, except this time you chose the option to create your site based on an existing upstream repository. This can be your team’s branch or your own fork. The exact workflow is up to you.

Conclusion

Platforms like GitLab that support agile development and CI/CD are helping bring best practices to the enterprise with easy to use tools that make implementing these activities simple.

Crafter CMS’s Git-based repository and DevOps integration make it simple to build CMS and content related projects while adhering to DevOps best practices and leveraging today’s best development platforms.

“Code Forward, Content Back” is a trademark of Crafter Software Corporation

Using Crafter CMS. Github and Two-Factor Authentication

Crafter’s Git based CMS supports developers working against remote repositories like Github, Gitlab, Bitbucket, and others. Many organizations that use Github enforce a two-factor authentication for developers.  This article shows you how to create a site in Crafter when you have two-factor authentication in Github configured.

Step 1: Configure an Access Token in Github

If you are reading this article, it’s very likely you already have two-factor authentication configured and are using it with Github.  If you’re interested in setting it up you can learn more about that here:
https://help.github.com/articles/securing-your-account-with-two-factor-authentication-2fa/ 

The first step in getting Crafter Studio to work with Github when two-factor authentication is enabled is to create a personal access token.  Follow the instructions shown here to create and acquire your token:   https://help.github.com/articles/creating-a-personal-access-token-for-the-command-line/

Step 2: Create a Site based on a Remote Repository

  1. If Crafter CMS is not installed: Install it locally (Source build or Binaries bundle)
  2. Login as Admin user

Next, you want to log in to Crafter Studio as the admin user. The admin user has the rights to create new projects (called sites.) Click Create Site.

Figure 1: Create site via Crafter Studio

Clicking Create Site will present you with the Create Site dialog. This dialog changes depending on what you choose. Below is an example of the dialog filled out in a way that creates your project locally based on an upstream repository that becomes it’s remote.

Let’s walk through each part of the dialog:

Figure 2: Set up a project based on existing remote Git repository via Crafter Studio

  1. The first thing you need to do is give your site an ID. The ID itself doesn’t matter in a sense. It doesn’t need to match anything per se, technically speaking the only requirement is that it’s unique. That said, it’s a best practice to provide an ID that is meaningful/recognizable to the team. If your website is called FreshFlowers.com a good ID might be “freshflowerscom”
  2. Next, because you plan to connect this project to an upstream repository you want to click the plus (+) on “Link to upstream remote Git repository” This will open a number of new fields.
  3. In the “Remote Git Repository Name” field you want to provide a repository name that makes sense. It’s common to use “origin” or “upstream.”
  4. In the “Remote Git Repository URL” field you must provide the link to the Git repository discussed in Step #1: https://github.com/russdanner/devworkflowexample.git

  5. Provide your credentials in Git Remote Repository Username and Password
    USE THE PERSONAL ACCESS TOKEN
  6. Choose the option: “Create site based on remote git repository.” This means that Crafter Studio will create a new site by cloning the upstream repository locally and setting the upstream repository as a remote.
  7. Click Create. Crafter CMS will create the local repositories, Solr core and internal data structures required to support the project and pull in the project from the remote.

 

Using War Overlays with Crafter Engine

Crafter Engine, the delivery component of Crafter CMS is completely programmable with scripted Groovy.  You never have to write a lick of Java if you don’t want to.  Even dependencies can be managed with Ivy and Grapes.

That said, from time to time:

  •  you may find that you want to build classes in Java directly
  • or you may need to include dependencies in a deployment where Ivy and Grapes are not an option
  • or you may need to modify the Web.xml of the engine WAR file for some reason.

These scenarios are an exception but they do come up. For these scenarios, you want to create a Maven WAR Overlay.  Overlays allow you to add and override contents of Crafter CMS component WARs like Crafter Studio, Engine, Profile, and Social.

An overlay is a very simple maven project that downloads a specific version of Crafter Engine (specified in the POM file), downloads the additional dependencies you require, builds your source code that’s specific to your project, packages it to a jar and then combines all of these into a new WAR file.

How:

Let’s create an example where we simply want to overlay a dependency into the jar, for example, the Amazon AWS SDK

Step 1: Create a project structure

Create a directory structure as follows

+--my-project (project root directory)
   |
   +--src
       |
       +--main
            |
            +--java (your class structure starts here)
            | 
            +--webapp (any files you want to override or include in the webapp like web.xml)

Step 2: Create your Maven POM file

In a file at my-project/pom.xml put the following contents:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <groupId>com.mysite</groupId>
 <artifactId>craftercms-engine-overlay</artifactId>
 <version>1.0.0-SNAPSHOT</version>
 <packaging>war</packaging>
 <name>craftercms-engine-overlay</name>
 <description>craftercms-engine-overlay</description>

 <properties>
 </properties>

 <dependencies> 
 <dependency>
 <groupId>org.craftercms</groupId>
 <artifactId>crafter-engine</artifactId>
 <version>3.0.8</version>
 <type>war</type>
 </dependency>

 <!-- ADD YOUR DEPS HERE -->
 <dependency>
 <groupId>com.amazonaws</groupId>
 <artifactId>aws-java-sdk</artifactId>
 <version>1.11.289</version>
 </dependency>
 </dependencies>

 <build>
 <finalName>ROOT</finalName>

 <plugins>
 <plugin>
 <!--<groupId>org.apache.maven.plugins</groupId>-->
 <artifactId>maven-compiler-plugin</artifactId>
 <version>3.3</version>
 <configuration>
 <source>1.8</source>
 <target>1.8</target>
 </configuration>
 </plugin>
 
 <plugin>
 <artifactId>maven-war-plugin</artifactId>
 <version>2.1.1</version>
 <configuration>
 <workDirectory>target/overlay-war-folder</workDirectory>
 <overlays>
 <overlay>
 <groupId>org.craftercms</groupId>
 <artifactId>crafter-engine</artifactId>
 </overlay>
 </overlays>
 </configuration>
 </plugin>
 </plugins>
 </build> 
</project>

Note that the above POM file is very simple.  It simply states that you want to download Crafter Engine 3.0.8, Download Amazon’s 1.11.x SDK and then recombine these into a new Engine WAR file called ROOT.war in the output directory target folder.

Step 3: Run the Build

Type the following command in your project directory: mvn clean package

Similar output to the following is expected:

mvn clean package
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building craftercms-engine-overlay 2.2.8-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ craftercms-engine-overlay ---
[INFO] Deleting /Users/rdanner/code/test-war-overlay/target
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ craftercms-engine-overlay ---
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory /Users/rdanner/code/test-war-overlay/src/main/resources
[INFO]
[INFO] --- maven-compiler-plugin:3.3:compile (default-compile) @ craftercms-engine-overlay ---
[INFO] No sources to compile
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ craftercms-engine-overlay ---
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory /Users/rdanner/code/test-war-overlay/src/test/resources
[INFO]
[INFO] --- maven-compiler-plugin:3.3:testCompile (default-testCompile) @ craftercms-engine-overlay ---
[INFO] No sources to compile
[INFO]
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ craftercms-engine-overlay ---
[INFO] No tests to run.
[INFO]
[INFO] --- maven-war-plugin:2.1.1:war (default-war) @ craftercms-engine-overlay ---
[INFO] Packaging webapp
[INFO] Assembling webapp [craftercms-engine-overlay] in [/Users/rdanner/code/test-war-overlay/target/ROOT]
[INFO] Processing war project
[INFO] Processing overlay [ id org.craftercms:crafter-engine]
[INFO] Webapp assembled in [780 msecs]
[INFO] Building war: /Users/rdanner/code/test-war-overlay/target/ROOT.war
[INFO] WEB-INF/web.xml already added, skipping
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 3.658 s
[INFO] Finished at: 2018-03-07T21:11:09-05:00
[INFO] Final Memory: 14M/309M
[INFO] ------------------------------------------------------------------------

 Step 4: Deploy Your New WAR

In the project folder, you will now see a target folder with a ROOT.war in it.  This is your new WAR file.  You can now place this in the webapps folder of your Crafter CMS authoring or delivery server.

 

Content Management Meets DevOps (Part 2 of 2) How a Git-based CMS Supports Continuous Integration and Delivery

As we learned in Part 1 of this series: Content Authoring and Publishing; development and content authoring are both a major part of producing today’s digital experiences. Unfortunately, development support is not something traditional CMS platforms handle very well at scale. Crafter CMS, a 100% open source project not only supports authors but DevOps as well.

In this article, we’re going to expand on the authoring workflow and publishing mechanics we looked at in the last article and explain how Crafter CMS seamlessly supports DevOps tools and process.

Development Requires Environments

The CMS where authors work is typically considered a production system. That’s not to say that the edits they make are immediately live. Typically CMS platforms support a concept of a “draft” type workflow with the ability to publish approved content and make it “Live”.

Crafter CMS is no exception here. As we described in our last article in this series, Authors work in a decoupled authoring environment and content is published from authoring to delivery on approval.

In the authoring environment, content can be edited and previewed via our web-based authoring tool called Crafter Studio. Edits are saved in a Git-based repository called “Sandbox”. On approval, edits are moved to a repository called “Published.” Crafter Studio handles all of the mechanics of making editing and publishing safe and simple for authors. Authors simply click edit and make changes, perform reviews and publish work via the UI. In the background, Crafter Studio will lock content, perform commits and take any other actions necessary to perform the low-level repository tasks necessary.

The authoring environment is akin to a work and test area for the authors. Relative to the live site or app the content authors are deploying content to, the Crafter Studio (and the Sandbox repository) where they edit, preview and approve content is what we would call a lower environment. Work is promoted from the lower environment (authoring) to the live environment (delivery.)
Developers almost always work in lower environments. No real developer modifies the code in production. Experience shows that making changes in production leads to outages and hinders future upgrades. Interestingly, many headless CMS platforms making their way to the market today require developers managing content types to work directly in production! While the scope of development in these systems is limited, the end results are the same.

In Crafter CMS, because we decouple authoring from delivery, it is possible for developers to work directly with the production system via authoring. Changes can be made and tested in the authoring environment before being pushed live.

Figure 1: Production environment.  Showing DevOps as part of the production workflow.  DevOps do not want to touch production directly and should not have to.  Unfortunately, most CMS platforms force them to do so.

That said, developers do not want to work with CMS tools! They want to work with their own Integrated Development environments (IDE) and other tools. They want to work locally on their own machines where they have control and can debug. They want the ability to collaborate with their teammates on feature branches. They want to be able to work in parallel with other development teams without fear of stepping on each other or interfering with content authoring activities and they want to be able to easily move their work through the various environments of their certification and testing process out to production. Developer environments and process are complex.

To illustrated this I have included a diagram below of a typical developer process and set of environments which must be followed in order to get new functionality to production.

Figure 2: Typical DevOps workflow.  Today’s modern app development DevOps workflows include parallel development efforts on the same project and extend from the developer’s local environment and team sandbox all the way to production.

Traditional CMS Systems and Environments, Code Artifacts and Process Don’t Mix Well

It is difficult at best to support this kind of process with traditional CMS architecture. Server-side code is typically managed in a source code repository while CMS related code artifacts like templates, Javascript and CSS (that should be managed in a source code management) want to live in the CMS. Server-side code typically requires heavy packing and deployment systems like JARs, WARs and OSGi bundles. It takes a lot of effort on the part of the developer to get an environment setup locally so that they can develop and it’s equally difficult to get a specific set of code into one of the often many environments. Worse, content is always stored in a JCR repository or SQL database and it’s a huge burden to get the latest production content to a lower testing environment. The whole process of “code forward, content back” with traditional CMS is a nightmare for DevOps. Still worse, in some environments, going to production means interruptions in content authoring ability for content authors while their environment is updated with the latest code. These outages can last hours to days or in some cases even longer.

These conditions are unacceptable.  This is no way to support innovation at a time when the amount and speed of innovation an organization can sustain is a major key to competitive advantage.

Crafter CMS Provides the Solution

Crafter’s Git-based dynamic CMS tackles all of these challenges head-on with a set of technologies that incorporate lightweight development, integration with developer tools and process and elastic scalability that provides the ability to serve any front-end technology via API or markup with fully dynamic content.

First: Crafter CMS supports a fully featured, Spring-enabled, Groovy-based scripting layer. This is a subject for a whole blog of its own — but without getting too in-depth, it’s huge. You can create classes on your own in Groovy. You can leverage classes in the classpath. You can create your own beans based on Groovy or Java classes, you can inject existing beans and services. It’s a rich, robust powerful environment full of services for you to build on at the speed of scripting in the same languages and frameworks that you are used to.
Second: Crafter CMS sits on top of Git. Git is traditionally speaking, a source code version control system. That means that all of your code can live in the same version control system as the business content, together. It’s versioned together and it can be packaged and deployed together. Crafter CMS makes the world of CMS simple for content authors and developer native for DevOps.
Third: Because Crafter is Git-based you can natively support your ideal DevOps process for Continuous Integration and Delivery (CI/CD).

 

Let’s jump in and take a look at how it works.
Below is what you might think of as the archetype of a developer workflow that’s integrated with the production authoring environment. In this diagram, you will find a mechanism for both a “code forward” activity in which code can be moved through a development process through to production as well as a “content back” activity in which production content, including in-process content, can be brought back to lower development environments! including local development machines.

Figure 3: Archetypal DevOps workflow that describes in general how content flows back to the development process and code flows forward through the certification process to production.

The above diagram has a lot going on. Let’s break it down and explain things a step at a time.

Step 1: Create an Upstream Repository

In order to facilitate a developer workflow, you want to establish an upstream repository for your Sandbox in your production authoring environment. Any Git repository will work. It’s typical to use a Git repository that has a UI/Workflow atop of it such as Github, Bitbucket, Gitlab and other similar systems. The upstream repository is the root of the developer workflow.

Figure 4: A Git repository with support for “developer/team workflow” such as Github, GitLab or Bitbucket is configured as a remote upstream repository of the Production Authoring Sandbox repository.  This is the primary point of contact between the authoring process and the development and code release process come together.  

Step 2: Use Automation to Sync Sandbox with the Upstream

Note that the repository is what the Git community refers to as an “upstream” remote repository. That means in a sense the Production Sandbox becomes subordinate to it from a Git log perspective. This upstream repository is where content and development work will be merged before making its way to the production Sandbox and ultimately to the Published repository and the delivery nodes themselves. Also, note that nothing changes about the publishing and deployment configuration and topology of the Production environment.

You will want to keep the upstream repository up to date with authoring. The best way to accomplish this is to use a DevOps automation platform such as Jenkins or Bamboo to orchestrate a push to the upstream on a schedule. Keeping the upstream repository up to date with the authoring Sandbox repository provides downstream development and testing repositories with the latest content and helps to avoid conflicts when it’s time to promote from the upstream repository to the authoring Sandbox repository.

Figure 5: Content flows from Production Authoring Sandbox to the Developer repository via automated Git Push

Step 3: Use the Upstream Repository to Support Development and Testing Environments and Workflow

From this upstream repository, you will feed all lower environments and branch for each of your development efforts. From the upstream repository, you can support any development process and supply content to any development or testing environment. Lower environments may consist of Authoring and Delivery, or just Authoring, or just Delivery. It depends on the needs. For example, Development often contains both Authoring and Delivery, while QA tends to focus only on Delivery. Simple “Git pull” mechanics are used to move code and content from the upstream repository, typically from a branch.

Figure 6: Development branches and forks can be created to meet your specific workflow needs.  Lower environments use these repositories and branches as their upstream.

Step 4: Merge Code Updates Into the Upstream Master and Pull them to the Production Authoring Sandbox Repository

When you are ready to move code from a development branch to the authoring Sandbox you will first merge the work into the master of the upstream repository. You can do merge all of your commits or you can merge them into a single commit by using the Git rebase command. By Squashing all of the commits into a single commit you make it easier to move the workaround as a single unit. Merges are typically done via pull requests on repositories that support development workflow.
Once the merge operation is complete in the upstream repository your automation will carry that work to the production authoring Sandbox.

Figure 7:  Use “Pull Requests” and other Git workflow mechanics to promote code through the process.  When it’s ready to go live merge it to the “Master” of the Developer Repository.  At this point, it will flow via automation to the Production Authoring Sandbox.

Step 5: Use Crafter Studio’s Publish Commits API to Publish Code to Delivery

Once your development work is in the Production Sandbox you will want to publish it. To do this Crafter Studio provides a REST API that will trigger the publishing on one or more commits. Simply call Crafter Studio’s Publish Commits REST API (/api/1/services/api/1/publish/commits.json) via the DevOps automation platform passing the required parameters including the commit IDs to be published and Crafter Studio will move the work to the Published repository from which it will be replicated to your delivery nodes.

Figure 8: Move code from Sandbox to Published with a simple API call. 

Step 5: Build Tons of Amazing Things

Now that you have the basic mechanics of Crafter’s native Git-based distributed repository and development workflow you are ready to support any amount of parallel development you want with the kind of tools and process rigor you are used to. Because Crafter’s Git-based repository is distributed, authors and developers, even developers working locally are all working out of what is essentially the same repository.

The workflow enables the team to collaborate and work simultaneously without ever interrupting or stepping on each other’s toes. It’s time to start innovating!

How do I set up this workflow?

For the purpose of simplicity, we’ll assume you’ve got Crafter Studio up and running and you are about to create a new project.

Step 1: Create your upstream

Create an empty repository in your upstream (GitHub, Bitbucket etc.) The specific steps depend on the repository you are using. The key here is that you want to create an empty or what’s sometimes called a “bare” repository.

Figure 9: Create a bare repository in your developer Git. In this example, we’re using Github.

On Github, once created you will see the following screen. Here you will note the repository URL (https://github.com/russdanner/devworkflowexample.git) which you will need for the next step. Also, if you’re trying to create an upstream for an existing project (out of scope for this blog), you’ll find the instructions below in the “push an existing repository from the command line” section.

Figure 10: Bare repository created.  

Step 2: Create Your Project In Crafter Studio

Next, you want to log in to Crafter Studio as the admin user. The admin user has the rights to create new projects (called sites.) Click Create Site.

Figure 11: Create site via Crafter Studio

Clicking Create Site will present you with the Create Site dialog. This dialog changes depending on what you choose. Below is an example of the dialog filled out in a way that creates your project locally, set the Github repository as its upstream remote and pushes the initial project contents to the upstream repository.

Let’s walk through each part of the dialog:

Figure 12: Create Site Dialog in Crafter Studio, populating a bare upstream Git repository.

  1. The first thing you need to do is give your site an ID. The ID itself doesn’t matter in a sense. It doesn’t need to match anything per se, technically speaking the only requirement is that it’s unique. That said, it’s a best practice to provide an ID that is meaningful/recognizable to the team. If your website is called FreshFlowers.com a good ID might be “freshflowerscom”
  2. Next, because you plan to connect this project to an upstream repository you want to click the plus (+) on “Link to upstream remote Git repository” This will open a number of new fields.
  3. In the “Remote Git Repository Name” field you want to provide a repository name that makes sense. It’s common to use “origin” or “upstream.”
  4. In the “Remote Git Repository URL” field you must provide the link to the Git repository discussed in Step #1: https://github.com/russdanner/devworkflowexample.git
  5. Provide your credentials in Git Remote Repository Username and Password
  6. Choose the option: “Create site based on blueprint push to a remote bare repository.” This means that Crafter Studio will create a new site based on the blueprint you choose, link the remote repository as an upstream and then once the blueprint is installed in the local Repositories it will be pushed automatically to the upstream remote.
  7. Choose your blueprint. There are several out of the box blueprints provided by default. Choose one of these or one of your own. For our example, we’ll choose Empty which is the “Hello World” of blueprints.
  8. Click Create. Crafter CMS will create the local repositories, Solr core and internal data structures required to support the project and install the blueprint. Once complete it will connect to the upstream and push the contents of the Sandbox repository to the remote.

Figure 13: Site is created and the contents of the sandbox are automatically pushed to the upstream repository.

Step 3: Set up Your Delivery Nodes

Now that your project is created you can set up the rest of your production environment by initializing your delivery nodes to receive deployments from authoring. Remember these delivery nodes will pull from Crafter Studio’s repositories, not the upstream remote repository.

When you add a new delivery node a simple command line script is run on that node that configures it to replicate and process content from the “Published” repository from authoring.

  • Instructions for creating a site can be found here.
  • Instructions for initializing a delivery node can be found here.

Step 4: Set up your Developer Workflow and Lower Environments

Now that your upstream repository is initialized in GitHub you can set up any developer workflow you want. It’s typical to consider Master to be in-sync with the Production Authoring Sandbox. Given that, you don’t want to work in Master. Create branches to isolate development work from work that’s ready to move to Production Authoring. Below is an example topology that shows multiple environments and developer workflow that include feature branches, developer forms, and local developer clones.

Figure 14: Full DevOps “Code Forward, Content Back” workflow for CI/CD with Crafter CMS leveraging Git mechanics and DevOps automation.

I Am a Developer, I Want to Work Locally Against The Upstream

Let’s consider for a moment that your a new developer joining the team. The topology above is already set up and you just want to get a local environment up and going. Simple. Follow these instructions.

  1. Install Crafter Studio locally (Source build or Binaries bundle)
  2. Login as Admin
  3. Click Create Site
  4. Fill out the Create Site Form as in a similar fashion described in Step 2, except this time you chose the option to create your site based on an existing upstream repository. This can be your team’s branch or your own fork. The exact workflow is up to you.

Figure 15: Set up a project based on existing remote Git repository via Crafter Studio

Conclusion

Today’s digital marketplace is constantly evolving. Companies are always iterating on existing functionality with improvements and deeper integration or introducing new functionality and channels for their employees, partners, and customers. Crafter CMS provides the right technology and integrates seamlessly with your DevOps processes to enable you to achieve a high, sustainable continuous rate of constant, iterative development, integration and delivery (CI/CD.)

Digital experience teams finally have a toolset that allows authors to work continuously without being interrupted by developers.

Developers have a means for easily moving code forward through environments and pulling content back from production to lower environments.

Further, with Crafter’s distributed repository development shops can run as much parallel development as they want and developers are able to leverage the workflow and local tools they are accustomed to.

“Code Forward, Content Back” is a trademark of Crafter Software Corporation

Content Management Meets DevOps (Part 1 of 2) How a Git-based CMS Improves Content Authoring and Publishing

Traditional CMS platforms based on SQL and JCR repositories have begun to show major signs of weakness in keeping up with today’s demands for a high rate of innovation and rapid scalable deployment on modern elastic architectures. This is nowhere more evident than the move towards headless CMS. Many CMS platforms today push headless, or what some call Content as a Service (CaaS), as the one-stop-shop solution to the struggles most CMS platforms have in providing support for scalability, multi-channel, and development integration. It’s not. Headless capability is important but it has its own limitations.

Crafter CMS, an open source Git-based dynamic CMS tackles all of these challenges head-on with a set of technologies and that incorporate lightweight development, integration with developer tools and process, and elastic scalability for content delivery that provides the ability to serve any front-end technology via API or markup with fully dynamic content.

In this two-part series, we’ll explain the basic mechanics that support content authoring, publishing and developer workflow and demonstrate how these mechanics combined with Crafter’s architecture and developer stack set a new standard for what a CMS can provide in today’s competitive digital marketplace.

Content Management and Deployment Mechanics

In this section we’ll explore the mechanics of how (non-technical) content authors work with the CMS and how their changes, once reviewed and approved, are deployed from their authoring tools to a live content delivery system.

Crafter CMS is decoupled, composed of several microservices where content authoring and content delivery services are separated into their own distinct, subsystems. This model has many advantages related to security, scalability and delivery flexibility. In a decoupled architecture, content is published from authoring to delivery as shown in the diagram below. The delivery system may be any number of independent digital channels – enterprise website, mobile app, social, augmented reality, digital kiosk or signage, e-commerce front end, microsite, etc.

Crafter CMS supports authoring via Crafter Studio that sits on top of a headless Git-based repository and publishing system. Content authors don’t need to know anything about Git. They simply work with Crafter Studio, a web-based application. Crafter Studio provides beautiful content entry forms, in-context editing with multi-channel preview, drag-and-drop layout, component placement, image cropping, and more. While content authors are performing their work, Crafter is managing all of the Git mechanics, managing locking, creating a time-machine like, Git-based version history and audit trail for them behind the scenes, all accessible to them via the Studio UI.

 

Figure 1: Crafter CMS microservices applied to decoupled architecture

Crafter’s publish mechanism deploys content from the Authoring system to the Delivery system. Content logically flows from the authoring environment to the delivery environment. The mechanism for this, given the underlying Git repo, is a “pull” type interaction. Meaning the actual network conversation is initiated from the delivery infrastructure to the authoring infrastructure, as shown in Figure 2.

Each delivery node has a Deployer agent that coordinates deployment activities on the node for each site that is being delivered on that node.

  • Delivery nodes can initiate deployment pulls either on a scheduled interval (a “duty cycle”), on-demand via an API call, or both.
  • The Deployer performs a number of activities beyond receiving and updating content on the delivery node. A list of post-commit processors is run. These can be used to execute updates on search indexes, clear caches and perform other such operations.
  • The Delivery node maintains a clone of the Authoring Git-based repository.
  • The Crafter Deployer takes care of managing the synchronization of the delivery node’s clone authoring repository from the authoring environment.
  • Git-mechanics ensure content sync is 100% accurate.

Figure 2: Crafter’s Dynamic CMS Publishing via Git

Technically speaking, Authoring does not require knowledge of the Delivery nodes. This makes the architecture more elastic, globally scalable and even enables Crafter to support disconnected and intermittent content delivery.

  • Elastically add new nodes or revive dormant nodes and they will sync to the latest without any additional wiring.
  • Create region-based depots to avoid transferring data more than once over long distances for global deployments.
  • Airplanes, cruise ships, drilling/mining locations and other remote disconnected deployments can operate with their latest pull of content, and sync up with Authoring when connectivity is available.

Figure 3: Elastic Delivery

In Crafter CMS, only approved content is published to the delivery environment. Crafter manages this by using 2 repositories for each project. One called a “Sandbox” which contains work-in-progress and the other called “Published” which represents approved, published work and complete content history.

  • Authors use the Crafter Studio UI to review and approve content via workflow.
  • Crafter Studio takes care of moving approved work between Sandbox and Published repositories.
  • Delivery nodes monitor the published repository for updates.


Figure 4: Authors work in Sandbox. Delivery nodes pull from Published.

Benefits

Crafter’s Git-based publishing model provides your authoring team with a highly reliable, highly accurate publishing mechanism that is elastically scalable, globally distributable and supports multi-channel.  Crafter CMS’s architecture enables your team to reliably deliver your dynamic content on any channel, wherever and whenever it is needed.

Further, As we’ll see in in Part 2, this architecture enables content authors to work side-by-side with DevOps, while they continually introduce new features and functionality without any disruption to the authors.

How do I set up this workflow?

The underlying Git repositories and related workflow for Authoring require no setup at all. When you create a project in Crafter Studio it automatically creates the local “Sandbox” and “Published” repositories. When you add a new “Delivery” node a simple command line script is run on that node that configures the node’s deployer to replicate and process content from the “Published” repository from authoring.

  • Instructions for creating a site via Crafter Studio can be found here.
  • Instructions for initializing a delivery node can be found here.

Conclusion

Content authors are non-technical users who need powerful but easy-to-use tools to help create, maintain and manage their digital experiences. Crafter Studio provides these users with a web-based application that makes it easy for content authors to achieve their goals. Under the hood, Crafter Studio leverages a powerful Git-based repository and deployment engine that provides authors with next-generation versioning and auditing mechanics as well as robust, elastic and distributed deployment.

Today’s digital marketplace is constantly evolving. Companies are always iterating on existing functionality with improvements and deeper integration or introducing new functionality and channels for their audiences. For today’s most innovative and competitive organizations, ongoing development and the move to DevOps is a fact of life. The companies that have the greatest success are those that have the right technology and processes through which they are able to achieve a high, sustainable continuous rate of constant, iterative development, integration and delivery, i.e., Continuous Integration and Delivery (CI/CD).

In the second half of this blog series, we will take a deep dive into how Crafter CMS seamlessly integrates with your CI/CD processes to enable your entire team of developers and content authors to innovate collaboratively without interfering with each other’s workstream.