<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Dave Talks.]]></title><description><![CDATA[Sitecore and other ramblings]]></description><link>https://daveblog.azurewebsites.net/</link><generator>Ghost 0.11</generator><lastBuildDate>Sun, 05 Apr 2026 21:11:12 GMT</lastBuildDate><atom:link href="https://daveblog.azurewebsites.net/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Decomposing a Sitecore monolith to microservices - the experience so far and what we’ve learnt.]]></title><description><![CDATA[<p>Over a year ago we embarked on a journey to re-architect a large Sitecore monolith.</p>

<p>Before we debate the definition of a microservice I should clarify - we are actually decomposing to small(<em>ish</em>) vertical web applications bounded by cohesive business functionality. That title didn’t have quite the same</p>]]></description><link>https://daveblog.azurewebsites.net/decomposing-a-sitecore-monolith-to-microservices-the-experience-so-far-and-what-weve-learnt/</link><guid isPermaLink="false">981f6a30-64c7-4feb-b1e6-ed3e555d34ea</guid><dc:creator><![CDATA[Dave Leigh]]></dc:creator><pubDate>Sun, 20 Jun 2021 17:52:29 GMT</pubDate><content:encoded><![CDATA[<p>Over a year ago we embarked on a journey to re-architect a large Sitecore monolith.</p>

<p>Before we debate the definition of a microservice I should clarify - we are actually decomposing to small(<em>ish</em>) vertical web applications bounded by cohesive business functionality. That title didn’t have quite the same ring to it!</p>

<p>We look to utilise the benefits of a microservice architecture but do accept some constraints.</p>

<h3 id="whydidwedoit">Why did we do it?</h3>

<p>Our Sitecore monolith has grown large and cumbersome over many years of optimising for time to market rather than the long term health of the platform. </p>

<p>It’s easy to jump to microservices and not all monoliths are a bad design choice, however ours has grown to exhibit two key constraints. </p>

<ul>
<li><p>The first is how well the application supports our ability to deliver new functionality to customers. We must release everything together as one large unit of deployment. This process is slow and therefore we tend to release infrequently.</p></li>
<li><p>The other constraint is development scale. As teams write more code the solution becomes more difficult to maintain, and cost of change gradually increases. Importantly we limit the number of teams who are able to work in parallel.</p></li>
</ul>

<h3 id="whatwerewelookingtoachieve">What were we looking to achieve?</h3>

<p>We looked to solve these problems by unlocking two main capabilities of the platform:</p>

<ul>
<li>Move towards smaller, quicker, incremental isolated units of deployment.</li>
<li>Partition the platform so that cross functional teams are able to work and release code independently of each other. </li>
</ul>

<h3 id="thedistributedmonolithantipattern">The distributed monolith anti-pattern</h3>

<p>Team autonomy is crucial in a distributed architecture. A release should have no impact on other teams. If we need to release Application B due to updates to Application A we expose ourselves to the drawbacks of the original monolith but also have all the challenges of a more distributed architecture.</p>

<h3 id="howquicklydowestartrealisingourobjectives">How quickly do we start realising our objectives?</h3>

<p>We use new business initiatives to determine which areas of the application to partition. In deciding which area of the platform to focus on we then determine how to partition, i.e. how big should each application be, which business functionality should each cover. </p>

<p>Usually we would partition by <a href="https://martinfowler.com/bliki/BoundedContext.html">bounded context</a> unless there was a technical capability we were looking to leverage for a particular application. For example an advantage of smaller units is that each application is independently scalable and fault tolerant. We might decide high volume areas of the site should be isolated. It can also be prudent to consider how often different areas of the site change, and which areas change together.</p>

<p>It is not necessary to decompose the whole monolith to start realising value from the new architecture. After releasing one or two applications in production we were able to assign ownership to individual teams. Applications are able be released quickly and independently of the monolith. Teams are able to make incremental updates to those applications.</p>

<p>In starting to realise these outcomes we allow ourselves time to iterate and learn. The architecture can evolve and we can improve based on past learnings. </p>

<p>We are able to further decompose (a now smaller monolith) when the business is ready, again using business initiatives as a catalyst to break out new applications.</p>

<h3 id="whatdoesthislooklike">What does this look like?</h3>

<p>There are a couple of approaches to decomposition, we opted for a common technique known as the <a href="https://martinfowler.com/bliki/StranglerFigApplication.html">strangler pattern</a>.</p>

<p>Effectively the original monolith remains unchanged at first. We build new applications in separate codebases and utilise a reverse proxy (CDN in our case) to redirect requests to the new application. The proxy also provides a convenient mechanism for rollback and risk management via traffic splitting.</p>

<p>Each vertical slice of functionality has two key components: </p>

<ul>
<li><p>First a micro frontend utilising a <a href="https://www.contentful.com/r/knowledgebase/what-is-headless-cms/">Headless CMS</a> (Sitecore JSS, which was the enabler for this architecture). </p></li>
<li><p>Each Micro frontend is served by a lightweight Restful API (effectively a <a href="https://samnewman.io/patterns/architectural/bff/">BFF</a> variation) and proxies commands and queries into backend service layers (not maintained by our teams). </p></li>
</ul>

<p>Continuous deployment and automation are the backbone of this architecture.</p>

<p><img src="https://i.ibb.co/qgWTqkv/then.png" alt="architecture then">
<img src="https://i.ibb.co/GCpxY6J/now.png" alt="architecture now"></p>

<p>Notice those unpleasant red lines? Dependencies on the monolith are not ideal, but we try to treat Sitecore as a service (headless CMS) in this model. This is one of the constraints vs true microservices and something we will discuss next.</p>

<h3 id="whatwelearnt">What we learnt</h3>

<p>No architecture is perfect, we make a compromise somewhere and hope to not close the door on modifying the direction based on what we learn. </p>

<p>In this scenario we have both the challenge which comes with a distributed platform whilst also working around some of the constraints that Sitecore forces upon us, most notably the shared database. In a distributed architecture a shared database is usually a big red flag as it couples applications together. True independence and isolation are much more difficult to achieve.</p>

<p>Sitecore is the constraint here, however there are short and long term techniques we can leverage to solve this problem. </p>

<p>Short term we did a few things to enable release independence:</p>

<ul>
<li>Ensure all content updates are backwards compatible.</li>
<li>Partitioned the content so each app owned an area of the Sitecore tree. We have an automated content deployment process and run automated integration tests on a staging environment.</li>
<li>To expose new data to the frontend applications via JSS’s Layout Service API you usually need to write code in your Sitecore solution (the monolith in the visualisation above). This obviously creates a release dependency on the monolith. To solve this we created an dynamic content based resolver more powerful and flexible than those Sitecore provides out of the box. There are also options to leverage GraphQL.</li>
</ul>

<p>Longer term we have other options too. </p>

<p>Applications which don’t need to be content editable (the content changes infrequently) are able to consume their content from another source if it makes sense to simplify in this manner. We can also look to a future Sitecore SaaS offering (potentially looking to move further towards a more <a href="https://machalliance.org/">MACH</a> esque architecture), utilise techniques such as <a href="https://jamstack.org/">Static Site Generation</a>, or a content cache close to the application. Any techniques we utilise can vary per app based on the context and business capability exposed via that application.</p>

<p><img src="https://i.ibb.co/f2XXhC3/next.png" alt="Next architecture"></p>

<h3 id="otherchallenges">Other challenges</h3>

<p>There are truly shared areas of concern in both API and Frontends such as authorisation which need consideration.</p>

<p>There are challenges in ensuring areas of the code and patterns remain consistent where you want consistency between codebases and therefore between teams. In a true microservice ecosystem autonomy would usually include teams having ownership of technology choices.</p>

<p>The frontend architecture becomes more complex. I will likely follow up with another post on frontend architecture as it can be easy to become stuck. There will be code you will want to package and version to share between apps which can be a challenge when a primary concern is ensuring applications remain loosely coupled. There will also be UI that teams will want to reuse between apps.</p>

<p>It’s all too easy to abstract too early and bake the business logic of multiple applications into a UI component. Where do you draw the line between <a href="https://anthonysciamanna.com/2018/07/28/the-dry-principle-and-incidental-duplication.html">DRY</a> and prudent duplication? One approach can be to utilise atomic design principles and treat shared UI as ‘dumb’ Lego which can be consumed by applications who then bake in their own domain logic within the application.</p>

<p>Other areas of concern are source control, continuous integration and deployment (A <a href="https://www.docker.com/resources/what-container">container</a> based deployment strategy can be extremely powerful). There is value in utilising the <a href="https://www.atlassian.com/git/tutorials/monorepos">Monorepo</a> pattern but also reasons why this approach might not be right for your context. </p>

<p>If you got this far I hope some of this was useful, the journey for this architecture is far from over.</p>]]></content:encoded></item><item><title><![CDATA[Experimenting with Kubernetes RBAC on Windows 10 with docker desktop]]></title><description><![CDATA[<p>This started as a dump of my notes exploring this but thought it might be useful for others.</p>

<p><a href="https://www.docker.com/products/docker-desktop">Docker desktop</a> is a quick and easy way to run a Kubernetes cluster locally on Windows 10 allowing Windows users to experiment with Kubernetes. If you have <a href="https://docs.docker.com/docker-for-windows/wsl/">Windows subsystem for Linux</a> installed</p>]]></description><link>https://daveblog.azurewebsites.net/experimenting-with-kubernetes-rbac-on-windows-10-with-docker-desktop/</link><guid isPermaLink="false">20836dc0-a245-4b22-80d4-f0b5e8553626</guid><dc:creator><![CDATA[Dave Leigh]]></dc:creator><pubDate>Sat, 12 Dec 2020 13:55:15 GMT</pubDate><content:encoded><![CDATA[<p>This started as a dump of my notes exploring this but thought it might be useful for others.</p>

<p><a href="https://www.docker.com/products/docker-desktop">Docker desktop</a> is a quick and easy way to run a Kubernetes cluster locally on Windows 10 allowing Windows users to experiment with Kubernetes. If you have <a href="https://docs.docker.com/docker-for-windows/wsl/">Windows subsystem for Linux</a> installed you can use this as the docker backend which provides better performance than Hyper-V.</p>

<p>Kubernetes RBAC (Role based access control) is a Kubernetes resource which allows us to define policies to determine which actions specific users are allowed to execute at cluster and namespace level. e.g pod creation.</p>

<p>If you are not familiar with RBAC there are many fantastic resources which explain RBAC fundamentals which are worth reading via a quick Google.</p>

<h4 id="settingupauserandauthenticatingwithkubernetes">Setting up a user and authenticating with Kubernetes</h4>

<p>Users cannot be added to a cluster through an API call, so user accounts have to be externally managed and then authenticated by the cluster. There are a few methods available to <a href="https://kubernetes.io/docs/reference/access-authn-authz/authentication/">authenticate with the cluster</a>. </p>

