Docs

Preview

Display live URL previews with switchable device views (desktop, tablet, mobile). Shows websites or web applications in an iframe with device-specific dimensions and responsive controls.

Overview  

Basic Preview  

The preview content block renders a live URL preview in an iframe with device switcher controls. By default, it displays in desktop view.

Hugo on Wikipedia
Live preview of the Hugo static site generator Wikipedia page
yml
- _bookshop_name: preview
  heading:
    title: Hugo on Wikipedia
    content: Live preview of the Hugo static site generator Wikipedia page
  url: "https://en.wikipedia.org/wiki/Hugo_(software)"

Preview With Specific Device  

Set the device argument to specify which device view to display by default. Options are desktop, tablet, or mobile.

Tablet Preview
Opens in tablet view (820×1180 logical pixels)
yml
- _bookshop_name: preview
  heading:
    title: Tablet Preview
    content: Opens in tablet view (820×1180 logical pixels)
  url: "https://en.wikipedia.org/wiki/Hugo_(software)"
  device: tablet

Controls Below Preview  

By default the device switcher appears above the preview. Set controls_placement: bottom to move it below the preview area instead.

Controls Below
Device switcher placed beneath the preview
yml
- _bookshop_name: preview
  heading:
    title: Controls Below
    content: Device switcher placed beneath the preview
  url: "https://en.wikipedia.org/wiki/Hugo_(software)"
  controls_placement: bottom

Strict Aspect Ratio  

By default the desktop preview fills the full container width and height (responsive mode). Set desktop_responsive: false to use a strict 16:10 contain fit instead — the full 1440 × 900px frame is always visible with no clipping, leaving symmetric gaps above and below when the container is wider than it is tall.

Strict Aspect Ratio
Full 1440×900px frame always visible, no clipping
yml
- _bookshop_name: preview
  heading:
    title: Strict Aspect Ratio
    content: Full 1440×900px frame always visible, no clipping
  url: "https://en.wikipedia.org/wiki/Hugo_(software)"
  device: desktop
  desktop_responsive: false

Full-Width Preview  

Use cover: true and fluid: true for a full-width preview layout, ideal for showcasing responsive designs.

Full-Width Preview
Responsive design showcase
yml
- _bookshop_name: preview
  heading:
    title: Full-Width Preview
    content: Responsive design showcase
  background:
    color: body-tertiary
    subtle: true
  width: 12
  cover: true
  fluid: true
  url: "https://en.wikipedia.org/wiki/Hugo_(software)"
  device: desktop

Embedded Map Example  

The preview component works well with embeddable content like OpenStreetMap  . This example demonstrates a full-width preview with custom background styling.

Embedded Map
OpenStreetMap embed URL - specifically designed for iframes
yml
- _bookshop_name: preview
  heading:
    title: "Embedded Map"
    content: "OpenStreetMap embed URL - specifically designed for iframes"
  background:
    color: body-tertiary
    subtle: true
  width: 12
  cover: true
  fluid: false
  url: "https://www.openstreetmap.org/export/embed.html?bbox=-0.1,51.5,-0.08,51.52"
  device: desktop

Blocked URL With Fallback Image  

When the target URL sets X-Frame-Options or Content-Security-Policy: frame-ancestors 'none', Hugo detects this at build time via a HEAD request and renders the error overlay server-side. Provide an image argument to display a representative screenshot in place of the blocked iframe. The warning alert with a direct link is still shown below the image.

Set show-fallback: true to force the error overlay explicitly — useful when the HEAD request cannot reach the target URL (offline or CI environments), or when the URL blocks embedding for your specific domain without using the headers detected above.

Preview Unavailable
This URL blocks iframe embedding — a fallback image is shown instead
Preview unavailable
Preview unavailable
Preview unavailable
yml
- _bookshop_name: preview
  heading:
    title: Preview unavailable
    content: This URL blocks iframe embedding — a fallback image is shown instead
  url: "https://google.com"
  image: /img/placeholder.png

Blocked URL Without Fallback Image  

Without an image argument the component shows only the warning alert when the iframe fails to load, with a link to open the URL directly in a new tab.

