Розробка кастомного шаблону Umbraco
Клієнт приходить із завданням: «Потрібен сайт на Umbraco, але готові теми не підходять — потрібна розробка кастомного шаблону Umbraco під нестандартну структуру». Ми не беремо шаблон з маркетплейсу: пишемо Razor-в'юхи, контролери та View Components з нуля під конкретний Document Type. Жодної зайвої розмітки, жодних костилів — тільки те, що потрібно проєкту. Кастомний шаблон дозволяє завантажувати сторінки на 40% швидше готового рішення за рахунок мінімізації запитів та bundle splitting.
Як кастомізувати шаблон без втрати продуктивності?
Перший крок — розібратися з Layout. Кожна сторінка успадковує загальний макет, але якщо в нього зашити надто багато логіки, постраждає TTFB. Ми виносимо статичні частини (шапка, підвал) в окремі partials, а динамічні — через @await Component.InvokeAsync(). Це дає кешування по частинах і знижує навантаження на базу. Наприклад, на одному з проєктів LCP впав з 2,8 с до 1,1 с після рефакторингу Layout.
Згідно з рекомендаціями Google Core Web Vitals, LCP має бути менше 2.5 секунд. Базовий макет:
@* Views/Shared/_Layout.cshtml *@
@using Umbraco.Cms.Web.Common.PublishedModels
@inject IPublishedValueFallback PublishedValueFallback
<!DOCTYPE html>
<html lang="@System.Threading.Thread.CurrentThread.CurrentCulture.TwoLetterISOLanguageName">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>@ViewData["Title"] – @ViewBag.SiteName</title>
<meta name="description" content="@ViewData["Description"]">
<link rel="stylesheet" href="~/css/app.css" asp-append-version="true">
</head>
<body class="@ViewData["BodyClass"]">
@await Html.PartialAsync("_Navigation")
<main>@RenderBody()</main>
@await Html.PartialAsync("_Footer")
<script src="~/js/app.js" asp-append-version="true" defer></script>
@RenderSection("scripts", required: false)
</body>
</html>Зустрічається ситуація: клієнт хоче, щоб на кожній сторінці був свій заголовок h1 та SEO-опис. Вирішується strongly-typed моделлю, яка маппиться з IPublishedContent. Ми використовуємо Umbraco Mapper для автоматизації перетворень (детальніше в документації Umbraco).
Приклад контролера статті на C#:
public class ArticleController : RenderController
{
private readonly IUmbracoMapper _mapper;
private readonly IRelatedContentService _relatedService;
public ArticleController(ILogger<ArticleController> logger, ICompositeViewEngine viewEngine, IUmbracoContextAccessor umbracoContextAccessor, IUmbracoMapper mapper, IRelatedContentService relatedService) : base(logger, viewEngine, umbracoContextAccessor)
{
_mapper = mapper;
_relatedService = relatedService;
}
public override IActionResult Index()
{
if (CurrentPage is not Article article)
return NotFound();
var model = new ArticleViewModel
{
Title = article.Title,
BodyHtml = article.Body?.ToString(),
PublishDate = article.PublishDate,
SeoTitle = article.SeoTitle,
SeoDescription = article.SeoDescription,
CoverImage = article.CoverImage?.First() as IPublishedContent,
Category = article.ArticleCategory?.First() as IPublishedContent,
RelatedArticles = _relatedService.GetRelated(article, 3),
};
return CurrentTemplate(model);
}
} Чому варто обирати кастомні шаблони Umbraco замість готових рішень?
| Критерій | Готовий шаблон | Кастомний шаблон |
|---|---|---|
| Продуктивність | Часто перевантажений непотрібними скриптами | Мінімум запитів, оптимізовані Partial View |
| SEO-структура | Розмітка фіксована, складно змінювати | Повний контроль над HTML, заголовками, мікророзміткою |
| Швидкість завантаження | LCP може бути > 2.5 с через бандли | Bundle splitting, lazy images через ImageSharp, WebP |
| Розширюваність | Будь-яка доробка — костилі та патчі | Чиста архітектура, Repository pattern, легко додавати блоки |
З таблиці видно, що кастомний шаблон виграє за всіма ключовими метриками. Додатково, економія на ліцензіях та підтримці може становити до 30% порівняно з готовим рішенням. Вартість кастомного шаблону нижча, ніж покупка та постійні доробки готового. Терміни розробки прозорі та фіксуються в ТЗ.
Процес кастомізації шаблону Umbraco
- Аналітика: вивчаємо Document Types, структуру контенту, вимоги до продуктивності.
- Проєктування Layout: створюємо макет, визначаємо зони для Partial View.
- Розробка контролерів: пишемо strongly-typed ViewModel з впровадженням залежностей для кожного Document Type.
- Реалізація блоків: налаштовуємо Block List / Block Grid з кастомними partials, підключаємо ImageSharp для адаптивних зображень.
- Тестування: перевіряємо Core Web Vitals, усуваємо N+1 запити, налаштовуємо кешування.
- Деплой: передаємо код, документацію та доступ.
Етапи розробки та терміни
| Етап | Тривалість |
|---|---|
| Аналітика та аудит | 1–2 дня |
| Проєктування Layout | 1–2 дня |
| Розробка контролерів | 2–4 дня |
| Реалізація блоків | 3–5 днів |
| Тестування та оптимізація | 1–2 дня |
| Деплой та документація | 1 день |
Типові помилки при кастомізації шаблонів Umbraco
N+1 запит — кожен блок Hero незалежно завантажує зображення. Рішення: інжектимо сервіс зображень в контролер та передаємо готові URL.
Hydration mismatch — при кешуванні часткових в'юх втрачається актуальність даних. Використовуємо [OutputCache(NoStore = true)] на динамічних компонентах.
Дублювання навігації — багаторівневе меню з окремими шаблонами для кожного рівня. Натомість застосовуємо єдиний рекурсивний partial _Navigation.
Приклад рекурсивної навігації
@* Views/Partials/_Navigation.cshtml *@
@using Umbraco.Cms.Web.Common.UmbracoContext
@inject IUmbracoContextAccessor UmbracoContextAccessor
@{
var ctx = UmbracoContextAccessor.GetRequiredUmbracoContext();
var root = ctx.Content?.GetAtRoot().FirstOrDefault();
var nav = root?.Children.Where(n => n.Value<bool>("showInNav"));
}
<nav class="main-nav">
@foreach (var item in nav ?? [])
{
<a href="@item.Url()" class="@(item.IsAncestorOrSelf(ctx.PublishedRequest?.PublishedContent) ? "active" : "")">
@item.Name
</a>
}
</nav> Що входить в роботу
- Розробка Layout та Partial View (навігація, підвал, попапи)
- Strongly-typed моделі ViewModel для кожного Document Type
- Контролери на C# з впровадженням залежностей
- Блочний редактор (Block List / Block Grid) з кастомними partials
- View Components для макросів (хлібні крихти, меню, віджети)
- Адаптивні зображення з WebP та srcset
- Мінімальна верстка Umbraco на Tailwind або CSS Grid — за погодженням
- Документація та доступ (адмінка, FTP, репозиторій)
Терміни та вартість
Терміни залежать від кількості типів сторінок та складності блоків. Орієнтуємося на діапазон:
- Базовий комплект (Layout + 5–6 типів сторінок + блоки): 2–3 тижні.
- Один складний шаблон з кастомним контролером та кешуванням: 3–5 днів.
Вартість розраховується індивідуально після аудиту поточної структури. Ми не називаємо ціну наосліп — спочатку знайомимося з проєктом. Оцінимо ваш проєкт за 1 робочий день, дамо точний кошторис та терміни. Наш досвід 7+ років та 50+ проєктів на Umbraco дозволяють гарантувати передбачуваний результат. Зв'яжіться з нами, щоб обговорити деталі — отримайте консультацію. Замовте розробку кастомного шаблону Umbraco — отримайте продуктивність, заточену під ваш проєкт.







