
Learning by Doing: How to Create Common Layout Components in Optimizely CMS (Header, Footer, Menu & Blocks)
Building consistent layout components in Optimizely CMS can feel overwhelming when you're starting out. You need headers that work across all pages, footers that editors can update without breaking things, navigation menus that make sense, and reusable blocks that actually get reused. If you're working with Optimizely CMS 12 (the current version as of 2025) and wondering how to build these components the right way, this guide will walk you through each piece with real code you can use today.
What we'll cover in this guide:
- Setting up your global layout file properly
- Building header and footer components that editors can manage
- Creating navigation menus (both simple and complex versions)
- Developing reusable content blocks
- Avoiding common pitfalls that slow down development
By the end, you'll have working examples of each component type and understand how they fit together in a production Optimizely site.
Prerequisites
Before we start building, make sure you have:
1. Optimizely CMS 12 installed - Running on .NET 6 or .NET 7
2. Visual Studio 2022 or VS Code with C# extensions
3. Basic understanding of:
- C# and ASP.NET Core MVC
- Razor syntax for views
- Content modeling concepts (pages vs blocks)
4. An Optimizely development environment - Either local or cloud-based
5. Admin access to your CMS instance for testing
If you're missing any of these, the official Optimizely documentation has setup guides to get you started.
Step-by-Step Implementation
Step 1: Set Up Your Global Layout File
Your _Layout.cshtml file acts as the skeleton for every page on your site. Instead of cramming logic directly into this file, we'll use View Components to keep things clean and testable.
Create or update your /Views/Shared/_Layout.cshtml:
@ViewData["Title"] - Your Site Name
@* Call a View Component for metadata/SEO tags *@
@await Component.InvokeAsync("Metadata")
@* Your CSS references *@
@* Header component *@
@await Component.InvokeAsync("Header")
@* Main content area *@
@RenderBody()
@* Footer component *@
@await Component.InvokeAsync("Footer")
@* Scripts at the bottom *@
@RenderSection("Scripts", required: false)
