Skip navigation

Integration with Hugo

Updated: 28.04.2026
Open as Markdown

Hugo is a fast and modern static site generator written in Go. Kinescope provides a ready-made shortcode for conveniently embedding video and playlists in Hugo documentation and blogs.

When you’ll need the Hugo integration

Use the Hugo integration if:

  • Documentation on Hugo — you want to embed video in your documentation
  • Blog on Hugo — you need to add video to blog posts
  • Uniform embedding — all videos and playlists are embedded the same way via a simple shortcode
  • Responsive — players automatically adapt to the container width
  • Performance — lazy loading for optimized page load times

If you use Hugo for documentation or a blog — read on. Below you’ll find how to set up the integration in a few minutes.

How the shortcode works (4 steps)

  1. Install the shortcode — add the shortcode file to your theme or project
  2. Use the shortcode in Markdown — insert a simple command instead of HTML code
  3. Hugo processes the shortcode — during site build, it generates the correct HTML with an iframe
  4. Video displays on the page — the responsive player automatically adapts to the container

Now let’s walk through how to set it up.

Setup: step 1 — install the shortcode

The kinescope shortcode is already included in the Kinescope documentation theme. If you’re using your own theme or want to add it to an existing Hugo project:

  1. Create the shortcode file in your theme directory:
themes/your-theme/layouts/shortcodes/kinescope.html

Or in the project root (if you’re not using a theme):

layouts/shortcodes/kinescope.html
  1. Create the file with the following content:
{{- /* 
  Shortcode for embedding Kinescope players (video and playlists)
*/ -}}

{{- $url := .Get "url" -}}
{{- $id := .Get "id" -}}
{{- $type := .Get "type" | default "" -}}
{{- $width := .Get "width" -}}
{{- $height := .Get "height" -}}
{{- $ratio := .Get "ratio" | default "56.25" -}}
{{- $allow := .Get "allow" | default "autoplay; fullscreen; picture-in-picture; encrypted-media; gyroscope; accelerometer; clipboard-write; screen-wake-lock;" -}}

{{- /* Validation: either url or id must be specified */ -}}
{{- if and (not $url) (not $id) -}}
  {{- errorf "kinescope shortcode: either 'url' or 'id' parameter is required" -}}
{{- end -}}

{{- /* Determine embed URL */ -}}
{{- $embedUrl := "" -}}
{{- if $url -}}
  {{- if strings.HasPrefix $url "https://kinescope.io/embed/" -}}
    {{- $embedUrl = $url -}}
  {{- else if strings.HasPrefix $url "https://kinescope.io/pl/" -}}
    {{- $embedUrl = strings.Replace $url "https://kinescope.io/pl/" "https://kinescope.io/embed/pl/" 1 -}}
  {{- else if strings.HasPrefix $url "https://kinescope.io/" -}}
    {{- $embedUrl = strings.Replace $url "https://kinescope.io/" "https://kinescope.io/embed/" 1 -}}
  {{- else -}}
    {{- errorf "kinescope shortcode: unsupported URL format: %s" $url -}}
  {{- end -}}
{{- else if $id -}}
  {{- if eq $type "pl" -}}
    {{- $embedUrl = printf "https://kinescope.io/embed/pl/%s" $id -}}
  {{- else -}}
    {{- $embedUrl = printf "https://kinescope.io/embed/%s" $id -}}
  {{- end -}}
{{- end -}}

{{- /* Build query parameters */ -}}
{{- $queryParams := slice -}}
{{- $serviceParams := slice "url" "id" "type" "width" "height" "ratio" "allow" "title" -}}
{{- range $key, $value := .Params -}}
  {{- if and (ne $key "_") (not (in $serviceParams $key)) -}}
    {{- $encodedValue := $value | urlquery -}}
    {{- $queryParams = $queryParams | append (printf "%s=%s" $key $encodedValue) -}}
  {{- end -}}
{{- end -}}

{{- if gt (len $queryParams) 0 -}}
  {{- $queryString := delimit $queryParams "&" -}}
  {{- $embedUrl = printf "%s?%s" $embedUrl $queryString -}}
{{- end -}}

{{- /* Determine mode: responsive or fixed */ -}}
{{- $isFixed := and $width $height -}}

{{- if $isFixed -}}
  <div class="kinescope-embed kinescope-embed-fixed">
    <iframe 
      src="{{ $embedUrl }}"
      allow="{{ $allow }}"
      frameborder="0"
      allowfullscreen
      width="{{ $width }}"
      height="{{ $height }}"
      loading="lazy">
    </iframe>
  </div>
{{- else -}}
  <div class="kinescope-embed kinescope-embed-responsive" style="position: relative; padding-top: {{ $ratio }}%; width: 100%;">
    <iframe 
      src="{{ $embedUrl }}"
      allow="{{ $allow }}"
      frameborder="0"
      allowfullscreen
      style="position: absolute; width: 100%; height: 100%; top: 0; left: 0;"
      loading="lazy">
    </iframe>
  </div>
{{- end -}}

Setup: step 2 — add CSS styles

Add CSS styles for correct display (optional, if they’re not in your theme):

/* Kinescope embed styles */
.kinescope-embed {
    margin: 1.5em 0;
    border-radius: var(--radius-md);
    overflow: hidden;
    background: var(--color-bg-tertiary);
}