<p>I decided to focus on X509 client certificates. We first create the private key for a user and a certificate signing request. We ask the cluster's CA to certify the certificate. We then authenticate using the signed certificate. </p>

<p><strong>Create the certificate signing request</strong></p>

<p>I did this in Ubuntu via WSL2.</p>

<pre><code>openssl genrsa -out myuser.key 2048  
</code></pre>

<pre><code>openssl req -new -key myuser.key -out myuser.csr -subj "/CN=myuser/O=myusergroup"  
</code></pre>

<p>Next we ask the Kubernetes API to sign the CSR.</p>

<p>Create a cert-sign-request.yaml</p>

<pre><code class="language-apiVersion: certificates.k8s.io/v1beta1">kind: CertificateSigningRequest  
metadata:  
  name: myuser
spec:  
  request: &lt;TO REPLACE&gt;
  usages: ['digital signature', 'key encipherment',
    'client auth']
</code></pre>

<p>Head back into Linux (WSL) to create the Request string (&lt; TO REPLACE>). There are presumably methods to do this all in windows but this was easiest for me.</p>

<pre><code>cat myuser.csr | base64 | tr -d '\n'  
</code></pre>

<p>Back in windows:</p>

<pre><code>kubectl apply -f .\cert-sign-request.yml  
kubectl certificate approve myuser  
</code></pre>

<p>Next we need to extract the base64 encoded signed certificate from the Kubernetes API.</p>

<pre><code>kubectl get csr myuser -o jsonpath='{.status.certificate}'  
</code></pre>

<p>In windows copy this into a txt file and generate the crt.</p>

<pre><code>certutil -decode cerbase64.txt myuser.crt  
</code></pre>

<p>To authenticate with Kubernetes as myuser we need 2 things, the crt we generated above and also the key file which if you did the same as me was created on Linux. If using WSL2 you can locate the key file easily enough here: <code>\\wsl$\&lt;distro&gt;\home\&lt;me&gt;</code></p>

<h4 id="impersonatingournewuser">Impersonating our new user</h4>

<p><code>kubectl config view</code> will show we are currently authenticated as admin the docker-desktop user.</p>

<p>To add the new user we add a new context with the credentials.</p>

<pre><code>kubectl config set-credentials myuser --client-key myuser.key --client-certificate myuser.crt --embed-certs

kubectl config set-context myuser --cluster docker-desktop --user myuser  
</code></pre>

<p>We can now run commands as our user to test RBAC:</p>

<pre><code>kubectl --context=myuser get pods  
</code></pre>

<p>You will see an error - as the user has no permissions.</p>

<h4 id="creatingrbacpolicies">Creating RBAC policies</h4>

<p>To test RBAC let's create a simple nginx pod definition ready for later - <strong>nginx-pod.yaml</strong>:</p>

<pre><code>apiVersion: v1  
kind: Pod  
metadata:  
  name: nginx-pod
  labels:
    name: nginx-pod
spec:  
  containers:
  - name: nginx-pod
    image: nginx
    ports:
    - containerPort: 8080
</code></pre>

<p>Running <code>kubectl apply --context=myuser -f ./nginx-pod.yaml</code> will throw a permissions error.</p>

<p>Let's create an editor role which will allow myuser permissions to create this pod - <strong>pod-editor-role.yaml</strong></p>

<pre><code>kind: Role  
apiVersion: rbac.authorization.k8s.io/v1  
metadata:  
  name: pod-editor
rules:  
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["create", "get", "list", "watch"]
</code></pre>

<pre><code>kubectl apply -f pod-editor-role.yaml  
</code></pre>

<p>To assign the member to the role we create a role binding - <strong>myuser-editor-binding.yaml</strong>:</p>

<pre><code>kind: RoleBinding  
apiVersion: rbac.authorization.k8s.io/v1  
metadata:  
  name: myuser-editor
subjects:  
- kind: User
  name: myuser
  apiGroup: rbac.authorization.k8s.io
roleRef:  
  kind: Role
  name: pod-editor
  apiGroup: rbac.authorization.k8s.io
</code></pre>

<pre><code>kubectl apply -f myuser-editor-binding.yaml  
</code></pre>

<p>Now if we create the pod as myuser - success!</p>

<pre><code>kubectl apply --context=myuser -f ./nginx-pod.yaml  
</code></pre>

<p>This is really scratching the surface of RBAC and not meant to be a  complete overview. Again our friend Google produces many fantastic resources if you wish to get stuck in furthur. </p>]]></content:encoded></item><item><title><![CDATA[Using VueJs in Sitecore and Asp.Net MVC razor pages (Part 2)]]></title><description><![CDATA[<p>A few months ago I created a prototype to explore using VueJs in our existing Sitecore application. Unfortunately JSS was not an option for us. I didn't take the prototype further as the project direction shifted but recently I've needed to revisit the approach. In this post I will take</p>]]></description><link>https://daveblog.azurewebsites.net/using-vuejs-in-sitecore-and-asp-net-mvc-razor-pages/</link><guid isPermaLink="false">4c15b67b-3ab3-4505-bf49-623ebcdf0fe9</guid><dc:creator><![CDATA[Dave Leigh]]></dc:creator><pubDate>Sun, 23 Jun 2019 11:08:45 GMT</pubDate><content:encoded><![CDATA[<p>A few months ago I created a prototype to explore using VueJs in our existing Sitecore application. Unfortunately JSS was not an option for us. I didn't take the prototype further as the project direction shifted but recently I've needed to revisit the approach. In this post I will take the previous prototype much further and discuss in more detail the options available.</p>

<h3 id="theproblem">The problem</h3>

<p>You'd think it would be fairly straightforward to use VueJs and Sitecore together. However the complexity is in splitting the template from the component definition. To render fields from Sitecore (<strong>and to enable page editor</strong>), we need to have our markup in .cshtml files which means the template cannot live in a .vue file along with the Javascript code.</p>

<h2 id="possiblesolutions">Possible solutions</h2>

<blockquote>
  <p>Caveat - As per the last post this is exploratory code, mainly because I couldn't find much help online to solve this problem. The solutions outlined here though are much more complete than the previous post which I received quite a few questions about - so hopefully more to get started with now!</p>
</blockquote>

<p>Note: I have updated to Typescript in these examples and used the webpack config from <a href="https://github.com/microsoft/TypeScript-Vue-Starter">https://github.com/microsoft/TypeScript-Vue-Starter</a>. I will Provide links to my github with all the code from these examples at the end of the post.</p>

<h2 id="option1xtemplates">Option 1 - X-Templates</h2>

<p>The previous post focused on X-Templates as a solution to the problem as these give us separation of markup and component code. <a href="https://vuejs.org/v2/guide/components-edge-cases.html#X-Templates">https://vuejs.org/v2/guide/components-edge-cases.html#X-Templates</a></p>

<p>The big problem with the X-Template solution from the previous post is that if you have multiple of the same component on a page the first variant will be rendered for each instance. (As both have the same Id).</p>

<p>Here is a solution to that:</p>

<p><strong>app.ts</strong></p>

<pre><code class="language-import Vue from " vue";"="">/* Components */
import HelloWorld from "./Components/HelloWorld/hello-world";

new Vue({  
    el: `#app`,
    components: {
        HelloWorld
    }
});
</code></pre>

<p><strong>HelloWorld.ts</strong></p>

<pre><code>import Vue, { VNode } from "vue";  
import { Component, Mixins, Prop } from "vue-property-decorator";

@Component({
    name: "hello-world"
})
export default class HelloWorld extends Vue  
{
    @Prop({default: "Example"})
    testprop!: string;

    mounted = () =&gt; {
        console.log("Props: " + this.testprop);
    }

    data = () =&gt;
    {
        return {
            message: "Hello from component data!"
        };
    }

    methods = {
        testClick: () =&gt; { console.log("I have been clicked!"); }
    };

    template: string = "#hello-world-template";
    static renderIndex: number = -1;

    render(createElement): VNode {
        HelloWorld.renderIndex += 1;
        this.template = `#hello-world-template_${HelloWorld.renderIndex}`;
        return createElement(this);
    }
}
</code></pre>

<p><strong>HelloWorld.cshtml</strong></p>

<pre><code>@model MyNamespace.MyModel

&lt;hello-world testprop="This is a message from props"&gt;&lt;/hello-world&gt;

&lt;!-- RenderIndex needs to come from your c# controller --&gt;  
&lt;script type="text/x-template" id="hello-world-template_@Model.RenderIndex"&gt;  
    &lt;div&gt;
        &lt;h1&gt;@Sitecore.FieldFor(m =&gt; m.MyField)&lt;/h1&gt;
        &lt;div @@click="testClick()" class="container"&gt;
            {{ message }}
        &lt;/div&gt;
    &lt;/div&gt;
&lt;/script&gt;
</code></pre>

<p><strong>Layout.cshtml</strong></p>

<pre><code>...
&lt;body&gt;  
    &lt;div class="main" id="app"&gt;
        @Html.Sitecore().Placeholder("full-screen")
    &lt;/div&gt;
    &lt;script type="text/javascript" src="~/Scripts/bundle.js"&gt;&lt;/script&gt;
&lt;/body&gt;  
...
</code></pre>

<p>There is one last problem to this approach. The x-template definition needs to live after the closing tag of the Vue app i.e <code>&lt;div id="app"&gt;</code> or you will get the following error: <em>Property or method "message" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property</em></p>

