Querying Content in Crafter CMS

Types of Content Queries

Crafter CMS supports 3 specific types of content queries:

  • Cross content Lucene/Solr queries. This enables you to query any/all content objects, by any group of properties.)
  • Filtered Structural Queries. This enables you to query against the repository structure e.g. “Get all articles by author XYZ”
  • Content Item specific query. This enables you to write queries inside of a given content item.

Type 1: Make a Lucene/Solr Query

The following code examples use the Crafter Search Service in Crafter Egnine to get content. You can find the interface for this service HERE.

def queryStatement = 'content-type:"/component/article" AND author:"Russ Danner"'

def query = searchService.createQuery()
query = query.setQuery(queryStatement)

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

return items

Type 2: Make a Query for Content Based on Structure

The following code examples use the Site Item Service in Crafter Egnine to get content. You can find the interface for this service HERE.

def topNavItems = [:]
def siteDir = siteItemService.getSiteTree("/site/website", 2)

if(siteDir) {
    def dirs = siteDir.childItems
    dirs.each { dir ->
            def dirName = dir.getStoreName()
            def dirItem = siteItemService.getSiteItem("/site/website/${dirName}/index.xml")
            if (dirItem != null) {
                def dirDisplayName = dirItem.queryValue('internal-name')
                   topNavItems.put(dirName, dirDisplayName)
            }
   }
}

return topNavItems

Make a Query for Content Based on Structure with Filter

The following code examples use the Site Item Service in Crafter Engine to get content. In the example we build on the Site Item Service of getting objects under a specific tree in the repository by supplying a filter that will be applied to each object first to determine if it should be part of the result. Filters can make their determination based on the path or the content or even “outside” influence.

  • You can find the interface for this service HERE.
  • Note in the example below we define our own filter based on the ItemFilter interface found HERE.
  • However, you may use out of the box filters as well if they meet your needs. These are found HERE.
  • Finally be aware that for simple filename patterns, methods for this already exist in the Site Item Service and no filter is required (but they make for an simple to understand example.)
import org.craftercms.core.service.ItemFilter
import org.craftercms.core.service.Item
import java.util.List


def result = [:]
def navItems = [:]
def siteDir = siteItemService.getSiteTree("/site/website", 2, new StartsWithAItemFilter(), null)

if(siteDir) {
    def dirs = siteDir.childItems
    dirs.each { dir ->
            def dirName = dir.getStoreName()
            def dirItem = siteItemService.getSiteItem("/site/website/${dirName}/index.xml")
            if (dirItem != null) {
                def dirDisplayName = dirItem.queryValue('internal-name')
                   navItems.put(dirName, dirDisplayName)
            }
   }
}
result.navItems = navItems

return result


/**
 * Define a filter that returns only items that have a name that starts with "A" or "a"
 */
class StartsWithAItemFilter implements ItemFilter {

    public boolean runBeforeProcessing() {
        return true
    }

    public boolean runAfterProcessing() {
        return false
    }

    public boolean accepts(Item item, List acceptedItems, List rejectedItems, boolean runBeforeProcessing) {

      if (item.getName().toLowerCase().startsWith("a")) {
          return true
      }

      return false
    }
 }

Type 3: Make a Query Against Fields in a Content Object

The following code examples use the Site Item Service in Crafter Engine to get content. You can find the interface for this service HERE.

def result = [:]
def segment = "a segment value" // could come from profile, query param etc

// load a specific content object
def itemDom = siteItemService.getSiteItem("/site/components/sliders/default.xml")

// query specific values from the object
result.header = itemDom.queryValue("/component/targetedSlide//segment[contains(.,'" +  segment + "')]../label")
result.image = itemDom.queryValue("/component/targetedSlide//segment[contains(.,'" +  segment + "')]/../image")

return result

Building and Optimizing Multi-Channel Digital Experiences

Over the last few years, the internet has undergone a tremendous amount of fundamental change in its landscape, and we are now entering into a new reality with today’s Web. This change is driven by five major trends:

Social – The Web is much more social and much less anonymous than ever before. As an example, many sites and applications allow users to authenticate using shared / common identities provided by Facebook and Google.

Personal – While the internet is continuously expanding in terms of ubiquity, at the same time, it’s becoming much more local and much more personal in terms of user experience.

Mobile – the growth of mobile access to the internet is rapidly expanding. Access from tablets and phones has long since exceeded that from desktops and laptops.

Internet of Things (IoT) – The internet is no longer just websites and applications. Consumer devices of all kinds from beacons and thermostats to digital assistants are now connected.

Digital Natives – We now live in a time where our children have had access to to extremely powerful computing and connectivity their entire lives.  As they become decision makers we must realize that their experience and hence their expectations are vastly different than our own.

Each of these trends is a significant development in user experience in their own right. However, these trends feed and reinforce one another in a way that’s accelerating change and adoption across all trends.

The very way we communicate with and understand our customers is changing, and when foundational change like this occurs, those who recognize the change and move quickly to adapt have the most to benefit. Adapting to these important changes should be on your near-term road map.

Let’s take a look at each of these trends in more detail to get a deeper sense of reasoning and urgency for change.

Social