Preview Unavailable (Alert Only)
No fallback image — only the warning alert is displayed
yml
- _bookshop_name: preview
  heading:
    title: Preview unavailable (alert only)
    content: No fallback image — only the warning alert is displayed
  url: "https://google.com"

CSP Configuration  

The preview component embeds external URLs in iframes, which requires appropriate Content Security Policy (CSP) configuration.

Production Configuration  

For production environments, explicitly allow the domains you want to embed in your config/production/params.toml:

[modules.hinode.csp]
    frame-src = [
        "https:",                        # Allow all HTTPS sources
        "example.com",                   # Specific domain
        "*.yourdomain.com",              # Wildcard subdomain
        "*.googletagmanager.com",
        "player.cloudinary.com",
        "www.youtube-nocookie.com",
        "www.youtube.com",
        "player.vimeo.com"
    ]

Development Configuration  

For local development, allow HTTP sources in your config/development/params.toml:

[modules.hinode.csp]
    frame-src = [
        "http:",                         # Allow all HTTP for localhost
        "https:",
        "*.googletagmanager.com",
        "player.cloudinary.com",
        "www.youtube-nocookie.com",
        "www.youtube.com",
        "player.vimeo.com"
    ]

This allows embedding localhost sites during development while maintaining security in production.

Hugo Security Configuration  

Build-time embedding detection issues a HEAD request to each preview URL during the build. Hugo’s default security policy only allows GET and POST methods. Add the following to your site’s config/_default/hugo.toml to enable HEAD requests:

[security]
  [security.http]
    methods = ['(?i)GET|POST|HEAD']
    urls = ['.*']

Without this setting, the HEAD requests are silently blocked and embedding restrictions are not detected. Use show-fallback: true to force the fallback explicitly — it is not affected by this setting.

Embedding Restrictions  

Many websites prevent iframe embedding using X-Frame-Options or Content-Security-Policy response headers. Hugo issues a HEAD request to each preview URL at build time and inspects the response headers. Detection coverage:

Response header Build-time action
X-Frame-Options (any value) Fallback rendered — blocks all cross-origin embedding
Content-Security-Policy: frame-ancestors 'none' Fallback rendered — blocks all embedding
Content-Security-Policy: frame-ancestors with specific domains No action — domain-specific; whether the iframe loads depends on the deployment domain
No relevant headers No action — embedding allowed by default

For frame-ancestors with specific domains (e.g. 'self' example.com *.example.com), Hugo cannot determine at build time whether the iframe will load on your site, since the allowed origins depend on the deployment domain. If you know a URL will not embed on your site, use show-fallback: true to render the fallback explicitly.

Best practices:

  • Use the preview component for sites you control or that explicitly allow embedding
  • Test URLs in development before deploying
  • Set image to a representative screenshot so users see meaningful content when embedding is blocked
  • Use show-fallback: true in offline or CI environments where the HEAD request cannot reach the target URL, or when a URL restricts embedding via domain-specific frame-ancestors headers
  • Use embeddable alternatives (e.g., youtube-nocookie.com instead of youtube.com)

Device Dimensions  

Device dimensions use logical pixels (CSS pixels), which is what browsers and responsive design tools use for layout. Physical pixels depend on the device pixel ratio (DPR) of the hardware display.

Device Logical resolution Aspect ratio DPR reference
Desktop 1440 × 900px 16:10 @1× (MacBook / laptop)
Tablet 820 × 1180px ~9:13 @2× (iPad 10th gen / iPad Air M2)
Mobile 402 × 874px 9:19.5 @3× (iPhone 17 Pro, 460 ppi)

A website loaded inside the iframe sees a viewport matching these logical pixel dimensions, so breakpoints and responsive layouts behave exactly as they would on the real device.

Auto-Scaling  

JavaScript scales each device on page load and on every browser resize. Tablet and mobile always use a contain fit — the largest scale where neither dimension is clipped:

scale = min(containerWidth / deviceWidth, containerHeight / deviceHeight, 1)

Desktop scaling depends on the desktop_responsive argument:

