Creating Custom Theme

This is a walk-through on how to build custom theme for BlogEngine.NET from scratch. In this example, version 3.1 was used, but should work with later versions too.

1. Theme folder

Start by adding new folder: "/Custom/Themes/Test". As soon as folder added, we can go to admin -> settings and select it as our theme folder.

With new theme set as current in settings, it will display in the list similar to below.

As you can see, theme entry only has a title, which is a folder name. There is no version or author and theme icon is generic. To fix this, we need to provide BlogEngine with some meta data.

2. Theme.xml

To provide meta data for new theme, create new XML file inside theme folder called "theme.xml". Content as in snippet below, most fields are self-explaining. The "iconurl" is a path to external image URL if you want to use image from the web.

<?xml version="1.0"?>
<metadata>
    <id>Test</id>
    <description>Testing theme</description>
    <authors>Tester</authors>
    <website></website>
    <version>3.0.0.1</version>
    <iconurl></iconurl>
</metadata>

3. Theme icon/screenshot

To use local picture, save image you want to use inside theme folder. Image can be "theme.png" or "theme.jpg".

With meta data and image set, we should see theme entry in the list looking like above. By now, in the admin UI all looks good. But if you go to the blog, you'll see empty page. This is, because our theme does not have any templates telling BlogEngine what we want to display.

4. site.master page

Create file "site.master" inside theme folder. The required elements for this file are "cphBody" content placeholder where BlogEngine will inject posts, as well as head and form (both used for server-side processing). Page menu is optional, it will add main blog menu so we can navigate around.

<%@ Master Language="C#" AutoEventWireup="true" %>
<!DOCTYPE html>
<html lang="en">
<head runat="server"></head>
<body>
  <form runat="Server">
    <blog:PageMenu ID="pageMenu" runat="server" />
    <asp:ContentPlaceHolder ID="cphBody" runat="server" />
  </form>
</body>
</html>

5. Default templates

When you save code snippet above in the theme folder as "site.master", you should be able to navigate to the blog and see list of posts. Here I have two posts with very minimal content, both displayed along with post titles.

Clicking post title will load post detail with comment form, all fully functional. So at this point we basically have a simple but working blog. Add styles to make it look pretty, add few nice pictures and all opened for business. You can post articles, people can read posts, write comments, subscribe to RSS feed and so on.

This is possible because BlogEngine uses default templates behind the scene when it can't find specific template in the theme folder. Default templates under "/Custom/Controls/Defaults", they very minimalistic and used only as fallback, but if that fit your needs, your theme can be really that simple.

Most times, however, designer would want to make lots of changes to produce trully custom theme, with specific layout and elements missing in super simple default templates. To do that, theme folder need to include template it wants to override, and BlogEngine will use it instead.

6. Overriding template

To understand how it works, copy "/Custom/Controls/Defaults/PostView.ascx" to "/Custom/Themes/Test". This template looks like this.

<%@ Control Language="C#" AutoEventWireup="true" EnableViewState="false" Inherits="BlogEngine.Core.Web.Controls.PostViewBase" %>
<article class="post" id="post<%=Index %>">
  <h2>
    <a href="<%=Post.RelativeOrAbsoluteLink %>">
      <%=Server.HtmlEncode(Post.Title) %>
    </a>
  </h2>
  <asp:PlaceHolder ID="BodyContent" runat="server" />
</article>

To make a point, lets add few useful elements.

<%@ Control Language="C#" AutoEventWireup="true" EnableViewState="false" Inherits="BlogEngine.Core.Web.Controls.PostViewBase" %>
<article class="post" id="post<%=Index %>">
  <div class="post-data">
    <%=Post.DateCreated.ToString("MMMM d. yyyy") %>
  </div>
  <h2>
    <a href="<%=Post.RelativeOrAbsoluteLink %>">
      <%=Server.HtmlEncode(Post.Title) %>
    </a>
  </h2>
  <div class="post-tags">
    <%=Resources.labels.tags %> : <%=TagLinks(", ") %>
  </div>
  <asp:PlaceHolder ID="BodyContent" runat="server" />
  <%=AdminLinks %>
</article>

Updated template has date on top of the title, post tags below and admin links at the bottom. BlogEngine will use this template now instead of default and post should look similar to this. So much better, right? :)

7. Adding styles

Ok, may be not much better. Let’s add some styles to make it look like an actual theme. Create file "style.css" inside theme folder. To register it with master page, add a reference. I also added couple common elements like blog name for a header and copyright at the bottom. The final site.master now looks like this.

<%@ Master Language="C#" AutoEventWireup="true" %>
<%@ Import Namespace="BlogEngine.Core" %>
<!DOCTYPE html>
<html lang="en">
<head runat="server">
  <link href="style.css" rel="stylesheet" />
</head>
<body>
<form runat="Server">
  <h1>
    <a href="<%=Utils.AbsoluteWebRoot %>">
      <%=BlogSettings.Instance.Name %>
    </a>
  </h1>
  <blog:PageMenu ID="pageMenu" runat="server" />
  <hr/>
  <asp:ContentPlaceHolder ID="cphBody" runat="server" />
  <p class="credit">
    Copyright © <%=DateTime.Now.Year %> 
    <a href="<%=Utils.AbsoluteWebRoot %>">
      <%=BlogSettings.Instance.Name %>
    </a>
  </p>
</form>
</body>
</html>

And when stylesheet applied to the site, it should look like this. Not a masterpiece obviously, but it provides usable and functional blog with very little effort.

The “Test” theme used in this example can be downloaded from link below. It is not 100% completed and not intended to be used as actual blog theme, it is just a sample to demonstrate basic concepts for building theme from scratch. Next article will use it to present more advanced topics.

Test.zip (143.5KB)


Comments are closed