Social Media is ubiquitous now, with Facebook reporting over 1.8 billion active users, Snapchat at 100 million users and Twitter users estimated to exceed 315 million. With these numbers – combined with the fact that studies show that while only 14% of consumers trust traditional advertising, 78% trust peer recommendations. Social communication is personal, emotional, timely, relevant and propagated amongst peers – it’s easy to see why social is so important.

Personal

We all know that over the last twenty five years the Web has made the world a much smaller place by knitting our global communities together through an increasingly ubiquitous network. This trend continues today, but on a whole other level. The internet is increasingly being used to deliver the activity, news, reviews, sales and other relevant data and services that are occurring and are available to us right in our immediate vicinity. All this information is being delivered right to us in real time through our mobile devices. While the world may be getting smaller, our personalized experience is growing larger.

Mobile

There are 7.4 billion people in the world, of which, 6 billion of us own an internet-enabled mobile device of some kind. In-short, almost everyone in the world is connected with at least a basic mobile device. Additionally, 1 third of the world’s connected users have at least 1 or more smartphone or tablet capable of delivering extremely rich digital experiences.  Competitive organizations Uber, Lyft and many others are leveraging this connectivity to change the way business is done.

Internet of Things (IoT)

The Internet is no longer about websites and apps accessed by computers and mobile devices. Our cars, the stores we shop in, the devices in our homes and all kinds of devices throughout industry are constantly connected and communicating with other devices and systems via the internet.  We call this new reality the Internet of Things (IoT.) Even at this “early” stage in 2017, there are some 20 billion IoT devices connected. IoT is almost certainly the “next” mega-trend for the internet. Pages and apps are rivaled in volume by APIs. Human users now share the web with “Robots”.  The “Next mega-trend” is in fact already upon us. IoT opens a universe of new capabilities and user experiences as well as new challenges.

Digital Natives

Anyone who has a “tween” or teenager today knows that we’re already living a new evolution of the population. From birth, our children have grown up with an extreme level of connectivity and computing power. “Computing” is unbelievably fast, highly visual and tactile. Connectivity is ubiquitous. The applications they’ve grown up with are highly interactive, social and personalized. They don’t know anything different. A new kind of user is born. Businesses that don’t adapt quickly as this group comes of age as the next wave of consumers and employees will lose big to the companies that that do.

Meeting the Demands of the Era of Engagement

Each of these trends reinforces the others, and fuels further adoption and drives innovation. It is these technologies – and the behaviors and capabilities they foster – that have brought us to a new era, which Forrester calls the “era of engagement”. This is a new reality where the distinction between on-line and offline is becoming ever more blurred and the experience ever more immersive.

Driving these trends are people – our friends, leads, customers, critics, and fans. This is our audience and the other half of the conversation. And it’s no surprise that in today’s reality – that is, in the age of engagement – they want to participate and expect us to engage them on their terms – on their schedule, in the context of their location, in their language, and optimized for their device.

Your audience has also become accustomed to a personal experience, and they expect a personalized, coherent and consistent customer experience regardless of whether they are in your brick and mortar store, on your Facebook page, or on your website. To effectively tackle this challenge of serving a mass audience with limited resources, enterprises require strategy and effective tools to help get the job done.

Does Traditional Web Content Management Get Us Where We Need to Go?

Traditional Web Content Management (WCM) solutions are focused on building websites, landing pages and blogs.  As we’ve seen, today’s challenges go well beyond these demands. Web Experience Management (WEM) provides us with the toolset to take on this otherwise daunting challenge. The capabilities of WEM allow you to create, manage, and deliver dynamic, targeted and consistent content across various online channels including your website, social media, marketing campaign sites, mobile applications, and more.

In short, it takes a lot more than a traditional Web CMS or Web Content Management (WCM) can provide to meet these needs.

Key Principles of Experience Management

Before we get too technical let’s take a step back and ask what kind of guiding principles can adopt that will help us meet the challenges of the “Era of Engagement.”

  1. Great experiences are designed, built and delivered by a multidisciplinary teams.
  2. New data and channels can spring up at any time.
  3. Time to market is king and the platform that enables the first mover is the king maker. Agile approaches and shorter delivery cycles are extremely important!
  4. Great experiences are relevant and relevancy drives value.
  5. Technical architecture matters and ultimately defines the limits of what is possible.
  6. Simplicity is paramount. True simplicity comes from the separation of concerns and good architecture rather than specific technologies, vendors and shrinkwrap.
  7. Today’s experiences exist anywhere and everywhere.
  8. Experience is a journey rather than an interaction. Customers and users expect each interaction to leverage previous interactions.
  9. “One size fits all” is a fallacy. Each organization has its own unique needs, existing skill sets, and back ends.
  10. Openness is key to innovation at scale.

Translating Principles to Technology

Based on the principles above we start to get a clearer picture of the kind of technical architecture we need:

  1. A platform that is content first.  Content must be cleanly separated from code and presentation so that it can be reused and consumed across multiple channels.
  2. Foundational support for dynamic personalized experiences. From the structure and retrievability of the content to the amount and types of data you can store about your users, to the complexity of the rules you can write; personalization is an architecture concern, not a feature.
  3. Strong support tool and process for both content creators and developers.
  4. An open architecture that favors innovation with scale, security, performance and performance.
  5. True independence between content creation / management and delivery.  Content authoring and content delivery, while closely related, they are really two very separate concerns.  At scale, publishing needs to be both push and pull. Truly decoupled architectures align best with today’s needs.