Mode desktop_responsive Behaviour
Responsive (default) true Scales to fill the full container width; iframe height is adjusted dynamically so the container height is also filled. The site inside sees a 1440px-wide viewport.
Strict aspect ratio false Contain fit — the full 1440 × 900px frame is always visible; symmetric gaps may appear above and below on wide containers.

The zoom recalculates on page load and whenever the browser window is resized.

Container height adapts to available viewport space and is capped so tall devices (tablet: 1180px logical) are never rendered beyond the available screen area:

height: min(calc(100vh - controls - navbar - 4rem),
            calc(var(--max-section-height, 1024px) - controls));
min-height: 400px;

Responsive Visibility  

The component automatically shows or hides device previews based on viewport width only:

  • Small screens (< 640px): Mobile preview only
  • Medium screens (640px–1023px): Tablet and mobile previews
  • Large screens (≥ 1024px): All three previews

Buttons for hidden device views are automatically hidden from the control bar, and the active view automatically switches when a panel becomes unavailable.

Container Constraints  

In responsive mode (default), the desktop preview fills whatever container it is placed in. For best results with desktop_responsive: false or when using cover: true:

  • Use fluid: true or width: 12 for full-width layouts
  • Use a container at least as wide as the desired desktop zoom level

Security  

The preview component includes iframe sandboxing for security:

sandbox="allow-scripts allow-same-origin allow-forms allow-popups"

This restricts iframe capabilities while allowing:

  • JavaScript execution (allow-scripts)
  • Access to same-origin resources (allow-same-origin)
  • Form submissions (allow-forms)
  • Opening popups/new windows (allow-popups)

Arguments  

The content block supports the following arguments:

Name Type Required Default Comment
_bookshop_name string Alias for _bookshop_name.
_ordinal int Zero-based position of the bookshop component within the page’s component hierarchy.
background background, string Background style of the section.
bg_class string Background class attributes of the element. It supports Bootstrap attributes to modify the background styling of the element.
controls_placement select top Position of the device selection button group relative to the preview area. Use “top” (default) to place the controls above the preview, or “bottom” to place them below. Supported values: [top, bottom].
cover bool Flag indicating if the element should be rendered fullscreen.
desktop_responsive bool true Controls how the desktop iframe scales within the preview container. When true (default), the iframe fills the full container width and height by adjusting its logical height dynamically — the website inside sees a 1440px-wide viewport at the current zoom level. When false, the desktop uses a strict 16:10 contain fit so the full 1440 × 900px frame is always visible with no clipping.
device select desktop Device view to display by default in preview component. Determines the initial iframe dimensions and active tab. Supported values: [desktop, tablet, mobile].
fluid bool true Flag to set the section container to fluid design, else the section is limited to xxl.
heading Heading Heading of the content block, including a preheading and content element.
id string Unique identifier of the current element.
image string Image to include in the content block or section heading.
justify select start Justification of the child elements. Supported values: [start, end, center, between, around, evenly].
mode bool Flag indicating if the media asset should support color modes. If set, the element searches for images having a matching color-mode suffix such as -light or -dark.
overlay_mode select Overlay mode of the element, overrides the site’s general configuration. Supported values: [light, dark, none].
section_class string Section class attributes of the element. It supports Bootstrap attributes to modify the section styling of the element.
show_fallback bool Forces the error overlay to be rendered server-side, bypassing build-time detection. Useful in offline or CI environments where the HEAD request cannot reach the target URL.
theme select Color theme to apply to the element. Supported values: [light, dark].
url string, template.URL yes Address of the link destination, either a local reference or an external address. Include the scheme when referencing an external address, such as https://google.com. Local references may include an optional anchor link such as blog/bootstrap-elements/#docs.
width int 8 Column width of the element. For embedded elements, the width is relative to the parent’s container.
wrapper string Class attribute of the element’s wrapper. It supports Bootstrap attributes to modify the styling of the element. Icons include the fa-wrapper and fa-fluid attributes by default.
Name Type Required Default
_bookshop_name string
Alias for _bookshop_name.
_ordinal int
Zero-based position of the bookshop component within the page’s component hierarchy.
background background, string
Background style of the section.
bg_class string
Background class attributes of the element. It supports Bootstrap attributes to modify the background styling of the element.
controls_placement select top
Position of the device selection button group relative to the preview area. Use “top” (default) to place the controls above the preview, or “bottom” to place them below. Supported values: [top, bottom].
cover bool
Flag indicating if the element should be rendered fullscreen.
desktop_responsive bool true
Controls how the desktop iframe scales within the preview container. When true (default), the iframe fills the full container width and height by adjusting its logical height dynamically — the website inside sees a 1440px-wide viewport at the current zoom level. When false, the desktop uses a strict 16:10 contain fit so the full 1440 × 900px frame is always visible with no clipping.
device select desktop
Device view to display by default in preview component. Determines the initial iframe dimensions and active tab. Supported values: [desktop, tablet, mobile].
fluid bool true
Flag to set the section container to fluid design, else the section is limited to xxl.
heading Heading
Heading of the content block, including a preheading and content element.
id string
Unique identifier of the current element.
image string
Image to include in the content block or section heading.
justify select start
Justification of the child elements. Supported values: [start, end, center, between, around, evenly].
mode bool
Flag indicating if the media asset should support color modes. If set, the element searches for images having a matching color-mode suffix such as -light or -dark.
overlay_mode select
Overlay mode of the element, overrides the site’s general configuration. Supported values: [light, dark, none].
section_class string
Section class attributes of the element. It supports Bootstrap attributes to modify the section styling of the element.
show_fallback bool
Forces the error overlay to be rendered server-side, bypassing build-time detection. Useful in offline or CI environments where the HEAD request cannot reach the target URL.
theme select
Color theme to apply to the element. Supported values: [light, dark].
url string, template.URL yes
Address of the link destination, either a local reference or an external address. Include the scheme when referencing an external address, such as https://google.com. Local references may include an optional anchor link such as blog/bootstrap-elements/#docs.
width int 8
Column width of the element. For embedded elements, the width is relative to the parent’s container.
wrapper string
Class attribute of the element’s wrapper. It supports Bootstrap attributes to modify the styling of the element. Icons include the fa-wrapper and fa-fluid attributes by default.

