Розробка кастомного шаблону Hugo (Go Templates)

Наша компанія займається розробкою, підтримкою та обслуговуванням сайтів будь-якої складності. Від простих односторінкових сайтів до масштабних кластерних систем, побудованих на мікро сервісах. Досвід розробників підтверджено сертифікатами від вендорів.
Розробка та обслуговування будь-яких видів сайтів:
Інформаційні сайти або веб-програми
Сайти візитки, landing page, корпоративні сайти, онлайн каталоги, квіз, промо-сайти, блоги, ресурси новин, інформаційні портали, форуми, агрегатори
Сайти або веб-програми електронної комерції
Інтернет-магазини, B2B-портали, маркетплейси, онлайн-обмінники, кешбек-сайти, біржі, дропшиппінг-платформи, парсери товарів
Веб-програми для управління бізнес-процесами
CRM-системи, ERP-системи, корпоративні портали, системи управління виробництвом, парсери інформації
Сайти або веб-програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, конструктори сайтів, портали надання електронних послуг, відеохостинги, тематичні портали

Це лише деякі з технічних типів сайтів, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Пропоновані послуги
Показано 1 з 1 послугУсі 2065 послуг
Розробка кастомного шаблону Hugo (Go Templates)
Середня
~3-5 робочих днів
Часті питання
Наші компетенції:
Етапи розробки
Останні роботи
  • image_website-b2b-advance_0.png
    Розробка сайту компанії B2B ADVANCE
    1262
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1171
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    874
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1094
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    831
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Розробка веб-сайту для компанії ФІКСПЕР
    851

Розробка користувацького шаблона Hugo (Go Templates)

Hugo використовує стандартний пакет html/template із стандартної бібліотеки Go, розширений власними функціями. Синтаксис відрізняється від Twig, Jinja2, Liquid — він має свою логіку, яку потрібно зрозуміти один раз, а потім ефективно працювати. Користувацький шаблон — це повна контроль над розміткою без залежності від чужих тем.

Структура шаблонів

Hugo вирішує шаблони за порядком пошуку. Для сторінки /blog/my-post/, Hugo шукає шаблон у такому порядку:

layouts/blog/single.html
layouts/blog/single.baseof.html
layouts/_default/single.html
layouts/_default/baseof.html

Для розділу /services/ (список сторінок):

layouts/services/list.html
layouts/_default/list.html

Базовий шаблон baseof.html визначає структуру через блоки:

{{/* layouts/_default/baseof.html */}}
<!DOCTYPE html>
<html lang="{{ .Site.Language.Lang }}">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>{{ block "title" . }}{{ .Site.Title }}{{ end }}</title>
  {{ block "head" . }}{{ end }}
  {{ partial "head/styles.html" . }}
</head>
<body class="{{ block "body-class" . }}{{ end }}">
  {{ partial "header.html" . }}
  <main>
    {{ block "main" . }}{{ end }}
  </main>
  {{ partial "footer.html" . }}
  {{ partial "head/scripts.html" . }}
</body>
</html>

Дочірній шаблон перевизначає блоки:

{{/* layouts/blog/single.html */}}
{{ define "title" }}{{ .Title }} | {{ .Site.Title }}{{ end }}

{{ define "body-class" }}page-post{{ end }}

{{ define "main" }}
<article class="post">
  <header class="post__header">
    <h1>{{ .Title }}</h1>
    <time datetime="{{ .Date.Format "2006-01-02" }}">
      {{ .Date.Format "2 January 2006" }}
    </time>
    {{ with .Params.authors }}
    <div class="post__authors">
      {{ range . }}
        {{ $author := index $.Site.Data.authors . }}
        <span>{{ $author.name }}</span>
      {{ end }}
    </div>
    {{ end }}
  </header>

  {{ if .Params.featured_image }}
  <figure class="post__cover">
    {{ $img := resources.Get .Params.featured_image }}
    {{ if $img }}
      {{ $webp := $img | images.Resize "1200x630 WebP" }}
      {{ $fallback := $img | images.Resize "1200x630" }}
      <picture>
        <source srcset="{{ $webp.Permalink }}" type="image/webp">
        <img src="{{ $fallback.Permalink }}" alt="{{ .Title }}" loading="eager">
      </picture>
    {{ end }}
  </figure>
  {{ end }}

  <div class="post__body">{{ .Content }}</div>

  {{ partial "blog/related-posts.html" . }}
</article>
{{ end }}

Робота з даними та змінними

Go Templates строго типізовані. Основні шаблони:

{{/* Призначення змінної */}}
{{ $total := 0 }}
{{ range .Pages }}
  {{ $total = add $total 1 }}
{{ end }}
Всього статей: {{ $total }}