Choosing a WEM Platform

Most people choose a CMS based on long check list of features and a demo of the authoring tools.  While checklists and demos are very important they don’t get at something much more fundamental, and in the case of the challenges we face, important and that’s architecture.  Architecture matters.   While many CMSs pass the checklist-demo gauntlet, nearly every CMS solution, regardless of what they claim, is an evolution on WCM and is ill-equipped for the Era of Engagement and beyond.  The proof is in the architecture.  Since so many CMS solutions out there claim to handle WEM but fail to deliver architecturally let’s dig in to some of the issues:

  • Most CMS platforms “couple” authoring and delivery.  While this is ok for some use cases it has a number of limitations:
    • Authoring and delivery often require unique security integrations.
    • If authoring and delivery are coupled in the same database, work-in-progress content is at risk to a security breach.
    • Coupled systems demand that authoring and delivery components share the same Service Level Agreements (SLAs) and scale out.  This significantly complicates the architecture and increases the total cost of ownership.
    • Most coupled architectures have no native PUSH support for content deployment which means they only support PULL style publishing (content rendered as HTML and JSON) and do not easily publish to disconnected / external systems via APIs.
  • Almost every CMS out there uses RDBMS database and JCR backed content.  This approach leads to a significant number of problems and constraints:
    • Scaling relies on clustering and replication and is difficult and clunky.
    • While clustering and replication schemes within a data center are approachable, globally distributing the topology via clustering and replication is whole other level of hurt.
    • Because code and content is stored in a database (in some cases just code) it’s extremely hard to innovate quickly because it’s very difficult to move code and/or content between environments and through the development process.
  • Many CMS’s are built on poor technology choices that ultimately slow the rate of development, deployment and kill innovation:
    • PHP a great example of technology that’s widely used in the CMS space.  The issue with PHP is that when it comes to heavy lifting or integration it breaks down.  Most PHP platforms like Drupal or WordPress require Java backed capabilities like Solr as soon as the going gets tough.  Making the right technology choices avoids work-arounds and leads to more simple, more cost effective and more maintainable infrastructures.
    • Older technologies like JSPs, Sling along with proprietary development and theme frameworks have huge learning curves or require hard-to-hire skills due to their niche application.
    • Approaches like war files and even OSGI are heavy deployment technologies slow time to market dramatically.  Scripting offers a much better approach for most functionality.
  • Most CMS’s have the wrong approach to user data. Storing user data in a traditional database doesn’t work at scale with today’s international regulations.
    • Many countries have on soil data requirements.
    • Many applications need to be able to access user data — but only see what they need to see.
    • Real personalization often requires a tremendous amount of data which in some cases must be analyzed in real time.  Traditional RDBMS doesn’t fit the bill.
  • Most CMS’s treat personalization, contextualization and localization as a feature rather.  They are not features. They must be part of the very fabric of the platform in order to succeed at scale.  Only the most basic use cases can supported unless these are treated like architecture rather than bolted on features.

Crafter CMS to the Rescue

Crafter CMS, a modern open source, Java based Experience Management platform is architecturally different than all of these other solutions — which means it can deliver different results.   Crafter is a complete and comprehensive WEM application built on top of leading open source technologies like Spring, Solr and Git – that provides multi-channel digital experience management through a rich user interface and a high-performance content delivery system, while providing content creative and development teams with the real tools they need to craft amazing personalized digital experiences for their customers.

Crafter CMS consists of thee major applications – Crafter Studio and Crafter Engine and Crafter Profile.

Crafter Studio provides all the content management services and integrates with repositories like Git, Alfresco and other CMIS based platforms to enable authoring, management, and publishing of all content. Crafter Studio provides a comprehensive set of user-friendly yet powerful features for managing and optimizing of experiences.  

Crafter Engine provides high-performance content delivery services that can power any type of Web or mobile application. It consumes content published through Crafter Studio and provides developers with the foundation for quickly building high-performance, flexible Web and mobile applications. Crafter Engine provides out-of-the-box integration with numerous data sources and application services. A key feature of Crafter Engine is its ease of integration. Modern WEM applications must integrate with one or more enterprise systems or third party services. Crafter Engine can easily be integrated with other applications such as CRM and sales force automation, marketing and email campaign management, and other enterprise systems required for optimizing the Web experience for your audience.

The management and delivery of content is decoupled and separate, allowing each system to be optimized for its purpose, audience and scalability requirements. Multi-channel publishing is naturally supported, and mobile devices and applications are enabled by means of both native device support (iOS and Android) and HTML5 support.

Crafter Profile provides a secure and scalable platform for storing, querying and analyzing user data at each interaction in your customer journey.  As it stands, data privacy concerns and international regulations are extremely complex and getting more complex with each passing day.  Crafter Profile leverages MongoDB and can store user data of any type and volume can be stored, the data is globally distributable to meet on-soil PII requirements. Further, Crafter Profile offers “Big Data” processing and analysis to the delivery tier to drive true personalization.

Content First