<p>(If you want to know why this happens: <a href="https://stackoverflow.com/questions/49193378/why-does-position-of-x-template-section-matter-for-vue-templates-to-work-with-da">https://stackoverflow.com/questions/49193378/why-does-position-of-x-template-section-matter-for-vue-templates-to-work-with-da</a>)</p>

<p>You could easily use a simple html helper to poke the x-template script within each cshtml file to the end of the layout page.</p>

<h2 id="option2usingslots">Option 2 - Using slots</h2>

<p>Interestingly a buddy of mine, Chris Howson, also had this problem to solve and uses a clever approach utilising slots (<a href="https://vuejs.org/v2/guide/components-slots.html#Scoped-Slots">https://vuejs.org/v2/guide/components-slots.html#Scoped-Slots</a>) to solve the problem. I'll link to Chris' blog post about this once he's had time to create it.</p>

<p>This is arguably a cleaner solution than the x-template approach. The only downsides are the extra code you need to write in render and some people might argue using slots in this way is a little strange. For me, it's a great solution.</p>

<p><strong>app.ts</strong></p>

<pre><code class="language-import Vue from " vue";"="">/* Components */
import HelloWorld from "./Components/HelloWorld/hello-world";

new Vue({  
    el: `#app`,
    components: {
        HelloWorld
    }
});
</code></pre>

<p><strong>HelloWorld.ts</strong></p>

<pre><code>import Vue from "vue"  
import { Component, Mixins, Prop } from "vue-property-decorator";

@Component({
    name: "hello-world"
})
export default class HelloWorld extends Vue  
{
    @Prop({default: "Example"})
    testprop: string;

    mounted() {
        console.log("Props: " + this.testprop);
    }

    message: string = "Hello from component data!";

    methods = {
        testClick() { console.log("i have been clicked!"); }
    };

    render() {
        return (&lt;any&gt;this.$scopedSlots).default({
            message: this.message,
            testClick: this.methods.testClick
        });
    }
}
</code></pre>

<p><strong>HelloWorld.cshtml</strong></p>

<pre><code>&lt;hello-world testprop="This is a message from props" v-slot="data"&gt;  
    &lt;div @@click="data.testClick()"&gt;
        &lt;h1&gt;@Sitecore.FieldFor(m =&gt; m.MyField)&lt;/h1&gt;
        &lt;div&gt;{{ data }}&lt;/div&gt;
    &lt;/div&gt;
&lt;/hello-world&gt;  
</code></pre>

<h2 id="githubexamples">Github examples</h2>

<p>I'll update this post with links to github code containing even more complete examples shortly. Hopefully the code above gives some fresh ideas for tackling this problem.</p>]]></content:encoded></item><item><title><![CDATA[Validate your Sitecore publishes with Cypress]]></title><description><![CDATA[<h3 id="theproblem">The problem</h3>

<p>It seems obvious but you really want to avoid a content change taking down your website.</p>

<p>No matter how well you code the site, null checking, version checking your items etc.. if a rouge item is published, or key data unpublished then your whole site could grind to</p>]]></description><link>https://daveblog.azurewebsites.net/validate-your-sitecore-publishes-with-cypress/</link><guid isPermaLink="false">c04b4783-f19c-4510-8e3a-33874950d7da</guid><dc:creator><![CDATA[Dave Leigh]]></dc:creator><pubDate>Thu, 03 Jan 2019 08:34:04 GMT</pubDate><content:encoded><![CDATA[<h3 id="theproblem">The problem</h3>

<p>It seems obvious but you really want to avoid a content change taking down your website.</p>

<p>No matter how well you code the site, null checking, version checking your items etc.. if a rouge item is published, or key data unpublished then your whole site could grind to a halt.</p>

<p>There are a few solutions to this such as:</p>

<ul>
<li>Workflow. - Of course put all/key content through an approval process. This can be a great solution.</li>
<li>Staging publishing target. - This can work nicely alongside workflow, ensure all content is checked on a non public facing publishing target first.</li>
</ul>

<h4 id="anotheroption">Another option</h4>

<p>Another option which can work standalone or alongside the ideas above and also helps mitigate human error, such as content just being approved without being checked is to run some UI tests on publish.</p>

<h4 id="testsonpublish">Tests on publish</h4>

<p>So the idea is actually rather straightforward. </p>

<ul>
<li>Content editor publishes to stage.</li>
<li>The publish action invokes a background Cypress (JavaScript UI test runner) job (<a href="http://cypress.io">http://cypress.io</a>) to run some UI tests on your staging target. These tests can check key journeys of your website are still functional. I.e Homepage is up and displays correct content, the checkout is working as expected.</li>
<li>When the user wants to publish to live they see a status of the last test run which gives them confidence in the publish. If the test run failed, then don't publish.</li>
</ul>

<p><img src="https://raw.githubusercontent.com/daveaftershok/sitecore-test-run-on-publish/master/result.gif" alt="example"></p>

<h4 id="howcaniachievethis">How can I achieve this?</h4>

<p>There are many ways to build this. In my prototype I combined a node API server with a small update to the publish dialog. I'm sure it can be improved upon but it works fairly nicely.</p>

<h5 id="thenodeserver">The node server</h5>

<p><a href="https://github.com/daveaftershok/cypress-node-api-windows">https://github.com/daveaftershok/cypress-node-api-windows</a></p>

<p>Once up and running exposes a number of endpoints to execute Cypress tests. If you don't know how to use Cypress it is great piece of software please try it out.</p>

<h5 id="thepublishscript">The publish script</h5>

<p><a href="https://github.com/daveaftershok/sitecore-test-run-on-publish">https://github.com/daveaftershok/sitecore-test-run-on-publish</a></p>

<p>Feel free to edit this code as you wish.</p>]]></content:encoded></item><item><title><![CDATA[How do you estimate the effort of a Sitecore upgrade?]]></title><description><![CDATA[<p>We are in the process of, or have recently completed a number of Sitecore upgrades and pooled our knowledge.</p>

<p>In this post I will share things to consider when planning an upgrade and also talk about the process we went through to upgrade and deploy a new version of Sitecore</p>]]></description><link>https://daveblog.azurewebsites.net/our-sitecore-7-9-upgrade-live-deployment-process/</link><guid isPermaLink="false">32668302-6d02-4e00-aa55-5c450065a62f</guid><dc:creator><![CDATA[Dave Leigh]]></dc:creator><pubDate>Thu, 22 Nov 2018 13:42:22 GMT</pubDate><content:encoded><![CDATA[<p>We are in the process of, or have recently completed a number of Sitecore upgrades and pooled our knowledge.</p>

<p>In this post I will share things to consider when planning an upgrade and also talk about the process we went through to upgrade and deploy a new version of Sitecore to production.</p>

<h3 id="planningahead">Planning ahead</h3>

<p>Estimating a Sitecore upgrade can be a difficult task. The effort required can vary significantly based on the complexity of your solution. Below are some things to consider when estimating the effort and time an upgrade will take. </p>

<ul>
<li>What version of Sitecore are you upgrading from and what version are you upgrading to?
Have you mapped out what the upgrade process will be? Can you use the Upgrade migration tool? (<em>more on this later</em>)  </li>
<li>How much custom Sitecore code is there in the solution?</li>
<li>How many support patches are there in the solution?</li>
<li>How do you perform a full regression test? What is the testing effort?</li>
<li>Do you have adequate test coverage to be confident in the solution post upgrade?</li>
<li>How complex is the solution (i.e more things can break, higher likelihood more bugs / issues will be found)</li>
<li>What is the current state of the Web and Sitecore configs?</li>
<li>How many non production environments will you need to upgrade and deploy the new version to?</li>
<li>What does the path to live look like?</li>
<li>Do you use any external modules? For example XDB, WFFM, EXM - and what is the upgrade path for these modules?</li>
<li>What is the state of package dependencies within the solution? i.e Do different projects have different versions of the same library?</li>
<li>How will you develop new functionality alongside performing an upgrade? - The elapsed time between first creating your upgrade code branch to actually deploying the upgraded solution to production will likely be a number of months.</li>
</ul>

<h3 id="ourprocess">Our process...</h3>

<p>Here are some things we did and learnt whilst upgrading from Sitecore 7.2 to 9.</p>

<h4 id="reworkingtheconfigs">Reworking the configs</h4>

<p>As we were working with a fairly old solution before we did anything upgrade-wise we spent about 2-3 weeks reworking our configs. This involves moving all changes to transforms and Sitecore patch files leaving us with out of the box Sitecore and web configs.</p>

<blockquote>
  <p>With any new projects I would suggest doing this from the start.</p>
</blockquote>

<p>We used file comparison tools to compare the 'compiled' Sitecore config (<em>/sitecore/admin/showconfig.aspx</em>) before and after the changes were made. Even after doing this we missed a few bits so be wary testing effort is still required. There are also Sitecore modules to help you do this e.g.: <a href="https://marketplace.sitecore.net/modules/sitecore_configbuilder.aspx">https://marketplace.sitecore.net/modules/sitecore_configbuilder.aspx</a></p>

<p>Consider contingency time to fix any issues which might arise.</p>

<blockquote>
  <p>As a side note to further improve your config setup Sitecore 9 now supports rules based configuration - more about that here: <a href="https://jammykam.wordpress.com/2017/10/17/rules-based-configuration/">https://jammykam.wordpress.com/2017/10/17/rules-based-configuration/</a></p>
</blockquote>

<h4 id="theexpressmigrationtoolandhowwedealtwithconfigsduringtheupgrade">The express migration tool and how we dealt with configs during the upgrade</h4>

<p>In the past the way to upgrade Sitecore was jumping from version to version, with all sorts of fun along the way. Sure the upgrade path allowed you to skip a few versions to get to your target but it was still a painful process. </p>

<p>The express migration tool is much better. It migrates your content from any version since 6.6 to version 9 at the time of writing. Check latest compatibility here: <a href="https://kb.sitecore.net/articles/400952">https://kb.sitecore.net/articles/400952</a></p>

