If you found value in this post, consider following me on X @davidpuplava for more valuable information about Game Dev, OrchardCore, C#/.NET and other topics.
(skip to the next section to dive straight into the technical details)
I have a renewed desire to blog consistently about software and technology. My hope is two fold: first, to help others learn about the technology I'm most passionate about; and two, in doing so to gain a deeper understanding about that technology.
My current obsession is with Orchard Core, a framework built atop ASP.NET and .NET that provides a content management system as well as a modular first approach to software architecture. Right now, I'm working my way through the content management features of Orchard Core to more deeply understand its capabilities and to experience how a less technical creator might use it to say launch a new blog.
In fact, my own blog here is built and managed using Orchard Core - I recently migrated from a custom .NET web application I built and attempted to turn into my own content management system. Once I learned about Orchard core, I realized it aligned exactly with my needs and desires. So far the experience has been very positive.
A popular tip from twitter on how to grow an audience for your blog or newsletter suggests putting a so-called "call to action" at the end of your post whether it be a blog post or twitter thread. It invites the reader to engage with you in some way and learn more about the information you're providing. I noticed my own blog posts were ending with the same, "For more information, follow me on twitter..." section that invited the reader to interact with me on twitter. You can scroll to the bottom of this post and see it.
If like me you grow tired of copying and pasting the same call to action at the end of every blog post, read on - there is a solution to this problem. With Orchard Core, you can use a feature called Widgets to automatically put content on certain parts of your site so you don't need to manually copy/paste it to every content item.
In short, you need to do the following things to automatically add a call to action to the end of every blog post in Orchard Core. Note that there are multiple ways to achive this affect, and this way allows you to do so without any custom code.
If you need or want to learn more about the widgets feature in Orchard Core, you can read the documentation.
If you need or want to know about Orchard Core in general, you can also... read the documentation.
TheBlogTheme does not by default provide a zone between the Content
and the Footer
zones. You need to provide that yourself. If you have your own theme that uses TheBlogTheme as it's base, you can simply override the default Layout in your own Layout.cshtml
or Layout.liquid
template. If you're like me and want to avoid your own theme as much as possible, you can override the layout through the Admin UI using the Templates
feature which allows you to override templates in your active theme.
Read more about templates in the Orchard Core documentation.
Log in to the Admin UI and navigate to Design
->Templates
- if you don't see that options you must find/enable the Templates
feature under Configuration
->Features
page.
Click Add Template
and give it a Name
value of Layout
. It's important that Layout
is used for the name because that is how Orchard Core will know to use your template as an alternative to the default Layout from TheBlogTheme.
Copy and paste the following code into the Content
section of your new Layout
template.
<!DOCTYPE html>
<html lang="{{ Culture.Name }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>{{ "PageTitle" | shape_new | shape_stringify }}</title>
{% resources type: "Meta" %}
{% link type:"image/x-icon", rel:"shortcut icon", href:"~/TheBlogTheme/favicon.ico" %}
<!-- Font Awesome icons (free version)-->
{% style name:"font-awesome", version:"6", at:"Head" %}
<!-- Google fonts -->
<link href='https://fonts.googleapis.com/css?family=Lora:400,700,400italic,700italic' rel='stylesheet' type='text/css'>
<link href='https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800' rel='stylesheet' type='text/css'>
<!-- Core theme CSS (includes Bootstrap) -->
{% style name:"theblogtheme" %}
{% style name:"theblogtheme-bootstrap-oc", version:"1" %}
{% script name:"theblogtheme", at:"Foot" %}
{% resources type: "HeadScript" %}
{% resources type: "HeadLink" %}
{% resources type: "Stylesheet" %}
{% render_section "HeadMeta", required: false %}
</head>
<body dir="{{ Culture.Dir }}">
<nav class="navbar navbar-expand-lg navbar-light" id="mainNav">
<div class="container px-4 px-lg-5">
<a class="navbar-brand" href="{{ '~/' | href }}">{{ Site.SiteName }}</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarResponsive" aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation">
<span class="sr-only">{{ "Toggle navigation" | t }}</span>
{{ "Menu" | t }} <i class="fa fa-bars" aria-hidden="true"></i>
</button>
{% shape "menu", alias: "alias:main-menu", cache_id: "main-menu", cache_fixed_duration: "00:05:00", cache_tag: "alias:main-menu" %}
</div>
</nav>
{% render_section "Header", required: false %}
<div class="container px-4 px-lg-5 mb-4">
<div class="row gx-4 gx-lg-5 justify-content-center">
<div class="col-md-10 col-lg-8 col-xl-7">
{% render_section "Messages", required: false %}
{% render_body %}
{% render_section "AfterContent", required: false %}
</div>
</div>
</div>
<footer class="border-top">
{% render_section "Footer", required: false %}
</footer>
{% resources type: "FootScript" %}
</body>
</html>
This is a modified version of the TheBlogTheme's default Layout template. The notable difference is the extra section named AfterContent
which appears after the render_body
section.
{% render_section "AfterContent", required: false %}
Click Save
.
This effectively creates a new zone named AfterContent
in which you can place your call to action widget.
Also note, you may want to check the Orchard Core source code to ensure the default layout of TheBlogTheme has not changed since the time of this writing. If it has, then you need to copy/paste that version. You may want to check if any new zones have already been added.
You can view the latest version here on GitHub because Orchard Core is open source.
Orchard Core provides a wide breadth of features that you'd expect from a content management system. And these modular features come together to provide great power in customizing its content.
The next step is to create a new layer that will be active for all the blog posts on your site but not the other pages of your site.
On the Design
->Widgets
page, click the Add
button under the Layers
section to add the new layer. Give the new layer a meaningful name like Blog Post CTA
(for call to action).
Next, click Add
next ot the Rules
section of the Edit Layer
page to tell Orchard Core under what conditions the layer should be active and visible. Specifically, find the Content type condition
and click Add
.
You should now see the Edit Rule
page where you can define the rule conditions. Enter Equals
and BlogPost
as values for the the Operation
and Value
fields, respectively.
Click Save
- you now have a new Blog Post layer you can use in conjunction with your new AfterContent
zone. With them you can create your new call to action widget to automatically display on every blog post.
Navigate back to the Design
->Widgets
page where you can add widgets to your zones. You will notice (assuming you haven't already done the following step) that your AfterContent
zone is not there underneath the Content
and Footer
zones. This is because you need to enable your new zone in the widget settings.
Navigate to Design
->Settings
->Zones
which gives you a "Available zones for Layers" field to configure which zones are available for use in Layers. Add AfterContent
to this list. You should see the following assuming you currently only have the default set of zones that come with TheBlogTheme.
Content, Footer, AfterContent
Navigate back to the Design
->Widgets
screen and see your AfterContent
zone is now available to add widgets.
Click Add Widget
and choose Paragraph
which allows you add the content for your call to action. For title, enter something meaningful like CTA - Follow on Twitter
, leave the Render title
box unchecked. For The layer the widget should be associated with.
select your Blog Post CTA
layer you added in the previous step. In Content
put your call to action - notice you have a WYSIWYG editor to make it easy to format HTML, add links, etc.
As an example, you can add something like the following (obviously use your own twitter handle).
If you found value in this post, consider following me on twitter @davidpuplava for more valuable information about software and other topics.
Then highlight the twitter handle, click the insert link button of the WYSIWYG editor and enter your twitter profile URL into the URL field.
Another option is to add a "Subscribe to my newsletter" call to action which I will demonstrate in a future post.
Note: You can also use the RawHtml
widget rather than the Paragraph
widget and just write the HTML with the <a href...></a>
tag yourself. I chose Paragraph
because it is more user friendly for a non-technical creator.
Click Save
and then Actions
->Publish Draft
for your new widget.
Navigate to one of your blog posts and see your call to action at the end of the post!
You may notice however that the indentation does not match the rest of the blog post. We will fix that in the next section.
The widget is published with its own wrapper HTML tags and classes that allows for the display of title and other styling. The Widget documentation (linked here) indicates that a common task is to remove the Widget wrapper tags. You can do this using the Templates
feature just like you did before with overriding the Layout
template to add the AfterContent
zone.
Naviate to Design
->Templates
and click Add Template
. The Name
should be the following to exactly match the widget in the AfterContent
zone.
Widget_Wrapper__Zone__AfterContent
Note: there is a single underscore between "Widget" and "Wrapper" but a double underscore before "Zone" and before "AfterContent". This follows the conventions that Orchard Core uses to identify the specific conditions for when the template is overriden. More information on overriding templates can be found in the documentation.
In the Content
field, simply add the following.
{{ Model.Content | shape_render }}
Click the Save
button.
And that's it! You should now see your call to action at the end of every blog post.
If you look at the text just below the tags on this blog post, you'll see my call to action. This is automatically added to every blog post using the method described in this post.
If you found value in this post, consider following me on X @davidpuplava for more valuable information about Game Dev, OrchardCore, C#/.NET and other topics.