Crafter CMS completely separates content, code and presentation.  Content is captured and stored as XML and other static assets (images, videos, PDFs, etc) in the repository.  By leveraging a file based, XML approach, content is easily moved between environments and systems for work processes (e.g. translation) and is easily published to/for any kind of content consumer.

Extreme Scalability

Performance and scalability are an architecture concern.  If you have the wrong architecture you’re forced to use work-arounds like CDNs or build replication based science projects at the data layer.  Crafter avoids these by getting the architecture correct from the start.  Crafter Engine is a high performance Spring MVC based application that can render dynamic, personalized content in any format within milliseconds. Crafter Engine a shared nothing component that does not rely on external databases.  By leveraging local in-memory databases, fast disk and local Solr, Crafter Engine provides the proper foundation to build a cloud scalable, elastic globally distributed infrastructure.

Personalization in the Core

Crafter CMS treats personalization as a part of the architecture rather than a bolt-on feature. Crafter Engine and Crafter Profile combine to deliver a platform for high-performance personalization at scale with complete scriptability, security and regulatory compliance.

Truly Decoupled

Crafter CMS is a decoupled CMS that separates authoring and publishing capabilities into their own subsystems in order to achieve the many benefits discussed above. Crafter CMS makes it easy for authors to create, manage, and deliver content in any format from RESTful APIs/JSON to HTML5, and even virtual and augmented reality via AFRAME. So for modern digital experiences that must be delivered across many channels, Crafter CMS provides a decoupled architecture combined with Content as a Service capabilities.

Built for Innovation

To be truly innovative you have to be great at both building and delivering.  What good is a platform that performs well but is hard to update or a system that’s easy to develop for but is hard to deploy new features on?  Crafter CMS is built on today’s leading open source technologies like Java, Spring, Groovy, Freemarker, Solr and Git.  This means your developers don’t need to learn a vendor specific stack to get started.  The right technologies make all the difference.  Crafter CMS combines the integration power of Java with the speed of scripting (via Groovy for controllers and Freemarker for templates.) Further code related assets like templates, CSS, Javascript etc in are stored and deployed from Git.  This means your developers work locally with desktop tools if they want, and can leverage their standard DevOps process and tools to move features and functionality forward to production.

Conclusion

There have been major revolutions in technology like the industrial revolution, the amazing growth of the web 1.0 and many others throughout history that have changed the way we work and live — but there has been no changes like the kind of change we see unfolding now.  The key difference is: the the number things changing at once,  the pace at which the changes are occurring and the fact that all of the changes feed and reenforce one another’s momentum.

To deal with this new challenge and the pace at which it is advancing you will need to think differently and arm yourself with new ways of working, new architectures, new technologies and new tools.  Old guard and rebranded WCM solutions are no match for the future we face. With the growth of social, mobile, the Internet of Things and the coming of age of digital natives we must evolve, innovate and be able to adapt much more quickly in order to survive. Proper architecture and solution design will play a much bigger role in driving success than simple features. Crafter CMS is open source WEM project and platform that was built from the ground up and has an architecture designed for today and tomorrow’s digital experience needs.

Web CMS Architectures: Coupled, Decoupled, or Headless?

Generally speaking there are two main types of Web/Experience Content Management System (CMS) architectures: coupled and decoupled.  Historically the term “coupled” has referred to the relationship between the authoring tools and content delivery of your live site.  With the introduction of headless CMS platforms the landscape has become a bit more complicated.  Are headless CMS’s the new decoupled CMS?  Let’s explore.

Headless CMS

Headless CMS technology provides content to the presentation tier (or content consumer) as a service, typically via a RESTful interface in JSON or XML format. This is known as Content as a Service (CaaS.)

 

The main advantage of a headless CMS (CaaS) architecture is that content is written and published once but  can be requested and presented uniquely by any number of different channels / content consumers.

Coupled vs decoupled

The classic example of a coupled CMS architecture is a blog engine. In a coupled system, the underlying store for your content serves both authoring and delivery.  Your authoring capabilities are part of the live delivery system but are available only to those who have permissions.  In a coupled system, the process of making content live is typically a matter of setting a flag in the database.

A decoupled system by contrast is one that puts authoring and delivery in separate applications, and potentially, on separate infrastructure. In a decoupled system, the process of making content live is done through a publishing mechanism where content is pushed from the authoring platform (and underlying content repository) to a content delivery infrastructure.

So which approach is the right architecture? The reality is, there is no single right or wrong answer.  The answer depends on context: alignment with your requirements, your business process and your business goals.  The topic of coupled vs. decoupled is not a new one.  It’s a debate that has been going on for a long time and will continue to go on so long as there continues to be Web CMS platforms, “fan boys” and a perception that one size fits all.  The more appropriate way to approach the question is to analyze the strengths and weaknesses of each approach and then to consider these in the context your own specific use cases.  We’ll see that in different scenarios we come to different conclusions on which architecture to use.

Coupled architecture

Let’s take a look at the strengths and weaknesses for a coupled CMS architecture.

Strengths

  • Easy to setup and deploy a single instance.
  • Authoring and delivery are on the same infrastructure which can make it easier to build cohesive authoring tools.
  • Relatively easy administration of production system for single sites

