Environment Styler for Sitecore

tl;dr; Install the module, set the config value to match your environment, have a stylised login screen and header bar per environment.

Have you ever sat there working on some task and then suddenly someone asks you to take a look at an issue on the Production environment? So you log onto that server, resolve the issue, get distracted for a few minutes by cat videos and then get back to what you were doing. But you suddenly realise that those changes you were just making was not on your local environment, you still had the Production site open in your browser tab! Oh noes!

Oh noes!

The problem is that all the environments all looks exactly the same… the only difference being that teeny tiny URL bar, the URL in which probably also looks very similar apart from some environment prefix.

Instead, let’s start the year off by not making that mistake in the wrong environments!

Login Background

Just before the Christmas break, Michael West shared a tweet about changing the background image of the login screen:

Simple way to change this is to point the config setting to your custom background:

<!--
  LOGIN BACKGROUND IMAGE URL
            Sets the background image used on the login page /sitecore/shell/default.aspx
            Default value: "//"

-->
<setting name="Login.BackgroundImageUrl" value="/sitecore/login/drop_wallpaper.jpg"/>

And you can do all sorts of pretty and festive things with it!

CSS can do styling too!

The problem is that this is changed just on the login screen. Once you’re logged in, you still potentially have the same issue of not having a visible cue to what environment you are on.

We’ve gone a bit further and have been using some CSS styling to identify the different environments. This has the advantage that it is not just the login screen that is styled, but also the header ribbon that is visible on all pages in the CMS interface.

Unfortunately we went and did the dirty – hacked some standard Sitecore CSS files. Sorry! To undo the bad deeds of last year, I went ahead and cleaned up that code so no default Sitecore files were harmed during the making of this module.

.logo-wrap::after,
.sc-globalHeader::before {
    color: #fff;
    font-weight: bold;
    font-size: 1.6em;
    content: "Production";
    text-transform: uppercase;
    position: absolute;
    margin-left: 60px;
}

.logo-wrap::after {
    position: relative;
    font-size: 3em;
    margin: 0;
    display: block;
}

.sc-globalHeader {
    background-color: #FF0000;
    background: radial-gradient(circle, #FF0000, #FF8C00, #FF0000);
}

.login-main-wrap {
    background-color: rgba(255,0,0,0.5);
    background: repeating-linear-gradient(to bottom right, #FF0000 15%, #FF8C00 30%, #FF0000 45%);
}

Most of the CSS is fairly straight forward, the slightly more interesting part is probably the ::before/::after selector and content property. It’s worth reading this article to understand what is going on there, but we are basically adding a pseudo-element, styling it as needed and setting the element text to what’s set in the content property.

The “local developer” stylesheet is heavily commented so take a look there to see some of the styles you can override.

Note that all stylesheets import the PROD file, add changes to that file for it to apply to all environments (e.g. client logos).

See the screenshots below for some examples.

SPEAK to me!

Getting the CSS file injected into the SPEAK based pages was very easy – that is, the Launchpad and Experience Editor.

On Sitecore 8.1+ we can tap into an existing processor in the speak.client.getPageStylesheets pipeline and slip in our custom stylesheet:

<speak.client.getPageStylesheets>
  <processor type="Sitecore.Web.Pipelines.GetPageStylesheets.GetVersionStyles, Sitecore.Speak.Client">
    <stylesheets>
      <stylesheet path="/sitecore modules/EnvironmentStyler/environment-override-$(sc.Environment).css" />
    </stylesheets>
  </processor>
</speak.client.getPageStylesheets>

Unfortunately that processor does not exist in Sitecore 8.0 releases, so we can create a processor to add the stylesheet in ourselves.

Extend the Page and inject

The regular WebForms pages of the CMS interface were a little more troublesome. So that’s the login screen, Content Editor and the Desktop. The Content Editor itself was not too much of an issue, but the other 2 pages did not follow this same rule and I couldn’t find a way in, but one possible way…

I couldn’t find much information on PageExtenders apart from this single article on Custom PageExtender from fellow MVP Mike ‘Gold Suits’ Reynolds. PageExtenders allow you to insert any HTML code to all/any of your pages using the PageExtenders pipeline for WebForms pages and mvc.renderPageExtenders pipeline for MVC pages. We only care about the first one.

public override void Insert()
{
    if (string.IsNullOrWhiteSpace(_cssFile) || _urlPaths.IndexOf(Sitecore.Context.Page.Page.AppRelativeVirtualPath, StringComparison.InvariantCultureIgnoreCase) < 0)
    {
        return;
    }

    if (Sitecore.Context.Items["sc_pagescriptmanager"] != null)
    {
        PageScriptManager.Current.StylesheetFiles.Add(new StylesheetFile {Src = _cssFile});
        return;
    }

    if (Sitecore.Context.Page.Page.Controls.Count > 0)
    {
        var control = new LiteralControl(StylesheetLinkTag.FormatWith(_cssFile));                
        foreach (System.Web.UI.Control pageControl in Sitecore.Context.Page.Page.Controls)
        {
            if (pageControl is System.Web.UI.HtmlControls.HtmlHead)
            {
                pageControl.Controls.Add(control);
                break;
            }
        }
    }
}

The 2nd if statement runs for the Content Editor and the Desktop, and we add the stylesheet to the PageScriptManager which Sitecore is helpful enough to provide us. Our script will be rendered in the <head> as expected.

The 3rd if statement runs for the Login page. There are no helpers here so we have manually inject in the stylesheet element by inspecting the controls already added to the page.

The 1st if statement has been added to break out of the processor early for pages we don’t want to inject anything onto. We use a config setting to specify the paths:

<setting name="FS.EnvironmentStyler.Paths" value="~/sitecore/login/default.aspx|~/sitecore/shell/default.aspx|~/sitecore/shell/applications/Content Manager/default.aspx" />

You can find the full code here.

Usage

Install the module and then change variable to match your environment:

<sc.variable name="sc.Environment" value="LOCAL" />

The following default environment styles are provided:

  • LOCAL
  • DEV
  • TEST
  • UAT
  • PREPROD
  • PROD
  • ANIMATED
  • RAINBOW

The last 2 are just for fun and to show some possibilities, take a look and have a play – CSS3 gives us gradients, animations and transforms.

The default stylesheets can be found in /sitecore modules/EnvironmentStyler/ folder. You can update the existing ones or add your one for your specific environments, just add them to the module folder and make sure the filename matches the same format environment-override-$(sc.Environment).css:

<setting name="FS.EnvironmentStyler.CssFile" value="/sitecore modules/EnvironmentStyler/environment-override-$(sc.Environment).css" />

You don’t need this on the CD servers. Either delete the config file or deploy/enable SC.EnvironmentStyler.WebCD.config.disabled.

Screenshots

Environment Styler - Login Screen

Environment Styler - Ribbon Header

Download

You can take a look at the code and find an installable Sitecore package in this Github repo: https://github.com/jammykam/Environment-Styler-for-Sitecore

Or download it from the Sitecore Marketplace

Or add it to your project as a NuGet reference:

PM> Install-Package Sitecore.Environment.Styler


Big thanks to Michael West and Pete Navarra for testing and providing feedback.

Leave a comment