Single Page Applications and Content Management Systems

This weekend, over beers and hockey, I heard a comment about how many Content Management Systems (CMS) do not support the use of modern single-page application (SPA) approach.  Normally, this would not have bothered me, but since this was not the first time I heard that point this holiday season, I feel like I need to set the record straight.  A CMS manages content.  The CMS provides a way to manage that content, include placing it on a page.  All of that work is done within the constraints of the CMS tool (examples include Sitecore, Joomla, Adobe Experience Manager, Drupal, WordPress, etc.).  What that CMS does with that content, however, is completely up to the developer/implementer.

A well-designed CMS system depends upon a collection of components.  These components each fulfill a different set of needs, either layout\design (such as a block of text with a title and sub-title as one component and an image, header, and block of content as another component) or feature\functionality (email address collection form, credit card payment section).  Each of these components support different content.  This means that a component that is a title, a sub-title, and a block of content must be able to support different text in each of those areas.  Creating a website is as simple as selecting a page template (there may be more than one) and then using the CMS functionality to put the various components onto the page.  An example of what this could look like is shown below:

An example page broken down into various content sections

The de-facto way to manage this is for the developer to write one or more HTML\CSS page-level templates, which act as the container for the components that site authors put into onto that page.  Each of those components is defined the same way, as snippets of HTML\CSS.  This means that the request\response cycle looks like:

  1. User clicks a link into the website
  2. Request made to URL
  3. CMS determines page for request, extracts definition
  4. Pulls out page template HTML
  5. Inserts all component HTML as defined, adding any author-controlled data such as the text for the title, which image to display, etc.
  6. Responds with completed HTML
  7. User presented with completely new page

That this is the general approach is what leads to the assumption that CMS systems do not support SPA-type designs.  This assumption is wrong. Virtually all enterprise-level CMS systems will support a non-page refresh approach to design, and all it takes is thinking outside the “de-facto” box.

One example of thinking about this process differently:

Consider an approach where a link on the menu does not request a new page, but instead makes a RESTful request to the CMS that returns information about what components belong on the “selected page” and where they need to be placed on that page.  Assuming each component is able to populate itself (perhaps through an AJAX approach after the component gets the ID that defines its content and was provided in the original RESTful request in response to the click on menu item), then it becomes a simple programming problem to assemble it into a coherent structure that is completely CMS managed.  The flow below walks through what this could look like.

  1. User clicks a link into the website
  2. RESTful request made to URL
  3. CMS determines page for request, extracts definition
  4. Provides page template identifier
  5. Adds information about the components
  6. Responds by sending a JSON object that describes the page layout
  7. Client-side processes JSON object and includes all necessary components (HTML & business logic)
  8. Rendering starts for user
  9. Each component makes an AJAX query to get its own content (if necessary)
  10. User presented with fully-rendered page without a complete page refresh

Using this kind of approach means that the JSON object returned in (6) to represent the pay shown earlier may look something like this:

{
"pageTemplate": standard,
"content": [{
"component": {
"template": "title_subtitle",
"contentId": 12875342567,
"sortOrder": 1
},
"component (copy)": {
"template": "email_signup",
"contentId": 12875618367,
"sortOrder": 2
},
"component (copy 2)": {
"template": "calendar_events",
"contentId": "129UY54A7",
"sortOrder": 3
}
}]
}

Which should be simple to process, even in that un-typed crap show that is Javascript.

I know what you are thinking, “Hey Bill, if it’s so simple, why isn’t everyone doing it”.  That is actually easy to answer.  There are many reasons why a company would choose NOT to build a SPA-like façade over their CMS.  In no particular order:

  • Complexity – It is easier and cheaper to write HTML-based components where the CMS interlaces them for you.  That is what CMSs do – they manage the relationship of content.  Abstracting that out to a client system adds complexity.
  • Editor support – Many CMS systems use WYSIWYG editors, so there is a need to have a defined HTML structure in a component so authors can see everything as they build it.  Since that structure has to be there already, any changes to client-side rendering is all new work.
  • Requires simple graphical design – the more complex the graphical layout of a site, the more complex a SPA wrapper would need to be.  The example that was used above is simple, one column that contains several components.  What if there are multiple columns in a page?  What if one of the components is a multi-column control that allows the author to put multiple columns of content into a single page column?  As the components get more complex, so will the work you have to do on the client to process them correctly.
  • Search-engine optimization – The whole point of a CMS is to have fine control over messaging and content.  A SPA-like approach makes SEO optimization problematic as search robots still have problems understanding the interaction between page changes and content changes – so cannot properly index content.
  • Analytics – Most analytics tools will just work when looking at sites where new pages load in the browser.  They will not “just work” in a SPA environment, instead you will generally need to add client-side logic to ensure that clicks are properly understood, with the correct context, by the analytics package.
  • Initial load – the first visit to a SPA application is long, generally because all of the templates need to be downloading before the first page can render.  There is a lot of downloading that would need to happen in an enterprise-level website with 10 page templates and 100 different components.  Yes, it could be shortened by using background or just-in-time loading, but are you willing to take a slow-down in an ecommerce environment where the first few seconds of the interaction between visitor and site are critical?
  • 3rd party add-ins – Analytics was mentioned earlier as being a potential issue.  Similar problems will happen with common third party add-ins like Mousify or Optimizely; the expectations that those tools have around working within a well-understood DOM will affect the usefulness of those tools.