<p>It worked really well for us. However it is not perfect - for example it did not migrate some renderings correctly which resulted in broken presentation details which we only noticed during testing the site. This can be fixed with content packages / unicorn etc (or in our case <a href="https://blog.boro2g.co.uk/sinj-scripted-sitecore-changes/">SINJ scripts</a> which are run after the site has been upgraded.</p>

<p>The tool can also migrate configuration... which we chose not to do. Instead we upgraded our configs manually, which after reworking (above) was not difficult.</p>

<p>As we were not utilizing any additional modules we were able to disable most of the provided patch files in the App_Config folder.</p>

<blockquote>
  <p>To get a better feel for the effort required one thing we like to do right at the start is a quick and dirty upgrade to get a feel for the sort of problems we might encounter when we do the real thing and to answer some of the bulleted points listed above.</p>
</blockquote>

<h4 id="stateofthesolutionandsupportpatches">State of the solution and support patches</h4>

<p>Luckily we have most of our custom code well documented. You will need to factor in time for fixing any problems that might arise in custom Sitecore code on the newest version of Sitecore. e.g custom pipelines, handlers, helpers etc.  </p>

<p>We also document support patches added to the solution. It's easy to forget why Sitecore.Support.12345.dll lives in your bin directory and what problem it is solving! Again validating these problems are still fixed after upgrade needs to happen. We were able to remove nearly all our support patches as the bugs they were implemented to fix were resolved in the newer version of Sitecore.</p>

<p>You might also find after upgrading you have dependency hell in terms of referenced assemblies not playing well with each other. This can take an age to fix.</p>

<h3 id="upgradingnonprodenvironments">Upgrading non prod environments</h3>

<p>You will need to factor in time for upgrading non production environments. Perhaps you will need to spin up a second QA environment for Sitecore 9 testing as your original QA environment is needed for ongoing development. What about CI and CD - is this a factor? Do you need to run automated tests against 2 versions of Sitecore now until you go live?</p>

<h4 id="testing">Testing</h4>

<p>I've mentioned testing quite a bit.. and for good reason. It's so easy to underestimate the testing effort that goes into an upgrade. </p>

<p>We have a whole suite of automated UI tests covering most of the business use cases which we run overnight. This really helps flush out any upgrade issues. We also have a super QA team who manually test the site and specifically the CMS itself which is not covered by our tests. </p>

<p>One example of something which caused us problems was that the way Sitecore stores raw time changed which caused some of the code to become unhappy. Expect small things like this which can crop up and do need identifying and fixing.</p>

<h4 id="othermodules">Other modules</h4>

<p>We were lucky. No XDB, no WFFM and no EXM. This makes the upgrade process much easier.</p>

<p>If you do have other modules to upgrade factor in time for this. It's easy to underestimate the complexity of upgrading these modules and identifying and fixing any issues than might occur. </p>

<p>XDB is notoriously hard to upgrade.</p>

<p>EXM and WFFM - You may have to go through lots of different install steps although the express migration tool does state it can help with WFFM. </p>

<p>This can be painful and time consuming. </p>

<p>Also consider older versions of WFFM are not supported in 9.1.</p>

<h3 id="thelivedeployment">The live deployment</h3>

<p>For zero downtime we utilize blue green deployments. We spun up new Sitecore 9 stacks and then switched traffic via Akamai after we've completed our 'offline' testing against the new stacks.</p>

<p>In a normal deployment we have a short content freeze of say 1 hour during which we backup the databases and use these backups in creating the new environments.</p>

<p>When migrating from Sitecore 7 to 9 we have one major change from our standard release process - the Sitecore 7 database needs updating to Sitecore 9.</p>

<p>We agreed a content freeze from 4pm the day before the release. </p>

<p>We created a new EC2 instance to perform the migration using the express migration tool via a number of custom powershell scripts. It time we needed to migrate a database from 7 to 9 we simply re-run these scripts changing a few params which determine the environment to upgrade.</p>

<p><strong>The process worked like this:</strong></p>

<ul>
<li>Powershell script is run which creates a backup of the live Sitecore databases (core and master) at 4pm.</li>
<li>Next it restores these databases to our upgrade box.</li>
<li>We then upgrade these databases using the Express migration tool.</li>
<li>We have a blank Sitecore 9 instance installed onto our upgrade box. We login to Sitecore and perform a full site publish.</li>
<li>We push the new migrated databases to S3 where they can be picked up by our deployment process when spinning up the new prod environment.</li>
</ul>]]></content:encoded></item><item><title><![CDATA[Using VueJs in Sitecore]]></title><description><![CDATA[<h4 id="updatejuly2019">Update July 2019</h4>

<p>I've had a lot of questions about this so have written a follow up to this post you can find here: <a href="http://www.daveleigh.co.uk/using-vuejs-in-sitecore-and-asp-net-mvc-razor-pages/">http://www.daveleigh.co.uk/using-vuejs-in-sitecore-and-asp-net-mvc-razor-pages/</a></p>

<hr>

<h3 id="background">Background</h3>

<p>We have a very large, (and now pretty old!) enterprise web application utilizing Sitecore MVC and Angular <strong>1</strong>.</p>

<p>Over</p>]]></description><link>https://daveblog.azurewebsites.net/using-vuejs-in-sitecore/</link><guid isPermaLink="false">ee122c15-1538-407b-9f1a-989dd0d7b27d</guid><dc:creator><![CDATA[Dave Leigh]]></dc:creator><pubDate>Mon, 05 Nov 2018 12:00:00 GMT</pubDate><content:encoded><![CDATA[<h4 id="updatejuly2019">Update July 2019</h4>

<p>I've had a lot of questions about this so have written a follow up to this post you can find here: <a href="http://www.daveleigh.co.uk/using-vuejs-in-sitecore-and-asp-net-mvc-razor-pages/">http://www.daveleigh.co.uk/using-vuejs-in-sitecore-and-asp-net-mvc-razor-pages/</a></p>

<hr>

<h3 id="background">Background</h3>

<p>We have a very large, (and now pretty old!) enterprise web application utilizing Sitecore MVC and Angular <strong>1</strong>.</p>

<p>Over the years Angular has worked well for us in some areas but has shown weaknesses in others. Some of the side effects from it's 2 way databinding, it's global state management and its over complicated digest system are just a few headaches we've head. This leads to the codebase being relatively complicated for new team members. Working on a team which adds new developers frequently Angular works but it could be better.</p>

<blockquote>
  <p>Caveat to the above, using a combination of Typescript with Angular has really helped us, and abstracting as much away from the angular layer as possible also helps simplify things</p>
</blockquote>

<h3 id="vuejs">VueJs.</h3>

<p>VueJs has a fantastic feel to it. it is an easy to pick up, intuitive component based Javascript framework. It feels very much like Angular to use, it's syntax is very similar but overall Vue is much less opinionated. It has improved many of the pain points that I found problematic in Angular and has also introduced concepts seen in React such as the virtual DOM. In terms of performance it is also much better (Angular suffers from an incurable performance issue, as the page gets larger and larger it quickly becomes slower and slower.)</p>

<p>Vue enforces a one way data flow between components meaning there is only one source of truth and global state is managed via a Redux type pattern - Vuex.</p>

<h4 id="whynotangular2">Why not Angular 2+?</h4>

<p>I'm sure Angular 2 is also a good option but it's something I haven't really focussed any time on. However as a team we are also exploring Angular 2+.</p>

<h4 id="whataboutreact">What about React?</h4>

<p>Using React with sitecore is certainly doable. The main complexity arises when you need to solve the issue of combining JSX and sitecore field renderers. </p>

<p>There are a few blog posts which provide some answers... and of course you could also use JSS.</p>

<p><a href="https://sitecoreblog.alexshyba.com/sitecore-and-react-how-hard-can-it-be/">https://sitecoreblog.alexshyba.com/sitecore-and-react-how-hard-can-it-be/</a></p>

<p><a href="http://sitecorepro.blogspot.com/2017/08/sitecore-and-react-simple-integration.html">http://sitecorepro.blogspot.com/2017/08/sitecore-and-react-simple-integration.html</a></p>

<p><a href="https://www.sitecorenutsbolts.net/2017/07/04/Sitecore-React-Getting-Started/">https://www.sitecorenutsbolts.net/2017/07/04/Sitecore-React-Getting-Started/</a></p>

<h4 id="whataboutjss">What about JSS</h4>

<p>If you can use JSS it is certainly be worth exploring. It will, in Sitecore 9.1 come out of beta and looks fantastic.</p>

<p>However there are many scenarios where you might not want to use JSS and ours was one of them.</p>

<p>This isn't a JSS post, if you want more info about JSS - <a href="http://jss.sitecore.net">http://jss.sitecore.net</a>.</p>

<h2 id="integratingvuejsintoasitecoresolution">Integrating Vuejs into a Sitecore solution</h2>

<p>A caveat.. I've used Vue many times before but never at enterprise scale so this post really documents a prototyping effort. </p>

<p>These are the main problems I wanted to solve:</p>

<ul>
<li>Installing Vue into existing Sitecore solution and setting up build.</li>
<li>Using Vue in Sitecore controller renderings (razor files).</li>
<li>Rendering Sitecore field data into Vue components with experience editor support.</li>
<li>Communication between different Vue components in different renderings.</li>
</ul>

<h3 id="installingandbuildingvue">Installing and building Vue</h3>

<p>This is pretty straightforward. </p>

<p><strong>1. create package.json</strong></p>

<pre><code>yarn init
</code></pre>

<p><strong>2. Install the following dependencies</strong></p>

<pre><code>yarn add vue
yarn add webpack webpack-cli --dev
yarn add vue-loader vue-template-compiler vue-style-loader css-loader --dev
yarn add @babel/core @babel/plugin-syntax-dynamic-import @babel/preset-env babel-loader cross-env css-loader --dev
</code></pre>

<p><strong>3. Configure webpack and babel</strong></p>

<p>The way I've always built my Vue applications is via webpack. Below is my basic dev config. Note it does not include any production build steps (minification, bundling etc etc) which are essential so don't forget those.</p>

<pre><code>'use strict'
  const webpack = require('webpack')
  const path = require('path');
  const { VueLoaderPlugin } = require('vue-loader')

module.exports = {
  mode: 'development',

  entry: [
    './vue/app.js'
  ],
  output: {
    filename: 'main.js',
    path: path.resolve('./vue-build')
       },
       resolve: {
             alias: {
                    'vue$': 'vue/dist/vue.esm.js'
         }
   },
  module: {
    rules: [
      {
        test: /\.vue$/,
        use: 'vue-loader'
      },
      {
        test: /\.js$/,
        loader: 'babel-loader',
        include: [path.join(__dirname, 'src')],
      },
      {
        test: /\.scss$/,
        use: [
          'vue-style-loader',
          'css-loader',
          {
            loader: 'sass-loader',
          },
        ],
      },
      {
        test: /\.css$/,
        use: [
          'vue-style-loader',
          'css-loader',
          {
            loader: 'css-loader',
          },
        ],
      },
    ]
  },
  plugins: [
    new webpack.HotModuleReplacementPlugin(),
    new VueLoaderPlugin()
  ]
}
</code></pre>

<blockquote>
  <p><strong>note: the 'resolve' section is a real gotcha and is required to build Vue in the style we will be coding later in this tutorial. Don't forget to add it to your webpack config!</strong></p>
</blockquote>

<h4 id="andmybabelrc">And my .babelrc</h4>

<p>Babel is a tool to transpile newer Javascript language features (e.g. ES6) into older versions of Javascript (e.g. ES5) that work in current and older browsers or environments. </p>

<pre><code>{
    "presets": [
      [
        "@babel/preset-env" ,
        {
          "modules" : false
        }
      ]
    ],
    "plugins": [
      "@babel/plugin-syntax-dynamic-import"
    ]
  }
</code></pre>

<blockquote>
  <p>Note: If you use typescript you won't need babel. For this prototype I didn't introduce typescript but i would if/when we use Vue outside of a prototyping context.</p>
</blockquote>

<p><strong>Update your package.json</strong></p>

<pre><code>...
"scripts": {
    "build": "webpack --config build/webpack.config.dev.js",
  },
...
</code></pre>

<p><strong>Run with</strong> </p>

<p><code>yarn build</code></p>

<p>(Although it won't work until we create './vue/app.js' in the next section..)</p>

<h3 id="usingvueinsitecorecontrollerrenderings">Using Vue in Sitecore controller renderings</h3>

<p>Create a rendering in Sitecore, for this example I created a simple view rendering with the path:</p>

<p><em>/vue/Components/HelloWorld.cshtml</em></p>

<p>Below is the contents of that file.</p>

<pre><code>@inherits System.Web.Mvc.WebViewPage

&lt;!-- component mounted here --&gt;
&lt;div id="vue-hello-world"&gt;&lt;/div&gt;

&lt;!-- component template --&gt;
&lt;script type="text/x-template" id="hello-world-template"&gt;
    &lt;div&gt;
          &lt;h1&gt;Hello Vue&lt;/h1&gt;
          &lt;div class="container"&gt;
               {{ message }}
          &lt;/div&gt;
    &lt;/div&gt;
&lt;/script&gt;

&lt;!-- This is our webpack output - this should live with your other scripts in the foot of the page not at component level.. but we are prototyping... :) --&gt;
&lt;script type="text/javascript" src ="/vue-build/main.js"&gt;&lt;/ script&gt;
</code></pre>