Weaknesses

  • SLAs (Service Level Agreements) are coupled — meaning that authoring has to be just as available as the live site.
  • Coupled infrastructures are generally more complex to scale, as they typically depend heavily on database scalability.
  • Content is typically captured in a database schema meant for delivery on the site.  This can make integration and migration difficult.
  • Software complexity is higher because the code base contains both authoring and delivery concerns.  All but the most trivial CMS projects involve some development, and thus becomes an development issue.
  • Pushing content in and out of the CMS to and from third parties takes place in the same system that runs your live site.  Integration is not native to the architecture and it may impact the system’s performance.

Decoupled architecture

Let’s take a look at the strengths and weaknesses of a decoupled CMS architecture.

Strengths

  • Easier to scale for high traffic websites, and to handle multi-site management.
  • SLAs are decoupled.  Authoring can be down for upgrades without impacting delivery. The reverse is also true.
  • Scale only the components that you need.  If you are not adding more authors then there is no need to scale out authoring.  This affects the complexity of the solution and also license costs where they are involved.
  • Code complexity is isolated within each of the two components (authoring and delivery).  Each piece can be as simple or complex as is needed without impacting the other.
  • Integration is a built in concept, as content is natively published to a the remote delivery system, it is generally straightforward to push to other systems as well. Also note, integration takes place on the authoring tier safely away from the live site protecting stability and performance.
  • Content migration and sharing with other systems is generally much more innate to the architecture.
  • Multi-channel support by nature, as publishing to mobile apps, social channels, and other digital channels is a natural extension of the native publishing capability.
  • Content sharing and syndication are more naturally supported.
  • When complexity is isolated and scaling is simple, it’s easier to develop and deploy rich features to your users.
  • Integrating with devOps is much easier.  When you need to integrate your development tools, process/automation and source code repository you are inherently entering in to a discussion about security and systems administration — all of which are significantly more approachable if authoring and delivery systems are separated.

Weaknesses

  • Setup has more components and can be more complex.
  • Publishing introduces additional points of failure.
  • Sub-division of components can go too far driving up complexity and driving down the cohesion of the user experience.

Is a headless CMS a decoupled CMS?

While a headless CMS architectures do “decouple” content and presentation, they do not dictate anything about the publishing capabilities of the CMS.  And while decoupling content and presentation is certainly one of the most important things you can do architecturally, as we can see above, it’s not the only major architecture decision you need to consider. Therefore, it is important to maintain the traditional use of the word decoupled CMS as it relates to separation of authoring and delivery capabilities.

A headless CMS can either be coupled or decoupled.

Further, any CMS worth its salt today, (decoupled or not) must be support headless/CaaS based content delivery.

Making a choice between coupled and decoupled CMS

It’s clear that each approach has its own strengths and weaknesses.  A coupled approach may work really well in one scenario while a decoupled approach may be much more appropriate in another.

Our analysis reveals that a coupled architecture can work well for web apps, mobile apps, and other content-backed digital experiences that need to be set up and put on line in short order and that do not need to be able to scale quickly or to publish content beyond the website itself.  On the other hand, we see that a decoupled architecture is ideal for websites / content back ends that require high levels of availability and performance, need a lot of tailored functionality, must be integrated with third party business systems and must publish to one or more digital channels beyond the website itself.

Crafter CMS

Crafter CMS is a decoupled CMS that separates authoring and publishing capabilities into their own subsystems in order to achieve the many benefits discussed above.  Crafter CMS makes it easy for authors to create, manage and deliver content in any format from RESTful APIs/JSON, to HTML5, and even virtual and augmented reality via AFRAME. So for modern digital experiences that must be delivered across many channels, Crafter CMS provides a decoupled architecture combined with Content as a Service capabilities.

Building Angular2 Single Page Applications with Crafter CMS

Single Page Applications (SPA) are quickly becoming the industry standard for HTML5 based applications and responsive websites because they tend to be more user friendly, feel faster and are more responsive.

As with most applications today, SPA’s frequently contain a lot of content and related digital media such as images and videos.  Often times content and digital media are deployed statically along with the application. This approach creates unwanted dependencies for content updates on the developers and requires heavy deployment processes.

In the business context this misalignment and lack of independence can slow activities way down and ultimately impact the bottom line.  To address this common problem developers often build custom applications for non-technical users or leverage content management system (CMS) technology.  Building custom authoring tools doubles development time and creates an additional support burden on your development team. Leveraging a CMS is a great idea, but you need to make the right choice.  Many CMS architectures impose serious limitations on application and API architecture and design. As we’ll see in this article, Crafter CMS supports application developers with Content-as-a-Service that does not force any constraints on the application itself.

In this article we’ll build a simple (but not too trivial) SPA based on Angular2, then we’ll update it so that non-technical users may edit and deploy/publish content through Crafter CMS.

angular-2-pokedex

For our application we’ll start with a fun, simple Angular2 application called Pokedex written by Cory Rylan. The application is freely available via Github the AngularExpo. This application is a great example of a content application because, like most real-world applications, it contains content-oriented data that should be separated from the application code. Smart web/mobile/digital app developers separate content from their code.

The example application has two modes for retrieving data, the first option is via a static JSON data store that’s built at compile time and the second is pulling the data from a traditional data store.  Both out-of-the box options are not ideal for this real world scenario because to add new Pokemon to the Pokedex you need to be technical (i.e., a developer).  In this article we’re going to fix that so that any basic non-technical user can manage the Pokemon content, while the application consumes the data via Crafter’s API that provide Content-as-a-Service.