{{/* Робота зі словниками */}}
{{ $meta := dict "og:type" "article" "og:title" .Title }}
{{ range $key, $val := $meta }}
  <meta property="{{ $key }}" content="{{ $val }}">
{{ end }}

{{/* Умови з AND/OR */}}
{{ if and .Params.featured (not .Draft) }}
  <span class="badge">Featured</span>
{{ end }}

{{/* Тернарний оператор через cond */}}
{{ $class := cond .Params.dark "section--dark" "section--light" }}
<section class="{{ $class }}">

Partial-функції з параметрами

Партіали приймають контекст (.) або довільний словник:

{{/* Виклик партіала з користувацьким контекстом */}}
{{ partial "components/card.html" (dict
  "title" .Title
  "url" .Permalink
  "image" .Params.thumbnail
  "excerpt" .Summary
  "date" .Date
  "tags" .Params.tags
) }}
{{/* layouts/partials/components/card.html */}}
{{ $ctx := . }}
<article class="card">
  {{ with $ctx.image }}
  <div class="card__image">
    <img src="{{ . }}" alt="{{ $ctx.title }}">
  </div>
  {{ end }}
  <div class="card__body">
    <h3 class="card__title">
      <a href="{{ $ctx.url }}">{{ $ctx.title }}</a>
    </h3>
    {{ with $ctx.excerpt }}
    <p class="card__excerpt">{{ . }}</p>
    {{ end }}
    {{ if $ctx.tags }}
    <ul class="card__tags">
      {{ range $ctx.tags }}
      <li><a href="/tags/{{ . | urlize }}/">{{ . }}</a></li>
      {{ end }}
    </ul>
    {{ end }}
  </div>
</article>

Користувацькі сторінки зі складною логікою

Приклад: сторінка команди з групуванням за відділами:

{{/* layouts/team/list.html */}}
{{ define "main" }}
{{ $pages := .Pages.ByParam "order" }}

{{/* Групування за відділом */}}
{{ $departments := slice }}
{{ range $pages }}
  {{ $dept := .Params.department }}
  {{ if not (in $departments $dept) }}
    {{ $departments = $departments | append $dept }}
  {{ end }}
{{ end }}

{{ range $departments }}
  {{ $dept := . }}
  <section class="team-department">
    <h2>{{ $dept }}</h2>
    <div class="team-grid">
      {{ range where $pages "Params.department" $dept }}
        {{ partial "components/team-card.html" . }}
      {{ end }}
    </div>
  </section>
{{ end }}
{{ end }}

SEO-шаблони

{{/* layouts/partials/head/seo.html */}}
{{ $title := cond .IsHome .Site.Title (printf "%s | %s" .Title .Site.Title) }}
{{ $description := cond .Params.description .Params.description .Site.Params.description }}
{{ $image := cond .Params.featured_image .Params.featured_image .Site.Params.defaultOGImage }}

<title>{{ $title }}</title>
<meta name="description" content="{{ $description }}">

<meta property="og:title" content="{{ $title }}">
<meta property="og:description" content="{{ $description }}">
<meta property="og:url" content="{{ .Permalink }}">
<meta property="og:type" content="{{ if .IsPage }}article{{ else }}website{{ end }}">
{{ with $image }}
<meta property="og:image" content="{{ absURL . }}">
{{ end }}

{{ if .IsPage }}
<meta property="article:published_time" content="{{ .Date.Format "2006-01-02T15:04:05Z07:00" }}">
<meta property="article:modified_time" content="{{ .Lastmod.Format "2006-01-02T15:04:05Z07:00" }}">
{{ range .Params.tags }}
<meta property="article:tag" content="{{ . }}">
{{ end }}
{{ end }}

<link rel="canonical" href="{{ .Permalink }}">

{{ range .AlternativeOutputFormats }}
<link rel="{{ .Rel }}" type="{{ .MediaType.Type }}" href="{{ .Permalink | safeURL }}">
{{ end }}

Продуктивність шаблонів

Hugo кешує результати partial через partialCached:

{{/* Кешувати за slug сторінки */}}
{{ partialCached "components/sidebar.html" . .Page.Slug }}

{{/* Кешувати глобально (один раз для всього сайту) */}}
{{ partialCached "components/footer-nav.html" . }}

partialCached особливо важливий для партіалів, які виконують важкі обчислення або отримають доступ до великих наборів даних.

Терміни

Користувацький шаблон для сайту з 5–15 сторінками, блогом та базовою SEO-розміткою — 1–2 тижні. Складний шаблон з багатьма типами контенту, користувацькими таксономіями, багатомовністю — 3–5 тижнів.