I know, I spent the first part of this post talking about how it is possible to do this, and then spend the second part seeming to say why it should not be done.  That is not what that second section is saying.  Other than the first three bullets, all of these points are issues that anyone considering a SPA site should understand and account for in their evaluation, regardless of a CMS.

What it really comes down to is if, after understanding the implicit limitations imposed by a SPA approach, you still feel that it is the best way to design your website, then rest assured that your CMS can support it.  You simply need to change the way that your CMS delivers content to match the new design paradigm. The easiest approach to understanding this is to build a simple POC.  There are two “web pages” below.  It is made up of 1 page template and 4 content components: block of text with title and sub-title, an email sign-up form, a calendar, and an image.  Note that the second page has 2 instances of the block of text component with different content. 

If you can make this work in your client-side framework d’jour, than you can do it with your CMS.

A discussion on data validation

Validation is a critical consideration when considering sourced data, that data over which the system designer does not have complete control.  Validation is also an essential part of interpersonal relationships, but that is out of scope for this article…  When looking at sourced data (and interpersonal relationships, actually), we can see that data can be made up of historical data, integration-related data, and\or user-entered data.  This data is called out because it was created by systems that are not necessarily making the same assumptions about data as your system.  Since there are different assumptions, there is a chance that this provided data will not work within your system.  This is where validation comes in; a way of examining data at run-time to ensure “correctness.”  This may be as simple as the length of a field to something more complicated and businessy, such as a verified email address or a post-office approved address.  This examination for “correctness” is validation. 

In the grand scheme of things, validation is simply the detection, measurement, correction, and prevention of defects caused directly, or indirectly, by weak quality data.  There are three different types of validation, internal validation, external validation, and process validation.  Internal validation methods are embedded in the production system at design time to ensure the internal validity of data by eliminating any inconsistencies. External validation, on the other hand, makes use of knowledge about the real world. This use of the real world means that, when looking at a data model, external validity of that model is determined by comparing it against the real world.  Finally, process validation focuses on actual data processing operations. This focus on operations means that all data defects are synonymous with process defects, and thus, correction of process defects effectively leads to the prevention of future data defects. Efforts around process correction are based upon the fact that once a piece of incomplete data is in a database, it will be challenging to fix.

lotsa words needs a picture of ducks!

Validation and correctness are somewhat vague words, so let us add some context around them.  The easiest way to do that would be to talk about the different types of validation that may need to be done.  The most common forms of validation are range and constraint checking, cross-reference checking, and consistency checking.

  • Range and constraint check – this approach is where the validation logic examines data for consistency with a minimum/maximum range, such as spatial coordinates that have a real boundary, or consistency with a test for evaluating a sequence of characters, such evaluating whether a US phone number has ten digits or a US postal code has either 5 or 9 numeric values.  A presence check, where a value is validated based on the expectation that it is populated, is a unique example of a range and constraint check.
  • Cross-reference check – this type of check is when a value is validated by determining if it exists elsewhere.  This is the kind of validation where a user-entered postal code would be checked against a database of postal codes do determine validity.  This is different from the constraint check, which was simply checking whether the characters in the entered string were appropriate and not making any determination as to whether those values are real.  Another example of a cross-reference check would be a uniqueness test, such as evaluating whether or not an email address has already been used within the system.  You can depend upon cross-reference checks being more expensive than are range and constraint checks.
  • Consistency check – where the system determines whether the data entered is consistent.  An example of this would be checking to see if the date shipped on an order is before the date the order was placed.

