Creating public websites with staging and custom skins
In this tutorial, Martin Aspeli plays investigative journalist, deciphering Alan's ramblings to find out exactly how Enfold deploy real sites with staging and different authoring and public skins.
Introduction
Why would you want to do this?
Plone is a content *management* system. A lot of thought has gone into the user interface that enables the modification and organisation of content and workflow. Plone is also used as a content *delivery* platform, pushing content (via Zope and probably a web server like Apache) down to the browsers of people who just want to view the content, not manage it. Typically, it is the same object (e.g. a page or a news item) that is the point of reference for the person managing the content and the person consuming it. We'll call this scenario "in-place editing".
For many people, this in-place editing works well. It is easy to understand, it is easy to see the effects of your changes, and this is indeed the default way of doing things in Plone. For some more demanding users, however, in-place editing can be a problem. The use case here is when Plone is used principally to manage content such as pages, news items or events that is to be presented in a branded website. Some of the drawbacks of the in-place approach are:
Theming -- For a professional public-facing website, you'll probably not be happy with the standard Plone look-and-feel. It is not very hard to "re-theme Plone":/documentation/tutorial/creating-custom-style, but often your public-facing theme and branding may be difficult to adapt to a content-editing scenario. Patching together Plone's editing views with your designer's vision of the public web site often leads to sacrifices in one of Plone's strongest areas: usability.
Control -- You may want to impose more control on how the final site ends up looking than what standard workflow can support. For example, you may want to your content editors to work on several parts of the site at once, but only update the public site when all the pieces are ready. Workflow for in-place edited documents works on one item at a time. Worse, there is no support in an out-of-the-box Plone site for working on an already-published document and only publishing the changes when they have been finalised and approved.
Performance -- Because it has to support logged-in users making changes to the live system, Plone's default authoring templates are harder to cache, deploy to other delivery platforms (e.g. using "Entransit":/products/entransit or "CMFDeployment":http://projects.objectrealms.net/projects/cmfdeployment) and performance optimise.
Repeatability -- If you are a consultant or technical lead setting up "serious" deployments of Plone more than once, having a repeatable way of setting up your Plone sites robustly is important. With in-place editing, it's more difficult to separate the repeatable parts of the development and deployment process from the parts that need heavy customisation, from the parts that should ideally involve no change to Plone's default behaviour.
The approach described in this tutorial is the one championed by "Enfold Systems":http://enfoldsystems.com for enterprise deployments. Briefly, it consists of:
o Standard Plone as the content *management* environment
o A folder in the Plone root, conventionally called 'public_website', where the public website is located. All day-to-day content management happens outside of this folder. When content is ready, it is deployed to the public website.
o This two-staged approach to content publication is called 'staging', and is enabled by "EnSimpleStaging":/products/ensimplestaging.
o A "retail view" for the public site - this is simply a "Plone skin":/documentation/tutorial/creating-custom-style that deals only with the public view of the site, not any editing views. As such, it can be greatly simplified from the full-blown Plone skin. Often, it is easiest to disregard Plone's main_template and CSS entirely, providing your own alternatives only as far as your needs go. (For optimisation in advanced use cases, using Five views for these views may be a good idea)
o Two URLs configured for the site via Apache rewrite rules. For example, 'http://admin.mysite.net' may point to the standard Plone root and the Plone editing environment, whilst 'http://mysite.net' would be the public view, pointing to the 'public_website' folder directly.
o An 'Access rule' in the 'public_website' folder. This is a Zope mechanism that in this case will be used to ensure that when accessing 'public_website' from the URL 'http://mysite.net', visitors will see the "retail view", not the standard Plone skin.
We will cover these steps in more detail in the following pages. Before you launch into this, though, you need to carefully consider whether you really want or need staged content and separate editing and display environments.
There are several reasons why this setup is not the default:
Ease of use -- For many users, separate editing and delivery skins may be confusing. It is harder to see exactly how content will look in the final site (which may necessitate content previews or similar solutions), and it is more difficult to know to change something on the public site, say if you discover a problem with a page there. You can of course get around this by customising the standard Plone editing skin as well, but this kind of defeats the point; alternatively, you will have to rely on previews or similar mechanisms.
Set-up time and difficulty -- This approach does require more set up than a vanilla Plone site, and you generally have to know what you're doing. If you don't understand acquisition, workflow, security and other basic Zope and Plone mechanisms fairly well, you are likely to find yourself in deep waters soon.
Interoperability -- Most products are written for the default set-up of in-place editing. Hence, not every product will work equally well with staged content. If you have a highly interactive site where users are logged in most of the time and use the system as an application rather than purely for viewing content, you're likely to find that many of the products that provide this interactivity make assumptions that don't gel with the staged approach.
Sometimes it may be worth working around these problems, sometimes it may not be. Since there is no one right answer, you'll have to rely on your experience and prototyping to find the balance that works for you. If you are in doubt, read on and think carefully about what is being suggested. If this tutorial doesn't make much sense to you, you're probably better off sticking with in-place editing, at least for the time being. It shouldn't be too difficult to move to a staged solution at a later date if it becomes necessary.
Pieces of the puzzle
Several technologies are involved in this set-up. It is important that you understand what each of them does.
First of all, you obviously need Zope and Plone. You're recommended to use the latest versions (but check the requirements for "EnSimpleStaging":/products/ensimplestaging as well). See the "set-up from source how-to":/documentation/how-to/setup-from-source for more information.
Secondly, you need to run a web server in front of Zope. This is a good idea for performance and security reasons. In this case, we also need to be able to server Zope on two different URLs, to differentiate between the authoring and public environments. The "Plone and Apache tutorial":/documentation/tutorial/plone-apache covers the basics of setting up Apache. Details about setting up Zope behind Apache on Windows can be found in "this tutorial":/documentation/tutorial/multiple-plone-instances-windows. We will cover some configuration of Apache and IIS, and the access rule that changes to the "retail view" when you access your site over the public URL in the subsequent pages.
With the servers in place, you will need to set up a basic Plone instance and install "EnSimpleStaging":/products/ensimplestaging. This is the tool that manages the deployment of content from the authoring environment into the public site. We will cover how to configure this shortly.
The "retail view" of your site needs to be a separate plone theme (aka skin). See the "DIYPloneStyle product":/products/diyplonestyle and "tutorial":/documentation/tutorial/creating-custom-style for details on how to create separate theme. As mentioned before, you probably don't to worry about themeing any part of the editing environment, which significantly simplifies your theme and frees your from many of Plone's UI comitments and complexities. It's probably a good idea to start with a simple theme and not spend too much time tweaking it before you've seen how the staged approach works and decided it's right for you (of course, you would probably need a custom skin for an in-place scenario as well, but the approach you take to making such a theme may be different).
You should of course also install any add-on products you want to use. Later, we will discover that not every type of content works well with staging. For example, it makes little sense to stage an issue tracker or a job board. You can, however, add such content directly to the public site.
Setting up Plone
With the server set up, a Plone instance created and products installed, we must configure the Plone site to work with staging.
The public webiste to which content is deployed from the staging environment is conventionally called 'public_website'. EnSimpleStaging will use this as its deployment target, and the public "retail view" theme will only be applied to this folder.
o To create the 'public_website' folder, simply add a 'Folder' in the Plone root from the Plone UI (**not** in the ZMI!).
You may give it whatever title you want. However, since Plone by default does not enable direct editing of "short names" (aka ids), you may want to use the 'actions' drop-down to rename the folder to 'public_website' afterwards (this is mostly for consistency, it doesn't really matter what the folder is called).
**NOTE:** In versions of Plone prior to 2.1.2, the 'actions' menu did not provide rename functionality, so you would have to go to the 'contents' tab in the Plone root to rename the folder instead.
We then need a bit of magic to ensure the "retail view" theme is applied:
o In the ZMI, go to the root of your Plone site, create a 'Script (Python)' with the id 'applyRetailView'::
request = context.REQUEST
if request.get('URL').startswith('http://public'):
context.portal_url.getPortalObject().changeSkin('Retail View')
o Still in the ZMI at the root of your Plone site, select 'Set Access Rule' from the 'add' menu, and enter 'applyRetailView' as the id.
There are several things to note here. First of all, we have created an access rule from the little 'applyRetailView' script (notice how the icon for the script has changed). This means that the script will be called when the folder is visited. When invoked, the script checks the URL in the request, and if it starts with 'http://public', it changes to the 'Retail View' skin (theme). This assumes that the public URL of your web site starts with 'http://public' and that your "retail view" skin is called 'Retail View'. You can of course change these strings if your theme is called something else, or if your public URL is different. All that is required is that the URL does not match the one through which you will access the authoring and staging environment.
For example, if you are running 'http://mysite.net', which is also accessible via 'http://www.mysite.net', and you will do your authoring via 'http://admin.mysite.net' (we will set up the difference between the public and authoring url's in the next section), you could do::
request = context.REQUEST
url = request.get('URL')
if url.startswith('http://mysite.net') or url.startswith('http://www.mysite.net'):
context.portal_url.getPortalObject().changeSkin('Retail View')
Coupled with the Apache or IIS configuration we will cover in the next section, that will make sure your visitors see the public "retail view" skin. However, Zope will not be much wiser.
Let's say a portlet on the public website does a catalog search for all recent news items. Zope would use the 'portal_catalog' tool from the Plone root, which would find all news items regardless of whether they were in the 'public_website' folder or in the stage. The simplest solution is to make sure that such queries include a path query like 'path = "/Plone/public_website'. You can achieve this customising the relevant portlets in your skin, for example.
For other tools, such as 'reference_catalog' or 'uid_catalog', it is actually necessary that the authoring/staging versions and the 'public_website' versions are separate. We can achieve this by setting up custom versions of these tools inside the 'public_website' folder, which will be acquired before the ones at the portal root. EnSimpleStaging ships with an External Method to do just this.
o In the root of your plone create a External method with id, 'setup_local_tools'
- id: 'setup_local_tools'
- module: 'EnSimpleStaging.Install'
- function: 'setup_local_tools'
o Create a Script (Python) with id, 'do_setup'::
from StringIO import StringIO
context.setup_local_tools(StringIO())
return 'Done'
Save this script and click 'test'. It should return 'Done' when it is finished.
Finally, you must set up your workspace. This is where the content production and staging occurs. Content created inside a workspace can be deployed to the public website, either incrementally or all at once. It is also possible to set up different workspaces, perhaps with different workflows or permissions for different groups of users, deploying to different subfolders of 'public_website' (or to the same target, but then you may get conflicts).
o In the Plone interface, create a 'Folder' called 'workspaces'
o In the 'workspaces' folder, add a 'Staging Area', and call it e.g "Authoring Space"
o Set the deployment path for the staging area to be 'public_website'
o If you want only published content to be deployed, enter 'published' in the "Deploy states" field. This ensures that the standard Plone visible-pending-published workflow cycle applies to staged content as well. You can enter other deployable states too, one per line.
Configuring your web server
With Zope and Plone set up, you need to set up Apache or IIS so that the public site and the private site are on separate URL
Trying it out
With all the pieces in place, you can try out your new staged site.
Let's try to stage a simple Page and Folder.
o Go to '/workspaces/authoring-space' in your Plone site - this should be the Staging Area you created previously.
o Click on the 'Public Node' - this is the Sandbox where content will be staged from.
o Create a 'Page' and enter some text. If you chose to only stage published content, you should publish it now.
o Create a 'Folder', and call it 'Help'. Publish it.
o Inside the 'Help' folder, add another 'Page'. Publish this too.
o Return to the 'Authoring Space'. You should now see the recently created/modified content, as well as any content pending review. At the botton, you will see the previous deployments.
o Scroll down and click 'Complete Deployment'. You can enter a note to go along with the deploymenet if you wish. You can make incremental deployments from now on, deploying only what's changed. For large sites, this may be necessary for performance reasons.
o Now look at the 'public_website' folder. Your content should be there, mirroring the structure under 'Public Node'.
o If you now access 'http://public.mysite.net', you should see your content using the "retail view" skin.
Taking it further
The solution we have outlined is fairly flexible. However, not all content makes sense to stage. There are also many other ways of using EnSimpleStaging to stage content.
EnSimpleStaging is, as its name suggests, quite simple. It helps you move content from the staging sandbox to the public site, and it can filter what it stages based on workflow state. By not being more restrictive, EnSimpleStaging allows you to manage your site and authoring process using other Plone tools more easily.
Here are some suggestions for how you may want to configure your system:
Unstaged content -- Let's say you wanted an issue tracker in your site. Staging that makes no sense. Luckily, EnSimpleStaging is clever enough to leave unstaged content in the 'public_site' alone. Hence, you can simply add your issue tracker object to the public site manually, and it will be left alone.
Multiple workspaces -- You can add several staging areas, and use different permissions on each via the 'sharing' tab. Hence, different groups in your organisation can use different workspaces to manage different parts of the site.
Multiple workflows -- With "CMFPlacefulWorkflow":/products/cmfplacefulworkflow you can even have content different workflows for each workspace.
Multiple stages -- You can make one stage deploy into another. For example, you could let several teams each have their own workspace, all deploying into a single staging area. This area would be used to view the site as a whole, before being deployed to 'public_website'. Permissions and workflows would probably be different in each workspace.