.kinescope-embed-responsive {
    position: relative;
    width: 100%;
}

.kinescope-embed-responsive iframe {
    position: absolute;
    width: 100%;
    height: 100%;
    top: 0;
    left: 0;
    border: none;
}

.kinescope-embed-fixed {
    display: inline-block;
    max-width: 100%;
}

.kinescope-embed-fixed iframe {
    display: block;
    border: none;
    max-width: 100%;
    height: auto;
}

Using the shortcode

Basic video embedding

The simplest approach — specify the full video URL:

{{< kinescope url="https://kinescope.io/pcFNnQGsD59CMKte2SQQaz" >}}

Or use just the video ID:

{{< kinescope id="pcFNnQGsD59CMKte2SQQaz" >}}

Video embedding example:

Embedding playlists

For playlists, use the URL with the /pl/ prefix:

{{< kinescope url="https://kinescope.io/pl/5ifZjJLLGYncrHYBdPNhKE" >}}

Or specify the type and ID:

{{< kinescope type="pl" id="5ifZjJLLGYncrHYBdPNhKE" >}}

Playlist embedding example:

Fixed player size

By default, the player is responsive and adapts to the container width. For a fixed size, specify width and height:

{{< kinescope id="pcFNnQGsD59CMKte2SQQaz" width="560" height="315" >}}

Playback parameters

The shortcode supports passing parameters via query string. For example, to play a video segment:

{{< kinescope url="https://kinescope.io/pcFNnQGsD59CMKte2SQQaz" seek="60" duration="30" >}}

This example starts the video from the 60th second and plays only the next 30 seconds.

Example with parameters:

Using different player templates

To apply a specific player template, use the player_id parameter:

{{< kinescope id="9cdAfqbbPcwu9GJwyxZ6jA" player_id="1213d24d-4624-4764-bf40-0baaf743377d" >}}

Setting the aspect ratio

For non-standard video formats, you can change the aspect ratio (default is 16:9, corresponding to padding-top: 56.25%):

{{< kinescope id="..." ratio="75" >}}

The ratio value is specified as a percentage. For example:

  • 56.25 — standard 16:9 ratio
  • 75 — 4:3 ratio
  • 100 — square 1:1 video

Usage examples in content

In documentation

Add video to a documentation article:

## Setting up the integration

To get started with the integration, watch the tutorial video:

{{< kinescope url="https://kinescope.io/pcFNnQGsD59CMKte2SQQaz" >}}

After watching the video, move on to the next step...

In a blog

Embed video in blog posts:

---
title: "New Kinescope Feature"
date: 2025-12-25
---

The video below showcases the new platform feature. Watch the demo:

{{< kinescope id="pcFNnQGsD59CMKte2SQQaz" >}}

After the video, add a short description and a link to the detailed article if needed.

In online courses

Use playlists for sequential learning:

## Lesson 1: Getting Started

Watch all videos in the playlist:

{{< kinescope url="https://kinescope.io/pl/iUsqhEMVWJCcUqg9Ay9gmD" >}}

How it works (in detail)

Validation and error handling

The shortcode automatically checks parameter correctness during site build:

  • If neither url nor id is specified, Hugo will return an error during build
  • If the URL has an unsupported format, the build will fail with an error
  • All errors are shown in the console when running hugo or hugo server

Example error for incorrect usage:

ERROR: kinescope shortcode: either 'url' or 'id' parameter is required

What the integration provides

  • Uniform embedding: videos and playlists are embedded the same way — via shortcode.
  • Responsive: the player adapts to the container width.
  • Parameters: playback settings can be passed (seek, duration, player_id, etc.).
  • Build-time checks: parameter errors are visible immediately during site build.
  • Lazy loading: the iframe loads lazily to avoid overloading the page.

Lazy loading

All iframes automatically load with the loading="lazy" attribute, improving page performance.

Support for all Kinescope parameters

The shortcode supports all parameters that can be passed in the player URL:

  • seek — initial playback position (in seconds)
  • duration — segment duration (in seconds)
  • player_id — player template ID
  • autoplay — video autoplay
  • And other Kinescope API parameters

Simply add them as shortcode parameters:

{{< kinescope id="..." seek="60" duration="30" autoplay="1" >}}

Compatibility

The shortcode works with:

  • Hugo version 0.100.0 and above
  • Any Hugo themes
  • Markdown and HTML content
  • Goldmark and Blackfriday renderers (when unsafe = true is enabled in the config)

For the shortcode to work, enable the following in config.toml:

[markup]
  [markup.goldmark]
    [markup.goldmark.renderer]
      unsafe = true

This allows Hugo to process the HTML code generated by the shortcode.

Support

If you have questions about the Hugo integration or using the shortcode, contact the support chat within the Kinescope interface — specialists will help you set up video embedding in your documentation or blog.

Hugo documentation is available on the official website .

That’s it! You can now embed Kinescope videos and playlists in your Hugo documentation or blog.

What’s next?

After setting up the Hugo integration, we recommend:

  1. Embedding — general principles of video embedding
  2. Customize the player — adapt the player’s appearance to your brand
  3. Set up content protection — enable DRM encryption and watermarks to protect video
  4. Restrict access by domain — allow video viewing only on your site

If you have any questions, write to the support chat within the Kinescope interface — our specialists will help!