The last thing for consideration as part of validation is post-validation actions, the steps to be taken after data validation.  The easiest decision is when validation is successful, as the business process can continue.  The more significant decision is what to do when validation fails.  Three different actions can happen in the event of a validation failure, an enforcement action, and advisory action, or a verification action.  I guess there is always the option of taking no action at all, but that kind of makes the performed work to perform the validation of a big ole’ waste of time…

  • Enforcement action – When taking an enforcement action, the expectation is that data that vailed validation will be put into a correct state.  There are typically two different ways that could happen, either the user corrects the information based upon feedback from the validator, such as by providing a missing value OR the system automatically fixes the data, such as fixing the capitalization in the LastName field when entered with AllCaps.
  • Advisory action – this approach is when the data is either accepted or rejected by the system, with an advisory is issued about the failed validation.  This approach tends to be taken when there is no user involvement and thus no ability to perform an enforcement action and could be represented as an item being loaded with a status that indicates the validation problem.
  • Verification action – This type of approach could be considered a select type of advisory action.  Also, by design, it is not a strict validation approach.  An example of this approach is when a user is asked to verify that the entered data is what they wanted to enter.  Sometimes there be a suggestion to the contrary.  This approach is relatively common in those sites that validate addresses, for instance.  In that case, the address validation may indicate that the street name is incorrectly spelled, so you end up giving the user the option of accepting the recommendation and replacing the value with the corrected value or keeping their version.

Validation is an important consideration when building any application that interacts with data.  There are various types of validation, such as internal validation, external validation, and process validation.  There are several different types of checking that could be performed for the validation, including range and constraint check, cross-reference check, and consistency check.  Lastly, there are three major approaches for managing an error: and enforcement action, and advisory action, and a verification action.

The next posts in the Validation series will show how to implement differing validation strategies.  Stay tuned!

Configuring the AWS Toolkit in JetBrains’ Rider

JetBrains just announced their release of their Amazon Web Services Toolkit for Rider.  For those that aren’t familiar with it, Rider is JetBrains’ cross-platform .NET IDE. Rider is based on JetBrains’ IntelliJ platform and ReSharper, and can be considered a direct competitor to Visual Studio.  It is also considerably less expensive then is Visual Studio.  If you don’t already have Rider, you can download a 30-day trial version at their site.

NOTE:  There is actually more work that needs to be done to fully configure your system to support the AWS Toolkit in Rider.  These steps include:

  • An AWS account configured with the correct permissions. Create a free AWS account here.
  • The AWS CLI (Command Line Interface) and AWS SAM (Serverless Application Model) CLI tools, which the plugin uses to build, deploy and invoke your code. SAM Instructions are several steps long and not trivial.  The regular CLI install steps, shown here, are also not trivial.
  • .NET Core 2.0 or 2.1. It’s not enough to just have .NET Core 3.0 or above installed. Make sure you’re running tests on the same version you’re targeting. Instructions
  • The SAM CLI will download and create a container to invoke your Lambda locally. Instructions (Should be covered in the CLIs, but just in case)

Install the Toolkit

Before we can walk through the new toolkit, we have to get it installed.  Installing the toolkit is simple once all the prerequisites are completed.  The directions are available from the AWS site here.  I have created my own version of these directions below because the sample on the AWS site is based upon the IntelliJ IDE rather than the Rider IDE so some of the steps are slightly unclear or look different.

  1. Open Rider. You do the installation of tool kits through the IDE rather than installing them outside of the context of the IDE (like a lot of the Visual Studio tool kits)
  2. Select Configure on the splash screen as shown below.
    Rider-Configure
  3. Select Plugins on the drop-down menu. This will bring up the Plugins
  4. Search for “AWS”. You should get a list of plugins, including the AWS Toolkit.
    Rider-AWSToolkit
  5. Install it.
  6. After installing, you will be asked to restart the IDE. You should probably go ahead and follow those directions.  I didn’t try NOT doing it, but I am a firm believer in the usefulness of “turning it off and on”; so I am all over it when the manufacturer tells me to take that step.
  7. Once the application is restarted, selecting New Solution will show you that there is a new solution template available, the AWS Serverless Application, as shown below.
    Rider-CREATEAWSSolution
  8. Go ahead and Create the solution named HelloWorld. It may be a little predictable, but HelloWorld is still the gold standard of initial applications…  Rider will go ahead and load the solution once it is completed and then open the README.md file.

Configure your connection to AWS

If you have already connected to AWS through the CLI or another toolkit or IDE, you should see the following in the bottom left corner of the IDE:

Rider-CredentialsReloaded

If not, follow the instructions for Configuring the AWS CLI here.  This will setup your default profile.  You will probably have to restart Rider after setting up your credentials.

Once Rider is restarted, you will see a notification on the bottom-right of the window that says “No credentials selected.”  Before you do what I did and roll your eyes, muttering “OMG” under your breath, click on that message (which is really a button)

Rider-NoCredentialsSelected

And find out that it is actually a menu.  Select the credential from the drop-down (it is probably called Default)

Rider-SelectProfile

And you’ll see that the it no longer says “No credentials selected.”  Congratulations, you are connected!