Homepage
>
posts
json
  • 2023-01-02 12:24:37 +0100 +0100

    @ExAniron

    Jan 02, 2023

    Really crude attempt at recreating in Hugo the link preview feature that you see on various social networks.

    Socials facebook Socials tumblr Socials twitter

    My result:

    Thumbnail preview for linked website
    🔗 Hugo Documentation

    Hugo is the world's fastest static website engine. It's written in Go (aka Golang) and developed by bep, spf13 and friends.

    To do this I used the iframely.com API together with some precautions to avoid hitting the request limit.

    How the API works

    Iframely offer 2 API endpoints: “oEmbed” and “Iframely”. The first is good enough for a basic link preview and follows some standard formatting so we are secure regarding API changes. The latter is more feature rich but it’s overblown for my use case, I think it would be trivial enough to implent on your own if you want.

    How to use it in your theme

    We are just going to implement a simple Hugo Shortcode to display an automatic link preview

    To use in your markdown file:

    {{<oembed "https://gohugo.io/">}}
    

    The API key to put in your config.toml

    [params]
    iframely = "1234567890pleasechangeme"
    

    In your layouts/partials/oembed.html

    {{ $url := (index .Params 0) }}
    {{ $reqUrl := printf "https://iframe.ly/api/oembed?url=%s&api_key=%s"  $url $.Site.Params.iframely }}
    {{ with $oembed := getJSON $reqUrl }}
    {{ with .Err }}
        {{ warnf "%s" . }}
        <div>
        <a href="{{  $url }}">{{  $url }}</a>
        </div>
    {{ else }}
        <div>
        {{with .thumbnail_url  }}
        {{ with resources.GetRemote . }}
            <img 
            src="{{ (.Fill "200x200 smart webp q90" ).RelPermalink }}" 
            />
        {{end}}
        {{end}}
        <div >
            <a href="{{.url}}">🔗 {{.title}}</a>
            {{ with .description }}<p>{{.}}</p>{{end}}
        </div>
        </div>
    {{ end }}
    {{ end }}
    

    You can obviusly change the layout of the shortcode and style it with CSS as you please, this is just a proof of concept.

    Notice how

    How to not hit the API limit.

    Hugo can cache the JSON requests and use them to avoid depleting your API quota at every render. In your config.toml:

    [caches]
      [caches.getjson]
        maxAge = -1
    

    Be sure to save the cache between renders if your “deploy infrastructure” resets at every run. If you run it on Netlify it should save everything out of the box, if you are like me and use Github Actions then there is some fiddling to do.

    For my setup the easiest way was to change the JSON cache folder and then push the eventual new JSON cache back to my repository.

    Back in your config.toml:

    [caches]
      [caches.getjson]
        dir = ':resourceDir/_gen/'
        maxAge = -1
    

    And then in your Github Actions workflow.yml, after the rendering:

          - name: GIT Commit Build Artifacts (coverage, dist, devdist, docs)
            # Only run on main branch push (e.g. after pull request merge).
            if: github.event_name == 'push'
            run: |-
              git add .
              git diff
              git config --global user.email "yourprivatemail@users.noreply.github.com"
              git config --global user.name "GitHub Action Bot"
              git commit -m "auto-update resource cache" -a || echo "No changes to commit"
              git push        
            shell: bash
    

    To avoid a recursive loop where pushing back to your repo triggers a second render we need to ignore the commits to the cache directory:

    on:
      push:
        branches:
          - main
        paths-ignore:
          - 'resources/_gen/**'
    

    This simple trick can help you stay in your monthly quota without any worries. You can easily spot the before and after in this graph.

    2023-01-02 12:24:37 +0100 +0100 January 2, 2023
    #Hugo #Iframely
    Last update: May 08, 2025