<p>There are <a href="https://medium.com/js-dojo/7-ways-to-define-a-component-template-in-vuejs-c04e0c72900d">many ways to define Vue templates</a>, to play nicely with Sitecore we are using the x-template option.</p>

<p><strong>Next we need an entry point for our Vue application</strong></p>

<p><em>/vue/app.js</em></p>

<pre><code>import HelloWorld from './Components/hello-world.js'
</code></pre>

<p>This just imports all our components, each parent component is it's own Vue instance.</p>

<p><strong>The hello-world component</strong></p>

<p>If you've used Vue before you will know a vue component typically has a .vue extension (hence the webpack loader) and has the following makeup:</p>

<pre><code>&lt;template&gt;
    &lt;div&gt;Hello world&lt;/div&gt;
&lt;/template&gt;
&lt;script&gt;
export default {
    name: 'hello-world',
    data() {
        return ...
    }
&lt;/script&gt;
&lt;style&gt;
    .blah {
    }
&lt;/style&gt;
</code></pre>

<p>Using .vue files doesn't really work for us, we need our markup to come from the rendering.</p>

<p>Instead we can create plain old js files:</p>

<p><em>/Components/hello-world.js</em></p>

<pre><code>import Vue from 'vue'

let component = {
   name: 'hello-world',
   template: '#hello-world-template',   
   data()
   {
       return {
             message: "Hello World!"
       }
   },
};

// Initialise Vue
if (document.getElementById("vue-hello-world")) {
new Vue({
   el: '#vue-hello-world',
   render: h =&gt; h(component)
});
}

export default component
</code></pre>

<p>And that's it! If you run the webpack build the hello world Vue component should render. </p>

<h3 id="torenderchildcomponents">To render child components:</h3>

<p>The syntax to achieve this also caught me out but here's how it done:</p>

<p><em>hello-world.js</em></p>

<pre><code>import AChildComponent from './hello-world-child.js'

let component = {
    name: 'hello-world',
    template: '#hello-world-template',
    components: { 'hello-world-child': AChildComponent },
...
</code></pre>

<p><em>hello-world.cshtml</em></p>

<pre><code>...
&lt;script type="text/x-template" id="hello-world-template"&gt;
        ...
        &lt;hello-world-child&gt;&lt;/hello-world-child&gt;
    &lt;/div&gt;
&lt;/script&gt;
...

&lt;!-- child component template --&gt;
&lt;script type="text/x-template" id="hello-world-child-template"&gt;
    &lt;div&gt;
        &lt;h1&gt;Hello!&lt;/h1&gt;
    &lt;/div&gt;
&lt;/script&gt;
</code></pre>

<p>and you would create the child vue component hello-world-child.js. It doesn't need referencing in app.js webpack will sort this out for you.</p>

<h3 id="vuecomponent">Vue.Component</h3>

<p>As we can't use .vue files, Vue components are <a href="https://vuejs.org/v2/guide/components.html">another option</a> in .js files. </p>

<p>However coding a Vue application is this style does come with caveats as documented here: </p>

<p><a href="https://frontendsociety.com/why-you-shouldnt-use-vue-component-ff019fbcac2e">https://frontendsociety.com/why-you-shouldnt-use-vue-component-ff019fbcac2e</a></p>

<h3 id="renderingsitecorefieldcontent">Rendering Sitecore field content</h3>

<p>Using this method we are simply adding markup and Javascript to standard controller renderings (razor files) which keeps a clean separation of server and client code. So whichever method you use to render sitecore fields should work just fine.</p>

<h3 id="vuex">Vuex</h3>

<p>You can just use Vuex as usual. Create an instance of the store and ensure each Vue instance (there is one per component in this setup) references that same store.</p>]]></content:encoded></item><item><title><![CDATA[Kubernetes beginners series - Part 2 - deploy a simple app]]></title><description><![CDATA[<p>If you followed by previous post you should be in the position where you have a Kubernetes cluster up and running and can access it via the <strong>kubectl</strong> which is installed on your local machine. If not please <a href="http://www.daveleigh.co.uk/kubernetes-beginners-series-part-1-what-is-kubernetes-setting-up-a-cluster-and-the-kubectl/">follow this link</a>.</p>

<p>In this post we will revisit the basics of</p>]]></description><link>https://daveblog.azurewebsites.net/kubernetes-beginners-series-part-2-deploy-a-simple-app/</link><guid isPermaLink="false">49552e47-ad11-4822-8e74-5f024f3a5b55</guid><dc:creator><![CDATA[Dave Leigh]]></dc:creator><pubDate>Fri, 06 Apr 2018 12:00:00 GMT</pubDate><content:encoded><![CDATA[<p>If you followed by previous post you should be in the position where you have a Kubernetes cluster up and running and can access it via the <strong>kubectl</strong> which is installed on your local machine. If not please <a href="http://www.daveleigh.co.uk/kubernetes-beginners-series-part-1-what-is-kubernetes-setting-up-a-cluster-and-the-kubectl/">follow this link</a>.</p>

<p>In this post we will revisit the basics of docker and then cover the basics of Kubernetes by completing the following tasks:</p>

<ul>
<li>Create a simple Node Js app, using Redis as a persistence store.</li>
<li>Dockerize the app.</li>
<li>Deploy the app to Kubernetes and explore two kubernetes resource types - <strong>pods</strong> and <strong>services</strong>.</li>
</ul>

<p>In the next post of this series we will cover some more advanced topics.</p>

<h3 id="thenodejsapp">The Node Js app</h3>

<p>First lets setup our env.</p>

<pre><code>npm init
npm install express --save-dev
npm install redis --save-dev
npm install body-parser --save-dev
</code></pre>

<blockquote>
  <p>If you're new to Node <strong>--save-dev</strong> will add the dependency to our package.json. Later our docker container will be bootstrapped by running <strong>npm install</strong> thus installing required dependencies into the container</p>
</blockquote>

<p>Note - Please don't worry if this app won't run locally - you probably won't have redis installed - but thats expected.. this is what containers are for.</p>

<p>Create an <strong>app.js</strong></p>

<pre><code>const express = require('express'); 
const bodyParser = require('body-parser');
const app = express();

app.use(bodyParser.json()); 
app.use(bodyParser.urlencoded({ extended: true }));

const redis = require('redis');
const client = redis.createClient('6379', 'redis');

app.get('/', (req, res) =&gt;
{
    client.hkeys('items', function (err, reply)
    {
        res.send(JSON.stringify(reply));
    });
});

app.post('/api/additem', function(req, res) 
{
    client.hmset('items', req.body.name, req.body.data, function (err, reply)
    {
        res.send(`Added ${req.body.data}.`);
    });  
});

const port = 3030;

app.listen(port, () =&gt;
{
    console.log(`server listen port: ${port}`);
});
</code></pre>

<p>This is a trivial app which does three things:</p>

<ol>
<li>Create an express webserver which listens for incoming requests on port 3030.  </li>
<li>If we receive a get request to the root we return a response with all the item keys in the redis store.  </li>
<li>If we receive a post request to /api/additem we add to the store.</li>
</ol>

<h3 id="dockerizetheapp">Dockerize the app</h3>

<p>Before we jump into Kubernetes we need to create a container for our app. Containers are based on images, and to create an image we need a dockerfile.</p>

<pre><code># The base image
FROM node:latest
# Create a directory on the container
RUN mkdir -p /my/app    
# Set the working directory
WORKDIR /my/app  
# Copy package.json to the working directory
COPY package.json . 
# Install node dependencies
RUN npm install
# Copy app.js into the working directory 
COPY app.js .       
# Expose the port 3030 on the container
EXPOSE 3030      
# Run the app
CMD [ "node", "app.js" ]    
</code></pre>

<p>To build an image from this dockerfile:</p>

<pre><code>docker build -t daveleigh/demo .
</code></pre>

<blockquote>
  <p>Note: Your local environment needs docker installed - I am on ubuntu. <a href="https://www.docker.com/community-edition">https://www.docker.com/community-edition</a></p>
</blockquote>

<p>We then need to make this image availble to our Kubernetes stack for later so we push it to a container registry. </p>

<pre><code>docker push daveleigh/demo
</code></pre>

<p>To do this with your own account sign up at <a href="https://hub.docker.com/">https://hub.docker.com/</a>.</p>

<p>You could run this container on your docker enabled host:</p>

<pre><code>docker run -d --name myapp -p 3030:3030 daveleigh/demo
</code></pre>

<p>However it would error as redis is not defined yet.  Also that's not the aim here, we are going to deploy this and redis to our Kubernetes stack.</p>

<h3 id="finallykubernetes">Finally... Kubernetes</h3>

<p>Kubernetes provisions and manages containers running on multiple hosts. It can scale pods, manage the health of the stack (spinning up new pods if existing ones crash), automate deployments, load balance... the list goes on.</p>

<p>Declarative yaml/json files define the stack and resources are provisioned by the master on to worker nodes on our cluster via the <strong>kubectl</strong> Api.</p>

<p>The first resource we will create is a <strong>pod</strong>. A pod is a unit of deployment and scale and will contain one or more containers that may expose ports. Containers within a pod can talk to each other via localhost.</p>

<blockquote>
  <p>In our example we will create a pod for our app, and a separate pod for redis. However in a real world scenario if you were using redis as ephemeral cache you may have both the web app and redis in the same pod so they scale together.</p>
</blockquote>

<p>Lets define a pod for our web app, and to do this we create a yaml file.</p>

<p><strong>web-pod.yml</strong></p>

<pre><code>apiVersion: v1
kind: Pod
metadata:
  name: web
  labels:
    name: web
    app: demo
spec:
  containers:
    - image: daveleigh/demo
      name: web
    ports:
      - containerPort: 3030
</code></pre>

<p>This file is pretty self explanatory. We define the type of resource to create and some meta data. Note labels are arbitrary so you can specify anything you want. The purpose of labels is for other resources should they need to target your pod, for example a load balancer might target pods where app = demo.</p>

<p>Within spec we define the containers the pod will host and the ports each container exposes. Simple.</p>

<p>Lets also define a redis pod:</p>

<p><strong>redis-pod.yml</strong></p>

<pre><code>apiVersion: v1
kind: Pod
metadata:
    name: redis
    labels:
    name: redis
    app: demo
spec:
    containers:
    - image: redis:latest
        name: redis
        ports:
        - containerPort: 6379
</code></pre>

<h3 id="provisioningthepods">Provisioning the pods</h3>

<p>Let's deploy our pods onto our cluster.</p>

<pre><code>kubectl create -f web-pod.yml -f redis-pod.yml
</code></pre>

<p>You should see the following output:</p>

<p>pod "web" created <br>
pod "redis" created</p>

<p>To view the pods we have just asked Kubernetes to create for us:</p>

