Blog

Tagged by 'cms'

  • I’ll get right to it. Should I be making the move to a headless content management platform? I am no stranger to the Headless CMS sector after the many years of being involved in using different providers for client-based projects, so I am well-versed on the technology to make a judgement. But any form of judgment gets thrown out the window when making a consideration from a personal perspective.

    Making the move to a Headless CMS is something I’ve been thinking for quite some time now as it would streamline my website development considerably. I can see my web application build footprint being smaller compared to how it is at the moment by running on Kentico 12.

    This website has been running on Kentico CMS for around 6 years ever since I was first introduced to the Kentico platform, which gave me a very good reason to move from BlogEngine. I wanted my web presence to be more than just a blog that would give me the flexibility to be something more. I do not like the idea of being restricted to just one feature-base.

    As great as it is running my website on Kentico CMS, it’s too big of an application for my needs. Afterall, I am just using the content-management functionality and none of the other great features the platform offers, so it’s good time to start thinking of downsizing and reduce running costs. Headless seems the most suitable option right?

    I won’t be going into detail on what headless is. The internet contains information on the subject matter detailed in a more digestable manner over the years suitable for varied levels of technical expertise. “Headless CMS” is the industry buzz-word that clients are aware of. You can also take a read of a Medium post I wrote last year about one type of headless platform - Kentico Cloud (now named Kontent) and the market.

    So why haven’t I made the move to Headless CMS? I think it comes down to following factors:

    • Pricing
    • Infrastructure and stability
    • Platform changes
    • Trust

    Pricing

    First and foremost, it’s the price. I am aware that all Headless CMS providers have a free or starter tier, each with their own defined limitations whether that be the number of API requests or content limits. I like to look into the future and see where my online presence may take me and at some point, I would need to consider the cost of a paid tier. How does that fit into my yearly hosting costs?

    At the moment, I am paying £80 yearly. If I were to jump onto headless, the cheapest price I’ve seen equates to £66 a year and I haven’t factored in hosting costs yet. I could get away with low-cost hosting as my web build will be on a smaller scale and I plan my next build using the .NET Core framework.

    If I had my own company or product where I was looking for ways to deliver content across multiple channels, I would use headless in a heartbeat. I could justify the cost as I know I would be getting my money’s worth and if I were to find myself exceeding a tiers limit I could just move onto the next.

    Infrastructure and Stability

    Infrastructure and stability of a headless service all come down to how much you’re willing to pay. The API uptime is the most important part after the platform features. I’ve noticed that some starter and free tiers do not state an uptime, for example, 99.9% or 99.5%. Depending on the technology stack, this might not be an issue where a constant connection to the API is required, for example, Gatsby.

    I do think in this area where Headless CMS wins, is the failover and backup procedures in place. They would more than likely surpass the infrastructure in place from a personally hosted and managed site.

    Platform Changes

    It’s natural for improvements and changes to be made throughout the lifespan of a product. The only thing with headless you don’t have a choice on whether you want those changes as what works for one person may not necessarily work for another. You are locked into the release cycle.

    I remember back in the early days when Headless CMS’s started to gain traction, releases were being made in such a quick turnaround at the expense of the editors who had to quickly adapt to the subtle changes in features. The good thing now is the dust has settled as the platform has gotten to the point of maturity.

    The one area I still have difficulty getting over is the rich-text area. Each headless CMS provider seems to have their restrictions and you never really get full control over HTML markup unless a normal text area is used. There are ways around this but some restrictions still do exist.

    Where do you as an individual fit into this lifecycle? That’s the million-dollar question. However, there is one headless platform that is very involved with feedback from their users, Kentico Kontent, where all ideas are put under consideration, voted on and (if successful) submitted into the roadmap. I haven’t seen this approach offered by other Headless CMS platforms and maybe this is something they should also do.

    Trust

    There is a trust aspect to an external provider storing your content. Data is your most valuable asset. Is there any chance in the service being discontinued at some-point? If I am being totally honest to myself, I don’t think this is a valid point as long as the chosen platform has proven it’s worth and cemented itself over a lengthy period of time. Choose the big players (in no particular order), such as:

    • Kontent
    • Contentful
    • Prismic
    • DatoCMS
    • ButterCMS

    There is also another aspect to trust that draws upon a further point I made in the previous section regarding platform changes. In the past, I’ve seen content features getting deprecated. This doesn’t break your current build, just causes you to rethink things when updating to the newer version API interface.

    Conclusion

    I think moving to a Headless CMS requires a bigger leap than I thought. I say this purely from a personal perspective. The main piece of work would be to carry out content modelling for pages, migrate all my site content and media into the new platform and apply page redirects. This is before I have made a start in developing the new site.

    I will always be in two minds on whether I should use a Headless CMS. If I wasn’t such a control-freak when it comes to every aspect of my application and content, I think I could make the move. Maybe I just need to learn to let go.

  • Published on
    -
    2 min read

    ASP.NET Core - Get Page Title By URL

    To make it easy for a client to add in related links to pages like a Blog Post or Article, I like implementing some form of automation so there is one less thing to content manage. For a Kentico Cloud project, I took this very approach. I created a UrlHelper class that will carry out the following:

    • Take in an absolute URL.
    • Read the markup of the page.
    • Selects the title tag using Regex.
    • Remove the site name prefix from title text.
    using Microsoft.Extensions.Caching.Memory;
    using MyProject.Models.Site;
    using System;
    using System.IO;
    using System.Linq;
    using System.Net;
    using System.Text.RegularExpressions;
    
    namespace MyProject.Helpers
    {
        public class UrlHelper
        {
            private static IMemoryCache _cache;
    
            public UrlHelper(IMemoryCache memCache)
            {
                _cache = memCache;
            }
    
            /// <summary>
            /// Returns the a title and URL of the link directly from a page.
            /// </summary>
            /// <param name="url"></param>
            /// <returns></returns>
            public PageLink GetPageTitleFromUrl(string url)
            {
                if (!string.IsNullOrEmpty(url))
                {
                    if (_cache.TryGetValue(url, out PageLink page))
                    {
                        return page;
                    }
                    else
                    {
                        using (WebClient client = new WebClient())
                        {
                            try
                            {
                                Stream stream = client.OpenRead(url);
                                StreamReader streamReader = new StreamReader(stream, System.Text.Encoding.GetEncoding("UTF-8"));
    
                                // Get contents of the page.
                                string pageHtml = streamReader.ReadToEnd();
    
                                if (!string.IsNullOrEmpty(pageHtml))
                                {
                                    // Get the title.
                                    string title = Regex.Match(pageHtml, @"\<title\b[^>]*\>\s*(?<Title>[\s\S]*?)\</title\>", RegexOptions.IgnoreCase).Groups["Title"].Value;
    
                                    if (!string.IsNullOrEmpty(title))
                                    {
                                        if (title.Contains("|"))
                                            title = title.Split("|").First();
                                        else if (title.Contains(":"))
                                            title = title.Split(":").First();
    
                                        PageLink pageLink = new PageLink
                                        {
                                            PageName = title,
                                            PageUrl = url
                                        };
    
                                        _cache.Set(url, pageLink, DateTimeOffset.Now.AddHours(12));
    
                                        page = pageLink;
                                    }
                                }
    
                                // Cleanup.
                                stream.Flush();
                                stream.Close();
                                client.Dispose();
                            }
                            catch (WebException e)
                            {
                                throw e;
                            }
                        }
                    }
    
                    return page;
                }
                else
                {
                    return null;
                }
            }
        }
    }
    

    The method returns a PageLink object:

    namespace MyProject.Models.Site
    {
        public class PageLink
        {
            public string PageName { get; set; }
            public string PageUrl { get; set; }
        }
    }
    

    From an efficiency standpoint, I cache the process for 12 hours as going through the process of reading the markup of a page can be quite expensive if there is a lot of HTML.

  • For one of my side projects, I was asked to use Butter CMS to allow for basic blog integration using JavaScript. I have never heard or used Butter CMS before and was intrigued to know more about the platform.

    Butter CMS is another headless CMS variant that allows a developer to utilise API endpoints to push content to an application via an arrange of approaches. So nothing new here. Just like any headless CMS, the proof is in the pudding when it comes to the following factors:

    • Quality of features
    • Ease of integration
    • Price points
    • Quality of documentation

    I haven't had a chance to properly look into what Butter CMS fully has to offer, but from what I have seen from working on the requirements for this side project I was pleasently surprised. Found it really easy to get setup with minimal amount of fuss! For this project I used Butter CMS's Blog Engine package, which does exactly what it says on the tin. All the fields you need for writing blog posts are already provided.

    JavaScript Code

    My JavaScipt implementation is pretty basic and provides the following functionality:

    • Outputs a list of posts consisting of title, date and summary text
    • Pagination
    • Output a single blog post

    All key functionality is derived from the "ButterCMS" JavaScript file:

    /*****************************************************/
    /*                    Butter CMS                                 */
    /*****************************************************/
    var ButterCMS =
    {
        ButterCmsObj: null,
    
        "Init": function () {
            // Initiate Butter CMS.
            this.ButterCmsObj = new ButterCmsBlogData();
            this.ButterCmsObj.Init();
        },
        "GetBlogPosts": function () {
            BEButterCMS.ButterCmsObj.GetBlogPosts(1);
        },
        "GetSinglePost": function (slug) {
            BEButterCMS.ButterCmsObj.GetSinglePost(slug);
        }
    };
    
    /*****************************************************/
    /*                Butter CMS Data                         */
    /*****************************************************/
    function ButterCmsBlogData() {
        var apiKey = "<Enter API Key>",
            baseUrl = "/",
            butterInstance = null,
            $blogListingContainer = $("#posts"),
            $blogPostContainer = $("#post-individual"),
            pageSize = 10;
    
        // Initialise of the ButterCMSData object get the data.
        this.Init = function () {
            getCMSInstance();
        };
    
        // Returns a list of blog posts.
        this.GetBlogPosts = function (pageNo) {
            // The blog listing container needs to be cleared before any new markup is pushed.
            // For example when the next page of data is requested.
            $blogListingContainer.empty();
    
            // Request blog posts.
            butterInstance.post.list({ page: pageNo, page_size: pageSize }).then(function (resp) {
                var body = resp.data,
                    blogPostData = {
                        posts: body.data,
                        next_page: body.meta.next_page,
                        previous_page: body.meta.previous_page
                    };
    
                for (var i = 0; i < blogPostData.posts.length; i++) {
                    $blogListingContainer.append(blogPostListItem(blogPostData.posts[i]));
                }
    
                //----------BEGIN: Pagination--------------//
    
                $blogListingContainer.append("<div>");
    
                if (blogPostData.previous_page) {
                    $blogListingContainer.append("<a class=\"page-nav\" href=\"#\" data-pageno=" + blogPostData.previous_page + " href=\"\">Previous Page</a>");
                }
    
                if (blogPostData.next_page) {
                    $blogListingContainer.append("<a class=\"page-nav\" href=\"#\" data-pageno=" + blogPostData.next_page + " href=\"\">Next Page</a>");
                }
    
                $blogListingContainer.append("</div>");
    
                paginationOnClick();
    
                //----------END: Pagination--------------//
            });
        };
    
        // Retrieves a single blog post based on the current URL of the page if a slug has not been provided.
        this.GetSinglePost = function (slug) {
            var currentPath = location.pathname,
                blogSlug = slug === null ? currentPath.match(/([^\/]*)\/*$/)[1] : slug;
    
            butterInstance.post.retrieve(blogSlug).then(function (resp) {
                var post = resp.data.data;
    
                $blogPostContainer.append(blogPost(post));
            });
        };
    
        // Renders the HTML markup and fields for a single post.
        function blogPost(post) {
            var html = "";
    
            html = "<article>";
    
            html += "<h1>" + post.title + "</h1>";
            html += "<div>" + blogPostDateFormat(post.created) + "</div>";
            html += "<div>" + post.body + "</div>";
            
            html += "</article>";
    
            return html;
        }
    
        // Renders the HTML markup and fields when listing out blog posts.
        function blogPostListItem(post) {
            var html = "";
    
            html = "<h2><a href=" + baseUrl + post.url + ">" + post.title + "</a></h2>";
            html += "<div>" + blogPostDateFormat(post.created) + "</div>";
            html += "<p>" + post.summary + "</p>";
    
            if (post.featured_image) {
                html += "<img src=" + post.featured_image + " />";
            }
    
            return html;
        }
    
        // Set click event for previous/next pagination buttons and reload the current data.
        function paginationOnClick() {
            $(".page-nav").on("click", function (e) {
                e.preventDefault();
                var pageNo = $(this).data("pageno"),
                    butterCmsObj = new ButterCmsBlogData();
    
                butterCmsObj.Init();
                butterCmsObj.GetBlogPosts(pageNo);
            });
        }
    
        // Format the blog post date to dd/MM/yyyy HH:mm
        function blogPostDateFormat(date) {
            var dateObj = new Date(date);
    
            return [dateObj.getDate().padLeft(), (dateObj.getMonth() + 1).padLeft(), dateObj.getFullYear()].join('/') + ' ' + [dateObj.getHours().padLeft(), dateObj.getMinutes().padLeft()].join(':');
        }
    
        // Get instance of Butter CMS on initialise to make one call.
        function getCMSInstance() {
            butterInstance = new Butter(apiKey);
        }
    }
    
    // Set a prototype for padding numerical values.
    Number.prototype.padLeft = function (base, chr) {
        var len = (String(base || 10).length - String(this).length) + 1;
    
        return len > 0 ? new Array(len).join(chr || '0') + this : this;
    };
    

    To get a list of blog posts:

    // Initiate Butter CMS.
    BEButterCMS.Init();
    
    // Get all blog posts.
    BEButterCMS.GetBlogPosts();
    

    To get a single blog post, you will need to pass in the slug of the blog post via your own approach:

    // Initiate Butter CMS.
    BEButterCMS.Init();
    
    // Get single blog post.
    BEButterCMS.GetSinglePost(postSlug);
    
  • There are many things that impress me about Kentico, especially when I compare my experiences to other CMS providers from previous walks of life. But the one thing that impresses me above all is how easy the guys at Kentico make upgrading to newer versions of their CMS platform. So I wasn't daunted when I had the job to upgrade a site from Kentico 5.5 all the way up to 8.2.

    Everything went smoothly. I was in the last leg of the upgrade process where the site had been upgraded to version 7 and was about to make the transition to 8. At this point, I started encoutering issues...

    Upgrading from version 7 to 8 alone is a very big jump and you will find that getting your site fully functional will require more effort than all the previous upgrades combined - depending on the size and complexity of your Kentico instance. Take a look at the "Upgrade Overview" section in the Kentico upgrade documentation for a list of important changes.

    I decided to list some quite important steps based upon information I have collated from issues others have experienced as well as key points covered within the Kentico Upgrade documentation. Following the points listed below resolved my upgrade issues, so it will more than likely help you too.

    1) Clear Browser Cache

    After each upgrade, remember to always clear your browser of all temporary files stored in cache and old cookies prior to logging into the Administration Area. Otherwise you will more than likely see a mish-mash of old/new graphical elements, as well as an Internal Server Error popup.

    Kentico 8 Upgrade - Internal Server Error

    2) Run The Site After Each Upgrade

    This is something I've had a tendency to forget. It is imperative that you run the site after each upgrade before moving onto the next, since Kentico requires code to be executed as well as database tasks.

    3) Update Macro Signatures

    This is an easy one. You'll probably see a bunch of Macro security errors in Kentico's Event Log post upgrade like these:

    Kentico 8 Upgrade - Macro Resolver Error

    Luckily, this is easily resolved by simply updating the macro signatures in the System > Macros > Signatures area of within the CMS Administration.

    Kentico 8 Upgrade - Sign Macros

    The system then resigns all macros. The new security signatures of all macros contain the username of your administrator account.

    4) Re-save All Page Types

    This is a strange one. For some odd reason, I experienced the same Internal Server Error popup message when logged into the CMS as described in point 1. In addition, I found when attempting to navigate directly to the website, I would get an Object not set to an instance of an object.NET error whenever a "DocumentContext.CurrentDocument" call was made.

    So I decided to randomly try something Kentico master Juraj suggested from one of his forum responses, which was to add and then remove a field from a document type. Instead, I just went to the Field section of each Page Type and clicked the "Save" button.

    I have no idea what difference this makes within the Kentico setup but this seems to do the trick.

    5) Custom Modules Created In Version 7

    If you have developed any custom modules, ensure you have marked them as "custom" before upgrading to version 8. I had numerous upgrade failures when Kentico Installation Manager was trying to upgrade the database. The error occurred in the CMS_UIElement table due to duplicated Element Resource ID's.

    You can mark your custom module as "custom" in version 7 by going to: Site Manager > Development > Modules > Your Custom Module > User Interface.

    Kentico 7 - Setting Element Is Custom

    6) Check Data & DB Versions

    After you have run an upgrade for each major version (6.0, 7.0, 8.0, 8.2), make sure you run the following SQL query against your Kentico database:

    SELECT
        KeyName, KeyValue
    FROM
        CMS_SettingsKey
    WHERE
        KeyName IN ('CMSDBVersion', 'CMSDataVersion')
    

    If both values for "CMSDBVersion" and "CMSDataVersion" are the same, you know the upgrade has successfully completed and you're on the right track. When I made my first attempt to upgrade a site from 7 to 8, I found the Data Version was 7.0 and the DB Version was 8.2. Not good.

    Useful Links

  • Published on
    -
    4 min read

    What Prismic.io Is Lacking

    WARNING! I may sound like an absolute hypocrite when the contents of this post is compared to my earlier post on first impressions of the Prismic.io platform. So here we go...

    I am starting to encounter increasingly longwinded and somewhat frustrating stumbling blocks during the development of a Prismic.io powered website due to lack of basic development related features. Fundamental features that should already be there from the start.

    I understand that Prismic.io is a new platform and is still in its infancy, but not having something simple as a time attribute to a date field is unforgivable (which I will explain later).

    The idea behind Prismic.io is to empower the developer and gives them the tools to manage the content anyway they want. Sounds great! But how can developers like myself be empowered when the tools that are provided are not up to scratch.

    So I have picked a few things lacking in the Prismic.io platform. I'll probably add some more on completion of the project I'm working on.

    1) Sorting By Date/Time

    Now you'd think if you have a date field, a time field would be not too far away. Wrong! A document only contains a date format field that shows a calendar on selection. This works for general use. But what if you have numerous articles written in a day that are displayed on a page in descending order and you wish to move an article higher up the page? There is no time field to allow for this.

    By default when using date ordering, two things happen:

    1. All documents are ordered by the date value defined in the document.
    2. If multiple documents added within a day, they are then ordered by the time it was added in Prismic.

    For me, this was a pain.

    2) Non-match predicate

    Sometimes, you want the ability to exclude documents from a query. In my case, return a list of authors except for one or two. Since Prismic.io predicate language is lacking a "not" operator I had to return a full list of authors and carry out the filtering at application level.

    In the grand scheme of things, this isn't a massive flaw. I can see this becoming an issue when you need to exclude items from a larger dataset. It would be faster to do this at Prismic level than application level.

    3) Where's the "OR" Operator?

    No really, I would like to know!

    4) No Required or Validation Fields

    It is not possible to make fields compulsory or implement any form of validation. Therefore, up to the developer to make sure suitable checks are put in place where null or incorrect values are present.

    To me, this seems a little bit backwards and you're solely relying on the editors to ensure the all data is correct and complete.

    5) WYSIWYG Editor Improvements

    As I stated in my previous post, that one of main deciding factors to why I used Prismic over Contentful was its easy to use WYSIWYG editor. I still stand by this point. It seems to offer a mish-mash of features that feel very intelligent and basic at the same time.

    The WYSIWYG functionality is based on a StructuredText field type, flexible enough to allow an amalgamation of different content, such as embedded object (from social websites), paragraphs, images, etc.

    On the surface, StructuredText is really nice to work with but then all of a sudden you encounter a key missing feature: blockquote! The only way I could get around this is by getting editors to insert custom mark up around any text for transformation into a blockquote at application level, like so:

    [BlockQuote][Hello. I would like to blockquote this text please.]
    

    This was just the start. There were other instances where further customisation had to be made to meet the editors requirements.

    I have to quote Paul Dijou here (link at bottom of post) for describing the additional changes he too had to make in a very theatrical manner:

    A writer wanted to have blockquotes: a whole paragraph should be displayed in a custom design and have an author. I had to kill him really fast and bury his body deep. Another one wanted semantic distinction between paragraphs, something like: this one should be red and this one blue just because. Thrown him into a bucket full of piranhas.

    6) Technical Support

    A platform or technology can only ever be as successful as the infrastructure present to support it. Without it, cracks will form. Currently, there is only one place you can ask a question: https://qa.prismic.io. It's definitely no StackOverflow. You really have to hope and pray for someone to answer your question promptly.

    7) Convoluted Production Workflow

    There will come a time when additional changes to a live site will be required. Whether it be modifications to a field or addition for a new document. All these changes will have to happen on the live Prismic repository. There is no development > stage > live workflow.

    It would be nice to have the ability to duplicate repositories and push new releases.

    Thankfully, someone has already raised this. I don't see this addition happening anytime soon.

    Summary

    My intention is not to give a very negative impression of the Prismic.io platform. It will most likely meet your content management needs. However, it does have its faults and unless modifications are made to some of the points raised from others in their Q&A forum and my post, I will have to question whether I use it again on a project by project basis. It's a CMS platform that just falls short of the mark.

    I recommend reading the following blog post written by Paul Dijou, describing his own experiences working with Prismic: http://platformpauldijou.fr/blog/2014/07/17/prismicio-when-happiness-met-disappointment.

    NOTE: If I have stated something that I have got completely wrong due to a lack of understanding. Let me know and I'll take everything back! :-)

  • Welcome to my new and improved website built in Kentico 8 and MVC Razor 5.

    My old site was crying for an upgrade and now seemed like a good opportunity to make quite a few modifications, such as:

    • Upgrading to Kentico 8
    • Ditch ASP.NET Web Forms for MVC Razor 5
    • Refresh the front-end (designed by yours truly!) ;-)
    • Responsive support using Bootstrap
    • Refactored all code to improve website performance and caching

    The new build has been a bit of a pet project and allowed me to put into practice everything I've learnt from over the years since my last build.

    Still work in progress and more refinements are in the pipeline.

  • Generally, all Content Management Systems are tightly integrated into the websites they control to serve one key function: publish custom content. Almost as one singular entity. From the moment you choose a CMS, you shall be forever locked down by its required platform and technology.

    So in terms of the CMS world, nothing revolutionary has happened to change our perception otherwise...until now...

    I have been doing some research into some content management systems that sits externally from a platform (such as a website), giving you freedom to manage the content however you like and it something that's gaining a lot of traction. I am starting to see why.  In fact, I'm in the middle of building a site using one of these "externally" managed CMS platforms.

    I would say the the main market players are Contentful and Prismic. They both are very similar in the features they provide and do a great job in delivering content to a platform of your choice through simply querying their native API's to return a nice JSON feed. So from a development perspective, they're both just as easy to integrate as each another and the deciding factors on the one you choose will primarily be:

    • Price
    • Ease of use
    • Editor features

    Based on these factors alone, I found Prismic to be the ideal candidate to fulfill my clients needs and adding content was a pleasure. It probably has the nicest interface I've seen in a long time. Very quick, easy and has something Contentful didn't have: a nice WYSIWYG editor. The markdown editor alone in Contentful was a deal breaker and I feared it would add an additional learning curve for non-technical clients.

    The only strange thing I noticed about Prismic was that you cannot add any form of validation or set a field to be required. Hopefully, this is something they will add to future releases. When you have other great features like an easy image upload to Amazon Cloud for resizing and cropping, having no validation isn't all that important. :-)

    I am already more than halfway through my first Prismic managed website and the implementation couldn't be easier with the help of their forum and starter projects in the technology of your choice.

    One of the fears I did have whilst implementing Prismic was how well will my pages load on high demand, especially when the content itself is external from the website. Would there be issues or delays in sending content to my platform? I guess this question is still yet to be answered. So far, the page speed has been better than expected (based on initial testing).

    Prismic in a nutshell (stolen from their website):

    prismic.io is a developer friendly, API-based approach to CMS. It features a Writing Room for content writers to author, manage and store content, and a Content Query API for developers to integrate managed content. Your content doesn't live "in a website / in websites", your project doesn't live "in a CMS"; rather, your content lives in one place and is shared across your websites, and your project lives absolutely anywhere you want.

  • Kentico LogoFor many years, I've been a happy BlogEngine user. However, recently my website was starting to expand in a way that wasn't flexible enough for the BlogEngine platform. Don't get me wrong, BlogEngine is a great blogging platform and it is without a doubt one of the best out on the market. But the capabilities and features Kentico provides made moving over to another platform an easy decision.

    The future of my site needed something that would give me free reign and control on making full customisations myself in a solid framework, and Kentico seemed to fit this requirement.

    Having worked with the Kentico platform for quite a few years now, I was impressed by how easy or complex I could make a site. Most importantly, the page perfomance of my site has got quite a boost. For a site that doesn't look like is doing much at face value, it is behind the scenes.

    What was the migration process like?

    Migrating all my BlogEngine content into Kentico did take some time, but the Kentico Import tool really does take the hassle out of getting key blog post information into the CMS. Just don't be expect tags and categories to be imported in the process. Migrating these facets is a manual job.

    In addition, I decided to overhaul the friendly URL's used for my blog posts in keeping with the URL structure provided by BlogEngine. Even to this day, I'm not sold on the way Kentico generates it's friendly URL's for blog posts. For example:

    /Blog/February-2013/My-Blog-Post.aspx
    

    When it should be the following format:

    /Blog/2013/02/03/My-Blog-Post.aspx
    

    Luckily, it was pretty easy to write a Custom Eventhandler to add additional custom URL paths whenever I update or insert a new post (will add a post in the near future on how to do this).

    I still have some additional features to add to this site (and dare I say fixes!) so watch this space...