Step 1: Get Crafter CMS downloaded and installed

The first step is to get the CMS downloaded and installed. Crafter CMS is free and open source software licensed under GPL v3.

1.1 Download the Crafter CMS bundle

1.2 Install Crafter CMS and start it up

  • Unzip the download
  • Execute startup.sh (or startup.bat if windows) inside the unzipped folder
  • Open a browser to http://localhost:8080/studio. I recommend using Chrome. Chrome has the best support for desktop file drag and drop of all the browsers which will come into play later in this article.studio-login
  • Log in with username ‘admin‘ and password ‘adminstudio-no-sites

Step 2: Get the Angular2 application downloaded, compiled and tested

Now we want to get the application source code and get it running. To get and and build the code for this application you will need Git and NPM installed.

2.1 Download the source code

  • On a command line, execute: git clone https://github.com/splintercode/ng-pokedex.git
  • This will give you a folder called ng-pokedex in the same directory where you executed the command.

2.2 Compile the source code

  • On a command line, execute: the following commands
    • cd ng-pokedex
    • ng init (answer (N)o to all questions)
    • ng build –target=development
  • If you get the following error: ‘You have to be inside an angular-cli project in order to use the build command.
    • Simply add “angular-cli”: “1.0.0-beta.28.3”, to your package.json under devDependencies
    • and re-run the ng-build command.
  • To test your build:

angular-2-pokedex

Step 3: Install the application as a project in the CMS

We now have the prerequisites done and we’re ready to party! Let’s install the application into the CMS.

It’s worth noting that this step is completely optional.  You can run and manage the application code itself completely outside the CMS and simply leverage the CMS for the Pokemon content itself.

So why add the whole app to the CMS?

Several reasons:

  1. To show that it’s possible. You’ll note we’re able to load the entire application into the CMS with no changes at all outside of a few static asset path modifications to CSS and Javascript.
  2. Deployment. Once in the CMS, the application is now easily deployed (i.e., published) to any delivery infrastructure at the push of a button.
  3. Ease of Editing. With the app in the CMS we can overlay advanced authoring tools on the application via the CMS and allow the authors to edit In-Context of the application.  That’s sweet.

If you plan to manage the application outside the CMS completely simply follow Step 3.1 and move to Step 4.

3.1 Create and setup a CMS project to manage your application

  • In Step 1.2 you logged into the CMS as the admin user which has an admin role. On the screen you will see a button on the left hand that says “Create Site.” Locate and click this button.create-pokedex-site
  • Enter Pokedex as the application name.  Crafter CMS will generate an Site ID for you.
  • Select “Empty” for you blueprint and click the Create button.  Crafter CMS will create a new project for your Pokedex application with an basic “Hello World” type configuration.hello-site

3.2 Upload your application to the CMS

  • Click on Site Content in the menu at the top of the screen. This will open a panel on the left
  • Click on the Static Assets label this will open the folder.
  • Right click on static-assets folder and choose Bulk Upload Assetsupload-static-assets

3.3 Update the site template with the AngularJS 2 HTML page

  • In your ng-pokedx folder from step 2 you will find a dist folder. If is not there, execute ng build again. Drag the contents of the dist folder on to the upload dialog in the browser. When it’s done you will be able to click Done.Screen Shot 2017-02-26 at 6.09.09 PM
  • By uploading the compiled assets we’ve loaded the app into the CMS.  Now we have to tell the CMS to render our single page.  To do this we must update our out-of-the-box template provided to us by the blueprint.  In Crafter CMS, templates are coded in Freemarker and can contain any kind of markup (typically HTML 5) as well as special Freemarker Directives that make it dynamic.
  • To update the template: click “Site Content” in the menu at the top to hide the Site Content panel.   Then locate the Wrench in the upper right hand corner on the toolbar.  Click the Wrench.  This will open the Preview Tools panel on the right hand side of the screen.  preview-tools
  • Now click on In-context Editing to expand that specific tool.  You will notice this tool allows you to edit content, templates and controllers.  We’re interested in the templates.  Click Edit Template.edit-tempate
  • Replace the code in this template with the HTML found in your build directory at dist/index.html.Screen Shot 2017-02-26 at 6.23.51 PM
  • Note that the build assumes the application assets are at / on the server.  In Crafter CMS, static assets like CSS, Java Scripts and images are served from /static-assets.  You will want to modify the paths in the HTML template to use the /static-assets folder as shown above.  Once done, click update.angular2-app-craftercms
  • Your app is now running in the CMS!  Congrats!   With this complete, we can start working on making the application dynamic, editable by a non-technical user and updatable at any time without a deployment.

Step 4: Content enable the application

The first step in content enabling the application is determining what the content model is.  A content model is a definition and structure of the content.  We maintain the definition of the content structures within Crafter CMS by declaring Content Types.

To figure out what your Content Types should be, look for the NOUNS in the application that you want a non-technical user to be able easily update and publish at any time.  In our case, this is an individual Pokemon creature.

While a Pokemon in this simple application will be pretty basic, real world applications leveraging Crafter CMS can model very complex objects as well as relationships between objects.