Background Type  

Name Type Required Default Comment
backdrop string Background image with a mask to improve contrast.
class string Class attributes of the element. It supports Bootstrap attributes to modify the styling of the element.
color select Theme color of the element. Supported values: [primary, secondary, success, danger, warning, info, light, dark, white, black, body, body-tertiary].
subtle bool Apply subtle theme colors.
Name Type Required Default
backdrop string
Background image with a mask to improve contrast.
class string
Class attributes of the element. It supports Bootstrap attributes to modify the styling of the element.
color select
Theme color of the element. Supported values: [primary, secondary, success, danger, warning, info, light, dark, white, black, body, body-tertiary].
subtle bool
Apply subtle theme colors.

Heading Type  

Name Type Required Default Comment
align select start Alignment of the headline, content, or icon. Supported values: [start, center, end].
arrangement select above Arrangement of the preheading, either left or above the header. On smaller screens, the preheading is always placed on top. Supported values: [above, first].
content string, template.HTML Section content displayed below the title.
preheading string Preheading of the section heading.
size int 4 Display size of the headline.
title string, hstring.RenderedString, hstring.HTML, template.HTML Title of the element. If the element references a (local) page, the title overrides the referenced page’s title.
width int 8 Column width of the element. For embedded elements, the width is relative to the parent’s container.
Name Type Required Default
align select start
Alignment of the headline, content, or icon. Supported values: [start, center, end].
arrangement select above
Arrangement of the preheading, either left or above the header. On smaller screens, the preheading is always placed on top. Supported values: [above, first].
content string, template.HTML
Section content displayed below the title.
preheading string
Preheading of the section heading.
size int 4
Display size of the headline.
title string, hstring.RenderedString, hstring.HTML, template.HTML
Title of the element. If the element references a (local) page, the title overrides the referenced page’s title.
width int 8
Column width of the element. For embedded elements, the width is relative to the parent’s container.
Follow Me

I work on everything coding and tweet developer memes