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

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

Это лишь некоторые из технических типов сайтов, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента

Предлагаемые услуги
Показано 1 из 1 услугВсе 2065 услуг
Разработка кастомного шаблона Hugo (Go Templates)
Средняя
~3-5 рабочих дней
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1214
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1161
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    852
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1041
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    823
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Разработка веб-сайта для компании ФИКСПЕР
    815

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

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

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

Hugo разрешает шаблоны по иерархии lookup order. Для страницы /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" }}

{{/* Группировка по department */}}
{{ $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 недель.