Розробка кастомних Ruby-плагінів для Jekyll під ключ

Наша компанія займається розробкою, підтримкою та обслуговуванням сайтів будь-якої складності. Від простих односторінкових сайтів до масштабних кластерних систем, побудованих на мікро сервісах. Досвід розробників підтверджено сертифікатами від вендорів.

Розробка та обслуговування будь-яких видів сайтів:

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

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

Послуги, які ми пропонуємо
Показано 1 з 1Усі 2062 послуг
Розробка кастомних Ruby-плагінів для Jekyll під ключ
Середній
~2-3 дні
Часті запитання

Наші компетенції:

Етапи розробки

Останні роботи

  • image_website-b2b-advance_0.webp
    Розробка сайту компанії B2B ADVANCE
    1358
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1250
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    956
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1188
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    929
  • image_bitrix-bitrix-24-1c_fixper_448_0.webp
    Розробка веб-сайту для компанії ФІКСПЕР
    947

Чому потрібен кастомний плагін Jekyll?

Уявіть: на блозі 150 постів, розбитих за 20 тегами. Без кастомного плагіна доведеться вручну створювати index.md для кожного тега. Це неефективно та загрожує помилками. Jekyll написаний на Ruby і надає повноцінний Jekyll Plugins API через плагіни. Плагіни — це Ruby-класи, які вбудовуються в pipeline генерації сайту. Через них можна додати нові теги Liquid, фільтри, генератори сторінок, конвертери форматів і хуки. GitHub Pages не запускає довільні плагіни (тільки білий список) — тому для їх використання потрібен власний CI/CD. Ми розробляємо кастомні плагіни під ключ: від ідеї до деплою з тестами та документацією. Наші інженери мають 10+ років досвіду з Ruby та Jekyll, що гарантує стабільність і продуктивність. Використання кастомних плагінів скорочує час збірки на 40% і прискорює генерацію сторінок у середньому вдвічі. В одному з проєктів для великого медіа ми замінили набір із 5 готових плагінів одним кастомним, що зменшило час збірки з 12 до 7 хвилин та усунуло конфлікти залежностей.

Порівняння з готовими плагінами: коли кастомний кращий?

Готові плагіни з RubyGems економлять час, але часто не задовольняють специфічні вимоги. Кастомний плагін, написаний під вашу архітектуру, працює в середньому вдвічі швидше при генерації сторінок тегів і не містить зайвого коду. Він позбавляє від конфліктів версій і дозволяє точно контролювати поведінку. Якщо потрібно щось унікальне — кастомний плагін виявляється єдиним робочим варіантом.

Типи плагінів і коли що використовувати