<pre><code>kubectl get pods
</code></pre>

<p>You will notice the web pod has errored! We can see the details of the error:</p>

<pre><code>kubectl get logs web
</code></pre>

<p>Don't panic just yet.. and it's not quite time to swear at me for wasting your time.. this is expected and brings us onto..</p>

<h3 id="services">Services</h3>

<p>Our pods need to be able to communicate with each other and potentially the outside world.</p>

<p>There are two main types of service, internal and external. Internal services allow our pods to communicate within the cluster. External services allow access to our pods from the host.</p>

<p>Lets create an internal service:</p>

<p><strong>redis-svc.yml</strong></p>

<pre><code>apiVersion: v1
kind: Service
metadata:
    name: redis
    labels:
    name: redis
    app: demo
spec:
    selector:
    name: redis
  type: ClusterIP
  ports:
   - name: http
     targetPort: 6379
     port: 6379
</code></pre>

<p>This will create a new Service object named 'redis' which targets TCP port 6379 on any Pod with the "name=redis" label. </p>

<p>Type 'ClusterIP' exposes the Service on an <strong>internal</strong> IP in the cluster. '<strong>targetPort</strong>' is the port the container exposes in the pod and '<strong>port</strong>' is the port used internally by consumers (it is the port your service listens on inside the cluster.)</p>

<pre><code>kubectl create -f redis-svc.yml
</code></pre>

<p>Then recreate the web pod:</p>

<pre><code>kubectl delete pod web
kubectl create -f web-pod.svc
</code></pre>

<p>Now the app should be up and running, however we can only access it internally. To test the app we can hop into the shell within our web pod:</p>

<pre><code>kubectl exec -it web /bin/bash
</code></pre>

<p>Now lets try using the api:</p>

<pre><code>curl -d "name=item1&amp;data=test" -X POST http://localhost:3030/api/additem
</code></pre>

<p>You should see <em>'Added item1'</em>. Great!</p>

<p>Before we finish up, lets make the app available from outside the cluster.</p>

<h3 id="externalservice">External Service</h3>

<p>Lets use our app via the public IP of one of our worker nodes. The only missing piece of the puzzle is to create an external service to allow requests to the host to access our pods.</p>

<p><strong>web-svc.yaml</strong></p>

<pre><code>apiVersion: v1
kind: Service
metadata:
    name: web
spec:
    selector:
    app: demo
  type: NodePort
     ports:
    - name: http
        nodePort: 31001
      port: 80
      targetPort: 3030
</code></pre>

<p>Creating our service of type '<strong>NodePort</strong>' exposes the Service on the same port of each Node in the cluster. </p>

<p>The '<strong>nodePort</strong>' defines the port on the node. <br>
Internally all the consumers of the service can talk to the service on port 80. <br>
the '<strong>targetPort</strong>' is 3030, i.e the port the container exposes in the pod.</p>

<pre><code>kubectl create -f web-svc.yml
</code></pre>

<p>If you want to see details about any of the resources you have created:</p>

<pre><code>kubectl describe svc web
</code></pre>

<p>You should now be able to access your app at: <a href="http://PublicIP:31001">http://PublicIP:31001</a>.</p>

<h3 id="toconclude">To conclude</h3>

<p>So we've taken our tiny app and deployed it onto a Kubernetes cluster. Hopefully this gives you a glimpse of what Kubernetes has to offer. This example is of course trivial but I hope it helps show the power of Kubernetes and how it could help you run your applications in production situations.</p>

<p>Speaking of more production like situations we will cover persistance in pods which is a hot topic in a later post and in the next post we will create a replica set and a rolling deployment.</p>]]></content:encoded></item><item><title><![CDATA[Kubernetes beginners series - Part 1 - What is Kubernetes, setting up a cluster and the kubectl.]]></title><description><![CDATA[<p>I'm a big fan of docker (well the concept of containers in general) so recently I became acquainted with Kubernetes. </p>

<h4 id="whatwewillcovertoday">What we will cover today:</h4>

<ol>
<li>What is Kubernetes and when would I use it?  </li>
<li>What is cluster &amp; setting up a cluster on AWS/Azure/Google cloud/Digital Ocean/Bare</li></ol>]]></description><link>https://daveblog.azurewebsites.net/kubernetes-beginners-series-part-1-what-is-kubernetes-setting-up-a-cluster-and-the-kubectl/</link><guid isPermaLink="false">d04e45c9-6bf0-46aa-a59a-225c96d4d434</guid><dc:creator><![CDATA[Dave Leigh]]></dc:creator><pubDate>Wed, 04 Apr 2018 12:00:00 GMT</pubDate><content:encoded><![CDATA[<p>I'm a big fan of docker (well the concept of containers in general) so recently I became acquainted with Kubernetes. </p>

<h4 id="whatwewillcovertoday">What we will cover today:</h4>

<ol>
<li>What is Kubernetes and when would I use it?  </li>
<li>What is cluster &amp; setting up a cluster on AWS/Azure/Google cloud/Digital Ocean/Bare Metal  </li>
<li>What is the Kubectl (spoiler alert, its the Kubernetes Api used to manage your resources).</li>
</ol>

<h3 id="whatiskubernetes">What is Kubernetes?</h3>

<p>If you've not used Docker before, I would suggest covering that first, trust me it's worth it.. i'll wait.</p>

<p>Great, so if like me you love the concept of containers, but now have the challenge of managing them in production Kubernetes is for you.</p>

<p>In the past whilst spinning up and linking docker containers you may have used docker compose. It's fairly simple and allows you to quickly create a number of linked containers on a single docker host (via a docker-compose yaml file). What it doesn't do though is:</p>

<ul>
<li>Allow you to deploy containers across multiple hosts (VMs).</li>
<li>Manage the lifetime and health of each container and provision new containers should existing ones crash.</li>
<li>Manage scaling, networking, automate deployments, load balancing etc.</li>
</ul>

<p>This is where Kubernetes (or k8s as it's also known) fits into the picture. (note: Docker swarm was also built to solve these problems. I won't go into Swarm vs K8s in these blog posts.)</p>

<blockquote>
  <h4 id="importantwhatkubernetesisnot">(Important) What Kubernetes is not...</h4>
  
  <p>It is not the silver bullet (sorry!) to solve all your production infrastructure challenges. You still need to solve those first... yourself. For example, do you need multi master database replication across multiple regions? Well, K8s will not solve scenarios like this for you. However once you have solved such problems conceptually (perhaps a managed database is better than facilitating this via K8s for this scenario) then sure, Kubernetes can provision and manage the lot... easily.</p>
</blockquote>

<h3 id="thecluster">The cluster</h3>