Before get into the CMS, let’s figure out what the definition for our Pokemon type should be.  We do this by looking at the application and seeing what fields the app will require.

crafter-pokemon-detail

By clicking around in the application we come to learn that every Pokemon instance will require the following fields:

  1. Title
  2. Number
  3. A list of “Attacks”
  4. Height
  5. Weight
  6. Description

It appears we also need an image; however, looking closely at the application code, we’ll find that the application assumes an image has been uploaded with a filename based on the Pokemon number.  For simplicity sake, we’ll maintain this assumption even though it’s worth noting that enabling authors to upload and pick images, videos and other rich media is very simple in Crafter CMS.

OK! We have a list of fields we need for our Pokemon, let’s get started defining the type inside the CMS:

4.1 Declare a Pokemon Content Type

  • Open the Site Content panel.
  • Locate and click the menu item for Admin Console. This will take you to power user area in the CMS used to manage and perform various site administration tasks.
  • On the left panel in the Admin Console, locate and click the menu option for Content Types. This tool is used to create new Content Types and edit existing ones.content-types-console
  • On the toolbar at the top of your screen you will notice two options: Open Existing Type and Create New Type. Because a Pokemon is a new concept you want to introduce and define in the CMS, click on Create New Type. This action will pop up a dialog to prompt you for some basic information about the content type.
  • Enter Pokemon for the display label. Crafter CMS will suggest a content type name automatically for you.
  • The Type you want to choose is Component. In Crafter CMS anything that you are modeling which is NOT a page is a Component. The main difference in the CMS between pages and components is that page objects are automatically URL addressable while components are not.create-type-dialog
  • Once the dialog is configured, click Create. This will open the content type editor for your Pokemon Content Type. You can learn more about the content type editor in detail at http://docs.craftercms.org/en/stable/developers/content-modeling.htmlnew-pokemon-type
  • The Content Type Editor lets you drag/drop editing field types from the right hand controls list into your Content Type definition. You then click on the individual controls and configure them with Labels, properties, data sources and constraints.
  • For each field you need to add (Title, Number, A list of “Attacks”, Height, Weight. Description), look through the controls list and find the appropriate editing control for that content and drag/drop it into the Pokemon properties area.
  • After you add a field to the Content Type, click on it to configure it  in the Properties Explorer.
    • Add a label. This is the user facing name the author will see by the input control.
    • Crafter CMS will automatically suggest a variable name which you can use later in templates and controllers to access the content values.
    • Scroll down in the Properties Explorer to see all the properties and constraints for the given field. This is how you mark fields as required, change their input length and make other adjustments. pokemon-type-1
  • Notice that “Attacks” is a multi valued field.  Also, it uses a predefined list of attack types.  To support this field we’re going to want to use a control that allows the user to select several values and that gets its values from a list of options.  In Crafter CMS the way picker type controls get their values is via a Data Source.  There are several out of the box Data Sources and it’s possible to define your own as well.  For our example we’re going to use the most basic data source called a Static Key Value Pairs Data Source.  Scroll down in the Data sources area until you see it then drag/drop it on to the Data Sources portion of the Content Type definition.pokemon-ds
    Click on the added Data Source and begin to configure it.  Provide the title “Attacks“.  Crafter CMS will suggest a name automatically.  When you click on Options you will be prompted to enter a list of Key and the Value pairs. The “key” is stored with the user’s selection. The “value” is used for a label in the entry form.  Add a few attacks to the list and click Save.
    Clearly the Static Key Value pair Data Source is pretty basic.  If you need to access a managed taxonomy or re-use the same key value pairs in different content types you’ll want a different Data Source type but for our needs here it works well.
  • Once our Attacks Data Source is defined, lets add a control to the Content Type definition to capture the attack values as data.  The control you want is the “Grouped Checkbox” control.
    • Drag/drop it on the Pokemon properties area then click on it to configure it.
      • Provide the titleAttacks“.
      • Crafter CMS will suggest the variable name.
      • Scroll down in the Property Explorer until you see the “Attacksdata source listed and select it.  This binds the data source you created to this Group Checkbox control.  data-source-pokemon-group-checkboxes
  • Perfect! Your Content Type definition is now complete.  Click Save at the bottom of the screen.Note that you are going to get a warning that the content type does not have a template associated to it. That’s ok.  Not every Content Type needs a template.  In our case the app already knows how to render the content and we don’t need another template.  Click Save on the dialog.  You’ll notice a small save indicator on successful save.no-template-warn

4.2 Create Pokemon Content Objects

Now it’s time to create some test content.  To return to your project Click the Crafter Logo on the toolbar in the top left corner of the screen.  This takes you to your workflow dashboard.  From here you can create content or navigate back to your application preview via the Site Content panel.

  • Click on Site Content in the menu at the top of the screen. This will open a panel on the left
  • Click on the Components label this will open the folder.
  • Right click on components folder and choose New Content. create-content
  • The CMS will prompt you for the type of content you want to create.  You will note the Pokemon option.  Choose Pokemon and click “Ok.”choose-conent-type
  • Once you click OK you will be given the entry form for your Pokemon which you can start filling out.  Awesome! Crafter CMS automatically creates your Pokemon editing interface based on the Content Type Definition.pokemon-form
  • Repeat this process as many times as you want, creating a new Pokemon each time.  When you save the form you will see the Pokemon item listed under the Components folder as whatever value you entered into the Internal Name field (which is only used by the CMS editing tools as a label in the tool.)pokemon-components