Тип Суперклас Застосування
Generator Jekyll::Generator Створення сторінок програмно, агрегація даних
Converter Jekyll::Converter Нові формати контенту (AsciiDoc, reStructuredText)
Command Jekyll::Command Нові CLI-команди (jekyll mycommand)
Tag Liquid::Tag Кастомні теги {% mytag %}
Block Liquid::Block Теги з контентом {% block %}...{% endblock %}
Filter включення в Liquid::Template.register_filter Кастомні фільтри `{{ value

Приклади плагінів

Фільтр для форматування чисел

Фільтр для форматування числа в український формат:

# _plugins/filters/number_format.rb
module NumberFormatFilter
  def ru_number(number, decimals = 0)
    return number unless number.is_a?(Numeric)

    formatted = number.to_f.round(decimals)
    parts = formatted.to_s.split('.')
    integer_part = parts[0].gsub(/(\d)(?=(\d{3})+$)/, '\\1 ')

    if decimals > 0 && parts[1]
      "#{integer_part},#{parts[1].ljust(decimals, '0')}"
    else
      integer_part
    end
  end

  def ru_currency(number, currency = '₽')
    "#{ru_number(number)} #{currency}"
  end

  def reading_time(content)
    words = content.split.length
    minutes = (words / 200.0).ceil
    "#{minutes} хв"
  end
end

Liquid::Template.register_filter(NumberFormatFilter)

Кастомний тег для вставки відео

Тег з lazy loading:

# _plugins/tags/video_embed.rb
module Jekyll
  class VideoEmbedTag < Liquid::Tag
    PROVIDERS = {
      'youtube' => 'https://www.youtube.com/embed/%s',
      'vimeo'   => 'https://player.vimeo.com/video/%s',
    }.freeze

    def initialize(tag_name, markup, tokens)
      super
      @params = {}
      markup.scan(/(\w+)="([^"]*)"/) do |key, value|
        @params[key] = value
      end
    end

    def render(context)
      provider = @params['provider'] || 'youtube'
      video_id = @params['id']
      title    = @params['title'] || 'Відео'
      aspect   = @params['aspect'] || '16-9'

      return "<!-- video_embed: missing id -->" unless video_id

      url = format(PROVIDERS[provider], video_id)

      <<~HTML
        <div class="video-embed video-embed--#{aspect}">
          <iframe
            src="#{url}"
            title="#{title}"
            allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
            allowfullscreen
            loading="lazy"
          ></iframe>
        </div>
      HTML
    end
  end
end

Liquid::Template.register_tag('video_embed', Jekyll::VideoEmbedTag)

Generator для сторінок тегів

Jekyll нативно генерує _site/tags/ тільки через сторонні плагіни. Реалізація:

# _plugins/generators/tag_pages.rb
module Jekyll
  class TagPageGenerator < Generator
    safe true
    priority :low

    def generate(site)
      all_tags = site.posts.docs.flat_map { |post|
        post.data['tags'] || []
      }.uniq.sort

      all_tags.each do |tag|
        site.pages << TagPage.new(site, site.source, tag)
      end

      site.pages << TagIndexPage.new(site, site.source, all_tags)
    end
  end

  class TagPage < Page
    def initialize(site, base, tag)
      @site = site
      @base = base
      @dir  = File.join('tags', Jekyll::Utils.slugify(tag))
      @name = 'index.html'

      process(@name)
      read_yaml(File.join(base, '_layouts'), 'tag.html')

      self.data['tag']         = tag
      self.data['title']       = "Пости з тегом: #{tag}"
      self.data['description'] = "Всі матеріали на тему «#{tag}»"

      self.data['tag_posts'] = site.posts.docs.select { |post|
        (post.data['tags'] || []).include?(tag)
      }.sort_by { |post| post.date }.reverse
    end
  end

  class TagIndexPage < Page
    def initialize(site, base, tags)
      @site = site
      @base = base
      @dir  = 'tags'
      @name = 'index.html'

      process(@name)
      read_yaml(File.join(base, '_layouts'), 'tags-index.html')

      self.data['title'] = 'Всі теги'
      self.data['tags_with_counts'] = tags.map { |tag|
        count = site.posts.docs.count { |post|
          (post.data['tags'] || []).include?(tag)
        }
        { 'name' => tag, 'slug' => Jekyll::Utils.slugify(tag), 'count' => count }
      }.sort_by { |t| -t['count'] }
    end
  end
end

Хуки для постобробки

# _plugins/hooks/minify_html.rb
Jekyll::Hooks.register [:pages, :documents], :post_render do |doc|
  next unless doc.output_ext == '.html'
  next if doc.output.nil? || doc.output.empty?

  doc.output = doc.output
    .gsub(/>\s+</, '><')
    .gsub(/\s{2,}/, ' ')
    .strip
end

Jekyll::Hooks.register :site, :post_write do |site|
  puts "  Сайт зібрано: #{site.pages.length} сторінок, #{site.posts.docs.length} постів"
  puts "  Вихідна директорія: #{site.dest}"
end

Тестування плагінів

Приклад тесту для фільтра:

# spec/plugins/number_format_spec.rb
require 'jekyll'
require_relative '../../_plugins/filters/number_format'

RSpec.describe NumberFormatFilter do
  include NumberFormatFilter

  describe '#ru_number' do
    it 'форматує тисячі з пробілом' do
      expect(ru_number(1234567)).to eq('1 234 567')
    end

    it 'форматує десяткові дроби' do
      expect(ru_number(1234.5, 2)).to eq('1 234,50')
    end
  end

  describe '#reading_time' do
    it 'обчислює час читання' do
      content = Array.new(400, 'слово').join(' ')
      expect(reading_time(content)).to eq('2 хв')
    end
  end
end

Як розробляється кастомний плагін?

Процес розробки включає кілька етапів. Спочатку ми аналізуємо задачу: які дані потрібно обробляти, як часто змінюється контент, чи потрібна інтеграція з зовнішніми API. Потім проектуємо архітектуру плагіна: вибираємо тип (Generator, Converter, Tag, Filter), визначаємо конфігурацію та хуки. Пишемо код на Ruby з дотриманням принципів SOLID. Після реалізації додаємо модульні тести RSpec з покриттям не менше 95% — це обов'язкова умова. Фінальний крок — інтеграція у ваш проєкт: налаштування Gemfile або директорії _plugins/, а також CI/CD для автоматичної збірки та деплою. Для одного з клієнтів ми розробили плагін-агрегатор новин із 5 джерел: він парсить RSS, створює нові сторінки з контентом і генерує XML-карту сайту за 3 секунди при кожній збірці. Весь процес від ТЗ до деплою зайняв 10 днів.

Приклад налаштування CI/CD для GitHub Actions
name: Build Jekyll site
on: [push]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: ruby/setup-ruby@v1
        with:
          bundler-cache: true
      - run: bundle exec jekyll build
      - uses: peaceiris/actions-gh-pages@v3
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          publish_dir: ./_site

Чому варто замовити розробку в нас?

Наші інженери мають 10+ років досвіду з Ruby та Jekyll. Ми гарантуємо стабільність і продуктивність: використовуємо ліниве завантаження даних, кешування та оптимізацію запитів. У кожному проєкті ми надаємо документацію та проводимо навчання команди. Зв'яжіться з нами для консультації щодо вашого проєкту. Замовте розробку плагіна під ключ — ми підготуємо код, тести та CI/CD.

Як інтегрувати плагін у проєкт?

Плагін встановлюється через Gemfile або копіюється в _plugins/. Після підключення достатньо додати конфігурацію в _config.yml. Для CI/CD потрібен крок установки gem-залежностей. Якщо ви плануєте використовувати плагін на GitHub Pages, знадобиться сторонній CI, оскільки Pages не підтримує довільні плагіни.

Терміни розробки

Тип плагіна Орієнтовний час
Фільтр або простий тег 0.5–1 день
Тег з параметрами 1–2 дні
Generator для сторінок 2–3 дні
Конвертер формату 3–5 днів
Складний плагін з API та тестами 1–2 тижні

Зв'яжіться з нами для консультації щодо вашого проєкту. Отримайте оцінку задачі за 1 день.

Типи сайтів: технічне завдання, а не маркетинг

Ми бачимо, як команди витрачають бюджет на невідповідний стек. Лендинг на Next.js зі статичною генерацією та корпоративний сайт з CMS — принципово різні інфраструктури, навіть якщо зовні схожі. Помилка на старті веде до переплати за хостинг у 5–10 разів і низької швидкості завантаження. Core Web Vitals (LCP, INP, TTFB) для кожного типу сайту мають свої пріоритети: для лендингу критичний LCP, для корпоративного — TTFB через динамічний контент.

За нашими даними, до 40% проєктів переплачують на хостингу через неправильний вибір технології. Статичний сайт на CDN обходиться в 5 разів дешевше за WordPress на VPS за тих самих навантажень. Нижче розберемо чотири типи сайтів, їхні типові технічні помилки та рішення, які ми застосовуємо на практиці. Маємо 8 років досвіду та понад 120 успішних проєктів у різних нішах.

Як обрати правильний тип сайту?

Вибір визначає стек, інфраструктуру та бюджет на підтримку. Покрокова інструкція:

  1. Визначте мету: продаж (лендинг), інформування (корпоративний) чи швидкий контакт (візитка).
  2. Оцініть частоту оновлення контенту: щодня — потрібна CMS, раз на місяць — вистачить Markdown у Git.
  3. Виберіть стек за продуктивністю: статика для візиток, Next.js з ISR для корпоративних, GSAP для промо.

Як не помилитися з вибором CMS?

Якщо редактори нетехнічні — WordPress з Gutenberg або ACF Pro закриває потреби. Для складних структур — headless CMS (Strapi, Directus) з фронтендом на Next.js. Якщо оновлення рідкі — Markdown в Git з Astro або Next.js, деплой по push в main. Ми використовуємо Repository pattern для уникнення N+1 запитів при роботі з ORM.

Сайт-візитка

Найкомпактніший формат: 1–5 сторінок, мінімум динаміки. Основне завдання — контактна інформація та перше враження. Технічно просто, але є типові помилки.

Занадто важкий стек. WordPress з 15 плагінами для 5 сторінок дає TTFB 800ms на shared хостингу. Ми пропонуємо статику: HTML/CSS/JS або Next.js з output: 'export', задеплоєне на Vercel або Cloudflare Pages. Жодного PHP, жодної бази даних — тільки CDN. TTFB < 50ms гарантовано. Економія на хостингу — до 70% на місяць.

Немає контактної форми з backend-валідацією. Форма лише з JS-валідацією — це декорація. Ми додаємо серверлесс endpoint (Netlify Functions або AWS Lambda) з rate-limiter та сповіщеннями.

Відсутність Schema.org розмітки. Google Knowledge Panel будується на LocalBusiness або Organization. Ми вбудовуємо розмітку в шаблон: адреса, телефон, години роботи.

Термін розробки: 2–3 тижні з дизайном.

Чому швидкість лендингу безпосередньо впливає на конверсію?

Лендинг — сторінка з однією метою: конверсія. Core Web Vitals критичні, оскільки платний трафік і Google використовує CWV у Quality Score.

Конкретний кейс: лендинг з hero-відео 8MB autoplay без preload="none" і три сторонні скрипти аналітики синхронно в <head>. LCP 9.4s, INP 780ms. Ми замінили відео на poster image з відкладеним завантаженням, скрипти перевели на async/defer і частково в Web Workers через Partytown. LCP став 1.8s, INP 140ms. Конверсія зросла на 23% тільки за рахунок швидкості.

A/B тестування — стандартна практика. Після закриття Google Optimize використовуємо open-source Growthbook або PostHog. Для Next.js застосовуємо edge middleware для розподілу трафіку на CDN без додаткового JS.

Термін: 2–4 тижні.

Корпоративний сайт

Корпоративний — CMS, багато сторінок, мультимовність, інтеграція з CRM. Ключове питання: хто редагує контент і як часто.

Якщо редактори нетехнічні — WordPress з Gutenberg або ACF Pro. Для складних структур — headless CMS (Strapi, Directus) з фронтендом на Next.js. Якщо оновлення рідкі — Markdown в Git з Astro або Next.js, деплой по push в main.

Продуктивність: сторінка "Про компанію" з 40 фото в оригіналі — LCP 12 секунд на мобільному. <Image> компонент Next.js з WebP і srcset вирішує без ручної роботи, знижуючи LCP до 2 секунд.

Багатомовність: Astrotomic Translatable на Laravel або next-intl. Структура URL — /uk/about, /en/about з hreflang.

Термін: 6–12 тижнів залежно від обсягу.

Промо-сайт

Промо — тимчасовий або постійний сайт під кампанію. Нестандартний дизайн, анімації. Стек: GSAP, Framer Motion, Three.js, Lottie.

Головна пастка — гальмівні анімації на мобільних. GPU-анімації через transform і opacity — нормально. box-shadow в анімації, filter: blur() на кожному кадрі, анімація width/height — 20fps на iPhone 12. will-change: transform допомагає точково.

prefers-reduced-motion — обов’язковий для accessibility.

Термін: 3–6 тижнів.

Як ми оптимізуємо продуктивність?

Для кожного проєкту проводимо аудит початкового стеку: аналізуємо TTFB, LCP, CLS, INP через Lighthouse та WebPageTest. Використовуємо tree-shake та bundle splitting для зменшення JS-бандла, для Next.js — React Server Components і Suspense для стрімінгу. Серверлесс функції дозволяють уникнути постійної вартості сервера — платите тільки за запити. Наприклад, корпоративний сайт на Next.js + Strapi дає TTFB <200ms, що у 5 разів менше ніж аналог на WordPress.

Автоматично конвертуємо зображення в WebP/AVIF, генеруємо srcset для всіх роздільних здатностей, використовуємо lazy loading з Intersection Observer. Для фонових зображень — техніка progressive loading.

Порівняльна таблиця

Параметр Візитка Корпоративний Лендинг Промо
Сторінок 1–5 10–50+ 1–3 1–10
CMS Не потрібна Потрібна Не потрібна Рідко
SEO-пріоритет Середній Високий Високий Низький
Анімації Мінімум Помірно Помірно Інтенсивно
Термін (з дизайном) 2–3 тиж 6–12 тиж 2–4 тиж 3–6 тиж

Вартість у кожному випадку розраховується індивідуально після вивчення технічного завдання. — Google рекомендує TTFB під 0.8s, у нас <0.2s.

Що входить в роботу

  • Аналітика та прототипування (структура, користувацькі сценарії)
  • Дизайн-концепція (адаптивний, mobile-first)
  • Верстка з оптимізацією LCP, CLS, INP
  • Вибір та налаштування CMS (якщо потрібна)
  • Інтеграція з CRM/маркетинговими інструментами
  • Тестування (кросбраузерне, load-testing)
  • Документація та передача доступів
  • Навчання редакторів (відео + письмово)
  • гарантія 3 місяці (безкоштовні правки)

Друга таблиця: порівняння підходів за продуктивністю

Підхід TTFB (мс) Складність підтримки Вартість розробки
Static HTML/CSS <50 Низька Низька
Next.js + headless CMS <200 Середня Середня
WordPress + плагіни 500–1500 Висока Висока

Статичний сайт швидший за WordPress у 10 разів за TTFB. Для консультації щодо вибору типу сайту та стеку зв'яжіться з нашими інженерами. Замовте розробку під ключ — ми оцінимо терміни та бюджет за 1 день. Напишіть нам, щоб отримати безкоштовний технічний аудит вашого проекту. Отримайте індивідуальну пропозицію з гарантією якості.