<p>A kubernetes cluster contains a master and a number of worker nodes. (Strictly you can have more than one master, but let's not complicate things this early)</p>

<p>Kubernetes provisions your containers across a cluster of worker nodes via the master. A worker node is simply a VM with some preinstalled runtimes. The master is responsible for scheduling and maintaining the cluster (amongst other things).</p>

<p>The simplest resource you can ask the master to provision for you is a <strong>pod</strong>.</p>

<p>A <strong>pod</strong> is a logical wrapper around a number of containers and in Kubernetes it is the unit of scale in a cluster.</p>

<p>For example, to deploy a single container to a Kubernetes stack, you would create a pod definition file (in yaml) and ask the master to provision and manage this for you, via the Kubernetes Api (<strong>kubectl</strong>).</p>

<p><strong>(There is a lot of background in this post, in the next couple of posts we actually provision a number of pods and start exploring other Kubernetes resources with the goal to deploy a simple distributed containerized app - a NodeJS API with a redis cache and a mysql backend.)</strong></p>

<h3 id="creatingaclusterandinstallingkubectl">Creating a cluster and installing kubectl</h3>

<p>During this series we will start simple and gradually introduce more Kubernetes concepts and resource types as we go. To start lets get a cluster (A single master and 2 working nodes) up and running.</p>

<p>How much will I pay for my cluster? Well that depends on the cloud provider and specifically the size of VMs you use. You can set up a cluster for about $30 a month though on AWS/Azure and GKE.</p>

<h4 id="kubectl">Kubectl</h4>

<p>Before you create your cluster install kubectl on your local machine. (I am using ubuntu)</p>

<p><a href="https://kubernetes.io/docs/tasks/tools/install-kubectl/">https://kubernetes.io/docs/tasks/tools/install-kubectl/</a></p>

<h4 id="azure">Azure</h4>

<p>At the time of writing Azure Container Service (AKS) is in preview. AKS is Azures newest managed Kubernetes offering. The beauty of AKS is that the master is abstracted away from you, you don't see it in your list of resources nor do you pay for it.</p>

<p>You can spin up a cluster in minutes.  The easiest way is via the CLI (follow these instructions - <a href="https://docs.microsoft.com/en-us/azure/aks/kubernetes-walkthrough">https://docs.microsoft.com/en-us/azure/aks/kubernetes-walkthrough</a>) This will also guide you through installing the kubectl (Kubernetes API) and linking your cluster to the API.</p>

<p>You can specify instance size rather than using the default:</p>

<p><code>az aks create --resource-group myresourcegroup --name mycluster --node-count 2 --generate-ssh-keys --node-vm-size Standard_B2s</code></p>

<p>You can see the list of instance sizes here: </p>

<p><a href="https://docs.microsoft.com/en-us/azure/virtual-machines/windows/sizes-general#d-series">https://docs.microsoft.com/en-us/azure/virtual-machines/windows/sizes-general#d-series</a></p>

<p><em>Edit: 04/04 - You may have problems creating clusters in westeurope, try eastus instead. <a href="https://github.com/Azure/AKS/issues/280">https://github.com/Azure/AKS/issues/280</a></em></p>

<p>*Edit: 09/04 - Seems to be resolved</p>

<h4 id="digitalocean">Digital Ocean</h4>

<p>Digital ocean do not offer a managed / one click service (at the time of writing) although Stackpoint can do all the work for you. Link your account, select your instance sizes and magically you have a cluster ready for you.</p>

<p><a href="https://www.digitalocean.com/community/tutorials/webinar-series-getting-started-with-kubernetes">https://www.digitalocean.com/community/tutorials/webinar-series-getting-started-with-kubernetes</a></p>

<p>The alternative is to spin up CoreOS / Ubuntu boxes and installing the runtimes and link the worker nodes to the master yourself (as you would if you were installing on bare metal).</p>

<h4 id="aws">AWS</h4>

<p>For the long time the way to set up a Kubernetes cluster on AWS was using KOPS. If you want to go down that route (it is a little more complicated than the options above) here are the instructions:</p>

<p><a href="https://kubernetes.io/docs/getting-started-guides/kops/">https://kubernetes.io/docs/getting-started-guides/kops/</a></p>

<p>However Amazon have recently released EKS (<a href="https://aws.amazon.com/eks/">https://aws.amazon.com/eks/</a>) in preview, which looks very similar to Azure's offering. Note: This is a managed Kubernetes offering not to be confused with ECS. </p>

<p>Look out for this when it is more widely available, currently you need to be invited to use it.</p>

<h4 id="googlecontainerenginegke">Google Container Engine (GKE)</h4>

<p>This is possibly the easiest of the lot. Presuming you've signed up to Google Cloud (they will offer you a substantial amount of free usage) head to <a href="https://console.cloud.google.com/kubernetes">https://console.cloud.google.com/kubernetes</a>.</p>

<p>Click 'Create cluster', pick a Zone and machine size. After clicking 'Create' you will have a fully managed Kubernetes cluster up and running.</p>

<p>After the cluster is created click 'Connect'. Execute the command provided on your local machine (the one with kubectl installed).</p>

<h4 id="baremetal">Bare metal</h4>

<p>Setting up a kubernetes cluster on your own servers / VMs is more complicated than cloud offerings but there is some help out there for you:</p>

<p><a href="https://medium.com/@sachin.arote1/installing-kubernetes-on-bare-metal-server-or-virtual-machine-via-kubeadm-8af39ec84562">https://medium.com/@sachin.arote1/installing-kubernetes-on-bare-metal-server-or-virtual-machine-via-kubeadm-8af39ec84562</a></p>

<p><a href="https://blog.alexellis.io/kubernetes-in-10-minutes/">https://blog.alexellis.io/kubernetes-in-10-minutes/</a></p>]]></content:encoded></item><item><title><![CDATA[Sitecore straight to datasource chrome plugin]]></title><description><![CDATA[<h3 id="getithere">Get it here</h3>

<p><a href="https://chrome.google.com/webstore/detail/sitecore-straight-to-data/lecpobmpcnpdhpljfebldoegfonlgjjj">https://chrome.google.com/webstore/detail/sitecore-straight-to-data/lecpobmpcnpdhpljfebldoegfonlgjjj</a></p>

<h3 id="whatitdoes">What it does</h3>

<p><strong>Sitecore S2D</strong> (formerly <strong>Sitecore STD</strong> - I changed the name for obvious reasons..!) is a <strong>chrome plugin</strong> which adds a <em>hyperlink</em> next to various link fields in the <strong>content editor</strong> which when clicked will jump you</p>]]></description><link>https://daveblog.azurewebsites.net/sitecore-straight-to-datasource-chrome-plugin/</link><guid isPermaLink="false">b2492b0f-8783-4647-8446-51fe5aa14a03</guid><dc:creator><![CDATA[Dave Leigh]]></dc:creator><pubDate>Fri, 22 Jul 2016 12:00:00 GMT</pubDate><content:encoded><![CDATA[<h3 id="getithere">Get it here</h3>

<p><a href="https://chrome.google.com/webstore/detail/sitecore-straight-to-data/lecpobmpcnpdhpljfebldoegfonlgjjj">https://chrome.google.com/webstore/detail/sitecore-straight-to-data/lecpobmpcnpdhpljfebldoegfonlgjjj</a></p>

<h3 id="whatitdoes">What it does</h3>

<p><strong>Sitecore S2D</strong> (formerly <strong>Sitecore STD</strong> - I changed the name for obvious reasons..!) is a <strong>chrome plugin</strong> which adds a <em>hyperlink</em> next to various link fields in the <strong>content editor</strong> which when clicked will jump you straight to the linked item referenced within the field.</p>

<p><img src="http://www.daveleigh.co.uk/content/images/s2d1.png" alt="example usage"></p>

<p>S2D works on <strong>Droplinks</strong>, <strong>Treelists</strong> and <strong>Multilists</strong>. </p>

<p>Simply select an option within the field (which will be another item as this plugin works with link fields) on a <strong>Multilist</strong> or <strong>Treelist</strong> and a link to the item will be rendered next to the field. Click it to go to that item (rather than Raw Values -> Copy, Search.. etc).</p>

<p>Droplink datasource link gets rendered automatically and will update if you change selected item.</p>

<h4 id="whychromeplugins">Why chrome plugins?</h4>

<p>The Sitecore dev's are working like crazy right now.. there is some awesome new stuff to come, but every now and then I'd like to add my own features to the content editor. Chrome plugins are a great unobtrusive way of doing this. You can get new version independent features without having to install anything on the server.</p>

<h4 id="foundbugs">Found bugs?</h4>

<p>I hope not.. Let me know :-)</p>

<h4 id="edit1otherresources">EDIT #1 Other resources</h4>

<p>Thanks to <a href="https://twitter.com/hi_dheer">Dheer Rajpoot</a> for pointing out that there is also an awesome alternative in the form of a sitecore module on the marketplace by <a href="https://twitter.com/ISlayTitans">@ISlayTians</a> (Mr Jon Robbins) which will give you similar functionality but for more field types. If you want something fast which requires no installation on each of your sitecore instances and covers the most common link types this chrome plugin should do the job for you otherwise download Jon's module - it looks fantastic:</p>

<p><a href="https://marketplace.sitecore.net/en/Modules/F/Follow_Field_Target.aspx">Get it here</a></p>]]></content:encoded></item><item><title><![CDATA[Quick tip - making an existing field shared]]></title><description><![CDATA[<p>So a shared field in Sitecore - basically means the value of the field is the same in every language. </p>

<p>There might be the situation where you have a field in use (it may have been in use for a long time) but you've realized it should be shared.</p>

<p>You</p>]]></description><link>https://daveblog.azurewebsites.net/quick-tip-making-an-existing-field-shared/</link><guid isPermaLink="false">1377cc80-db3b-469c-8fbc-236dc1bda2d6</guid><dc:creator><![CDATA[Dave Leigh]]></dc:creator><pubDate>Fri, 15 Jul 2016 12:00:00 GMT</pubDate><content:encoded><![CDATA[<p>So a shared field in Sitecore - basically means the value of the field is the same in every language. </p>

<p>There might be the situation where you have a field in use (it may have been in use for a long time) but you've realized it should be shared.</p>

<p>You might have different data against 50 different languages - what will happen to my data?! For example you may want the shared value to be that of the French version.</p>

<p>Well actually there is logic behind it and it's not based on the current language you have selected against the template. </p>

<p>If you make a field shared, which has data in it, Sitecore will set every language version to use the field data from the last language version you updated that field for.</p>

<p>Might help someone :-)</p>]]></content:encoded></item><item><title><![CDATA[Sitecore Peek Content editor Tab]]></title><description><![CDATA[<p>I've been busy playing with <strong>SPEAK 2.0</strong> and as a result have added a nice little module to the marketplace.</p>

<p><strong>PEEK</strong> allows you to see differences in your field data for the current item across various publishing targets (i.e web/delivery db) - all from the master (content)</p>]]></description><link>https://daveblog.azurewebsites.net/sitecore-peek-content-editor-tab/</link><guid isPermaLink="false">215e9bb0-9546-45ef-98e6-934aa599ea3d</guid><dc:creator><![CDATA[Dave Leigh]]></dc:creator><pubDate>Thu, 31 Mar 2016 12:00:00 GMT</pubDate><content:encoded><![CDATA[<p>I've been busy playing with <strong>SPEAK 2.0</strong> and as a result have added a nice little module to the marketplace.</p>

