Розробка кастомного шаблону 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 — отримайте продуктивність, заточену під ваш проєкт.