Step 5: Configure a JSON based REST service to provide Pokemon content as service to the app

Any CMS worth its salt today can provide content via REST in JSON and other formats. Crafter does this out of the box — but Crafter also provides an important capability a lot of CMS do not and that’s an ability to easily define your own service. The dirty little secret with Content as a Service (CaaS) and CMS’s is that if you use the CMS’s out of the box APIs to get content you may be locking your self into the CMS and you are almost certainly forcing your app to adapt to the CMS. That’s the tail wagging the dog. Let’s look at how we can do small amount of scripting so that our JSON service response matches EXACTLY what the app expects (rather than changing the app to match the CMS.)

5.1 Create a RESTful Controller

  • Click on Site Content in the menu at the top of the screen. This will open a panel on the left
  • Click on the Scripts label this will open the folder.
  • Expand the scripts folder, right click on the rest folder and choose Create Controller.create-controller
  • Once you click Create Controller you will be prompted to enter a controller name.  In Crafter CMS the name of the controller in the REST folder follows a naming convention that defines the HTTP method that the controller responds to.  Our name is going to be “pokemon.get”  This means that we’ll end up with a service at the following URL “http://localhost:8080/api/1/services/pokemon.json”  that responds to GET requests.create-controller-dialog
  • When ready click create and you will be provided with a code editing screen.  In Crafter CMS, controllers are coded in Groovy (or Java).  There are many different kinds of controllers: REST controllers, page controllers, component controllers, request interceptors, scheduled jobs and others.pokemon-code-editor
  • Enter the following code in the editor and click update.
    def data = []// Define a query for pokemon content
    // Crafter CMS uses SOLR query syntax
    def queryStatement = ‘content-type:”/component/pokemon”‘
    def query = searchService.createQuery()
    query = query.setQuery(queryStatement)// Execute the query
    def executedQuery = searchService.search(query)
    def items = executedQuery.response.documents// For each result item, map the content type values to the names and JSON structure that the app expects
    // On the left hand side we see the fields the app expects on the right, the field variable names we defined.
    items.each { item ->
    def pokemon = [:]
    pokemon.id = item.number as Integer
    pokemon.name = item.title
    pokemon.description = item.description
    pokemon.height = item.height as Integer
    pokemon.weight = item.weight as Integer
    pokemon.types = item[“attacks.item.key”]
    data.add(pokemon)
    }

    // Return the data structure, which Crafter CMS will MARSHALL into JSON automatically
    return data

  • Now that our REST service is defined we can test it.  Open a browser to the following URL:      http://localhost:8080/studio/preview/#/?page=/api/1/services/pokemon.json&site=poledexpokemon-test-rest

Step 6: Update the app to use the RESTful Service

We’re in the home stretch now!  We have a dynamic service that updates any time we add, update or remove Pokemon content.  All we have to do now is change the application to use the new service.

6.1 Update src/app/shared/services/pokemon.service.ts

  • Add the following import:
    import { Response } from '@angular/http';
  • Add the following method:
    public getPokemon() {
    return this.http.get('/api/1/services/pokemon.json').map((res: Response) => res.json());
    }
  • Update the constructor to use the new getPokemon method:
    constructor(private http: Http) {
    this.store = { pokemon: pokemonData };
    this._pokemon = new BehaviorSubject(Object.assign({}, this.store).pokemon);
    this.pokemon = this._pokemon.asObservable().map(pokemon => pokemon.map(p =>         this.setPokemon(p)));
    this.pokemon = this.getPokemon();
    }
  • Rebuild your distribution by executing ng buld
  • In the CMS, Under the Site Content Panel:
    • Click on Site Content in the menu at the top of the screen. This will open a panel on the left
    • Click on the Static Assets label this will open the folder.
    • Right click on static-assets folder and choose Bulk Upload Assets
    • Drag/drop main.bundle.js and main.bundle.map to upload the latest build into the CMS.

update-app-js-pokemon

  • Under pages in the Site Content panel click home to load the preview and test the application.updated-pokemon-app
  • Congrats! Your app is now consuming content from the CMS.  You can now use the CMS to add new records or update existing ones!

 

Conclusion

Single Page Applications and the frameworks that help developers build them like AngularJS 2 are quickly becoming the defacto approach for building user-friendly responsive applications.  Smart developers will separate code from content so that non-technical users can quickly and easily update the application’s content without involvement from technical resources for code updates or deployments.  Integrating your CMS with your SPA is a strong pattern for solving this problem — but architects beware, not all CMS platforms are the same.  The wrong CMS will interfere with the development process and force interface and implementation details.  Crafter CMS offers the right architecture for the job. Crafter CMS integrates with your development process and tools and puts you app in control of the interfaces and implementation code while providing content authors with the tools they need  to update and publish the application independently.  To learn more check out Crafter CMS at http://craftersoftware.com and http://craftercms.org.

Special thanks to Cory Rylan and the Angular Expo for providing a fun application!