<p><strong>PEEK</strong> allows you to see differences in your field data for the current item across various publishing targets (i.e web/delivery db) - all from the master (content) database. It's pretty straightforward - I'll continue to update it with more features (i.e are item's children the same on web as on master.)</p>

<p><img src="http://www.daveleigh.co.uk/content/images/peek1.jpg" alt="Peek1"></p>

<p>Why? Well I built this mainly for our content pops and QA teams who will quite often query why some content isn't displaying on the front end. In large teams working on multiple items at once it's hard to keep track of which items have been published. They (and often us investigating!) had to keep switching content databases within the CMS to check what content was indeed published.</p>

<h4 id="youcangetithere">You can get it here:</h4>

<p><a href="https://marketplace.sitecore.net/Modules/P/Peek.aspx?sc_lang=en">https://marketplace.sitecore.net/Modules/P/Peek.aspx?sc_lang=en</a></p>

<h4 id="toaddthenewtab">To add the new tab:</h4>

<ol>
<li><p>Install the package (there is a version for Sitecore 8 and a SPEAK 2.0 version for Sitecore 8.1)</p></li>
<li><p>Navigate to the item template _standard Values and click '<strong>Configure->Editors</strong>' in the main ribbon. Select <strong>DEL/Peek</strong> and <strong>Save</strong>.</p></li>
</ol>

<p><img src="http://www.daveleigh.co.uk/content/images/peek2.jpg" alt="Peek2"></p>

<p><img src="http://www.daveleigh.co.uk/content/images/peek3.jpg" alt="Peek3"></p>]]></content:encoded></item><item><title><![CDATA[SPEAK 2.0 Helpers]]></title><description><![CDATA[<p>If like me you are starting to move your SPEAK 1.1 applications and components across to 2.0 you will notice there are a fair few differences - one of these is how you access the Helpers in your page code.</p>

<p>e.g: Sitecore.Helpers.url.getQueryParameters(window.location.</p>]]></description><link>https://daveblog.azurewebsites.net/speak-2-0-helpers/</link><guid isPermaLink="false">bf5f3da4-e7e9-4ec5-ae4c-2459bf0f9a76</guid><dc:creator><![CDATA[Dave Leigh]]></dc:creator><pubDate>Sat, 05 Mar 2016 12:00:00 GMT</pubDate><content:encoded><![CDATA[<p>If like me you are starting to move your SPEAK 1.1 applications and components across to 2.0 you will notice there are a fair few differences - one of these is how you access the Helpers in your page code.</p>

<p>e.g: Sitecore.Helpers.url.getQueryParameters(window.location.href)['id']</p>

<p><a href="http://mhwelander.net/2014/07/08/speak-for-newbies-part-6-speak-helpers/">http://mhwelander.net/2014/07/08/speak-for-newbies-part-6-speak-helpers/</a></p>

<p>I couldn't actually find the 2.0 equivilent in the documenation but actually with a quick play in the console it was pretty obvious..</p>

<p>Sitecore.<strong>Speak</strong>.Helpers.url.getQueryParameters(window.location.href)['id']</p>

<p><a href="https://mikerobbins.co.uk/2015/10/20/sitecore-speak-2-0-component-vs-speak-1-1/">Mike Robbins</a> and <a href="http://sitecoreart.martinrayenglish.com/2016/01/getting-started-with-sitecore-speak-20.html">Martin English</a> have a couple of great posts if you get stuck upgradeding to 2.0 and also watch this space - I'll blog anything I find!</p>]]></content:encoded></item><item><title><![CDATA[Responsive Images (srcset) and Sitecore Media]]></title><description><![CDATA[<p>In this current age of web development more and more sites are going responsive. I mean its not a surprise really with the almost endless amount of web ready devices out there.</p>

<p>Thinking in terms of performance we don't want poor Eric on his 320px wide Android downloading images designed</p>]]></description><link>https://daveblog.azurewebsites.net/responsive-images-srcset-and-sitecore-media/</link><guid isPermaLink="false">6d333b32-9c91-46c8-86ac-7b8fd15d707f</guid><dc:creator><![CDATA[Dave Leigh]]></dc:creator><pubDate>Thu, 10 Dec 2015 12:00:00 GMT</pubDate><content:encoded><![CDATA[<p>In this current age of web development more and more sites are going responsive. I mean its not a surprise really with the almost endless amount of web ready devices out there.</p>

<p>Thinking in terms of performance we don't want poor Eric on his 320px wide Android downloading images designed for a desktop experience. This is where responsive images, the '<strong>srcset</strong>' and '<strong>sizes</strong>' attributes come in handy.</p>

<p>Specifying <strong>srcset</strong> and <strong>sizes</strong> allows the browser to determine which size image to use. We don't need to get involved at all - the browser does it all.</p>

<p>For example:</p>

<pre><code>&lt;img src="dave.jpg" alt="daves face" 
  srcset="dave-320.jpg 160w, dave-320.jpg 320w, dave-640.jpg 640w, dave-1280.jpg 1280w"&gt;
</code></pre>

<p>Using responsive images Eric only needs to download the 320px wide image to see my face rather than waiting an eternity for the 1280px full resolution version.</p>

<p>Browser support is pretty good too: <a href="http://caniuse.com/#feat=srcset">http://caniuse.com/#feat=srcset</a></p>

<p>...and polyfills are available for those pesky older browsers: <a href="https://scottjehl.github.io/picturefill/">https://scottjehl.github.io/picturefill/</a></p>

<h3 id="whataboutsitecore">What about Sitecore?</h3>

<p>Well as we know Sitecore has a pretty neat way of handling media - if you specify a ?mw= querystring you can request a lower res version of the original image.</p>

<pre><code>/medialibrary/dave.ashx?mw=320
</code></pre>

<p>This means I don't need to crop four images in Photoshop and upload all four to my web server to achieve the example above - I just upload dave-1280.jpg to Sitecore and write my img tag thus:</p>

<pre><code>&lt;img src="dave.jpg" alt="daves face" 
  srcset="/medialibrary/dave.ashx?mw=320 160w, /medialibrary/dave.ashx?mw=320 320w, /medialibrary/dave.ashx?mw=640 640w, /medialibrary/dave.ashx?mw=1280 1280w"&gt;
</code></pre>

<p>Sitecore does the rest - it will serve the image at the correct resolutions and store them in media cache too!</p>

<p>Great!</p>

<p>p.s Learn more about srcset here: <a href="http://blog.cloudfour.com/responsive-images-101-part-4-srcset-width-descriptors/">http://blog.cloudfour.com/responsive-images-101-part-4-srcset-width-descriptors/</a></p>

<p>p.p.s Don't use srcset without sizes: <a href="http://blog.cloudfour.com/responsive-images-101-part-5-sizes/">http://blog.cloudfour.com/responsive-images-101-part-5-sizes/</a></p>]]></content:encoded></item><item><title><![CDATA[Go to Item, Go to DataSource - Huge update for Sitecore Hotkeys.]]></title><description><![CDATA[<p><strong>Sitecore Hotkeys</strong> is an ongoing experiment for me. </p>

<p>The idea was to build something useful and gradually add features to speed up how we use the Sitecore Content Editor. It is a <strong>chome extension</strong> so that no installaion is required within your projects, you can use it anywhere as long</p>]]></description><link>https://daveblog.azurewebsites.net/go-to-item-go-to-datasource-huge-update-for-sitecore-hotkeys/</link><guid isPermaLink="false">3a4e7636-05b0-4b9a-9b85-ae5cb3b6fa47</guid><dc:creator><![CDATA[Dave Leigh]]></dc:creator><pubDate>Wed, 04 Nov 2015 12:00:00 GMT</pubDate><content:encoded><![CDATA[<p><strong>Sitecore Hotkeys</strong> is an ongoing experiment for me. </p>

<p>The idea was to build something useful and gradually add features to speed up how we use the Sitecore Content Editor. It is a <strong>chome extension</strong> so that no installaion is required within your projects, you can use it anywhere as long as you have Chrome installed! Great! Click the link above to install it. (It's worth it just for <strong>Alt+0</strong>)</p>

<h3 id="newfeaturesfornovember">New features for November</h3>

<h4 id="pastetoitem">Paste to Item</h4>

<p>This is pretty cool. have an Item Id on your system clipboard? Just press <strong>Ctrl+v</strong> (Standard paste) with the content editor open (not a focussed text box) and the item will be selected/loaded in the tree.</p>

<h4 id="gotodatasource">Go to DataSource</h4>

<p>Within presentation details I've always wanted a <strong>Go to Datasource</strong> button. Alas we haven't got one yet but <strong>Alt+0</strong> is the next best thing!</p>

<p>With the sublayout details dialog open press <strong>Alt+0</strong>. The Datasource item will load in a brand new window.</p>

<p><img src="http://www.daveleigh.co.uk/content/images/schk_nov1.png" alt="nov1"></p>

<p><img src="http://www.daveleigh.co.uk/content/images/schk_nov2.png" alt="nov2"></p>

<p>Sitecore Hotkeys is always changing and is still in BETA but it should work great. If it doesn't or you find a bug give me a shout.</p>]]></content:encoded></item><item><title><![CDATA[Sitecore Deployments Part 3 - Octopus]]></title><description><![CDATA[<p>I've moved a couple of projects over to Octopus recently. Is MSDeploy dead? I don't think so just yet! - but after writing build scripts which are honestly hundreds and hundreds of lines long it's nice to use a piece of software which takes all the pain away.</p>

<h4 id="whatisoctopus">What is</h4>]]></description><link>https://daveblog.azurewebsites.net/sitecore-deployments-part-3-octopus/</link><guid isPermaLink="false">7293e70f-ce21-46c7-8f20-8f5866d86056</guid><dc:creator><![CDATA[Dave Leigh]]></dc:creator><pubDate>Mon, 19 Oct 2015 12:00:00 GMT</pubDate><content:encoded><![CDATA[<p>I've moved a couple of projects over to Octopus recently. Is MSDeploy dead? I don't think so just yet! - but after writing build scripts which are honestly hundreds and hundreds of lines long it's nice to use a piece of software which takes all the pain away.</p>

<h4 id="whatisoctopus">What is Octopus?</h4>

<p>If you haven't used Octopus Deploy (<a href="https://octopusdeploy.com/">https://octopusdeploy.com/</a>) I'd suggest trying it out. Octopus takes over the deploy phase your of build process. We still use Team City to build, run tests and create a package of the application (plus other bits) however it is at this point that Octopus takes over. Octopus acquires the package, runs config transforms (amongst other things) and pushes the code to target environments. </p>

<p>It can create IIS Sites, execute tasks on the server (via PowerShell), actually it can pretty much do everything you can think of - and most of it configurable right out of the box. The great news - it just works.</p>

<h3 id="howweuseoctopus">How we use Octopus</h3>

<p>We have two main projects in Octopus, they are fairly similar. One is for one off deployments to non-production environments e.g. QA and UAT. The other is our release track - the web app is deployed to an integration environment and then promoted to live, both CM and then CD servers one at a time. </p>

<blockquote>
  <p>Note: Promoting a release means deploying exactly the same package to another environment ensuring consistency.</p>
</blockquote>

<p>Taking the production release as an example our configuration of Octopus does the following:</p>

<p><strong>1) Takes the server out of load balancer</strong></p>

<ul>
<li>Runs a powershell script to take the current server out of the load balancer.</li>
<li>Prompts the user to confirm the site is receiving no traffic. (This step only runs when the target server is tagged as <strong>ContentDelivery</strong>)</li>
</ul>

<p><strong>2) Ensures Sitecore runtimes</strong></p>

<ul>
<li>Here we check if the Sitecore runtimes are on the server. </li>
<li>If they are not Octopus deploys the Sitecore and Data folders. Basically everything not in source control from a nuget package we previously uploaded to Octopus.</li>
</ul>

<p><strong>3) Web deploy</strong></p>

<ul>
<li>Acquires the latest package created by Team City.</li>
<li>Run config transforms.</li>
<li>Copies package contents to the server.</li>
<li>Moves environment specific patch files to <strong>App_config/Include</strong> folder.</li>
<li>Copies Sitecore assemblies (those not referenced by any projects but needed by the CMS to <strong>/bin</strong>)</li>
<li>Deletes some unwanted files.</li>
<li>Creates the application pool if it does not exist.</li>
<li>Creates the IIS Site if it does not exist.</li>
<li>Assigns bindings to the website.</li>
<li>Notifies our team chat of success / failure.</li>
</ul>

<p><strong>4) Put the server back into the load balancer</strong></p>

<ul>
<li>Prompt the user to confirm they have tested the deployment on the specific server.</li>
<li>Runs powershell script to put the server back into the load balancer.</li>
</ul>

<p>Below are a few screenshots with some notes if you want to see how the above is configured:</p>

<p><strong>Process</strong></p>

<p><img src="http://www.daveleigh.co.uk/content/images/octo-process.png" alt="Process"></p>

<p><strong>Take server out of load balancer</strong></p>

<p><img src="http://www.daveleigh.co.uk/content/images/octo-takesiteoutoflb.png" alt="Load balancer"></p>

<p><strong>Deploy Sitecore runtimes</strong></p>

<p>In the check step we set a variable if the runtimes do not exist.</p>

<p><img src="http://www.daveleigh.co.uk/content/images/octo-doruntimesexist.jpg" alt="Check Sitecore runtimes"></p>

<p>We then check this variable during the deploy runtimes phase.</p>

<p><img src="http://www.daveleigh.co.uk/content/images/octo-deploysitecore.JPG" alt="Deploy Sitecore runtimes"></p>

<p><strong>Deploy web app</strong></p>

<p>The pre-deplyoment script copies our environment specific config from a Configuration folder /Config/QA/Sitecore.Qa.Config to the App_Config/Include folder.</p>

<p>It also moves the SwitchMasterToWeb config if we are deploying to a CD box.</p>

<p><img src="http://www.daveleigh.co.uk/content/images/octo-deployapp.png" alt="Deploy Sitecore runtimes"></p>

<p>(This screenshot is actually from our non-prod project but the prod process is almost exactly the same.)</p>

<h2 id="finalthoughts">Final thoughts</h2>

<p>There is so much I haven't even talked about yet - for a start how we deploy Sitecore content. I guess this is saved for another day however there is loads of good material out there for example have a Google for <strong>Sitecore.Ship</strong> / <strong>Sitecore.Octopus</strong> and also <strong>Sitecore Nirvana</strong> by the Hedgehog guys.</p>]]></content:encoded></item></channel></rss>