Integration with Hugo
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)
- Install the shortcode — add the shortcode file to your theme or project
- Use the shortcode in Markdown — insert a simple command instead of HTML code
- Hugo processes the shortcode — during site build, it generates the correct HTML with an iframe
- 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:
- 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
- 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 ratio75— 4:3 ratio100— 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
urlnoridis 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
hugoorhugo 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 IDautoplay— 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 = trueis 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:
- Embedding — general principles of video embedding
- Customize the player — adapt the player’s appearance to your brand
- Set up content protection — enable DRM encryption and watermarks to protect video
- 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!