renderchat shortcode - Open WebUI chats in Hugo sites

Table of Contents
Introduction#
Since I’m using AI to help me more quickly brain dump my non-linear thoughts into a more readable format, I thought it would sometimes be handy to display Open WebUI chats in Hugo sites. This is where the renderchat
shortcode comes in.
Installation#
To use the renderchat
shortcode, you can do this by creating a file in your site, layouts/shortcodes/renderchat.html
, and adding the following code:
{{/* renderchat.html */}}
{{ $file := .Get "file" }}
{{ if eq $file "" }}
<p>No chat log file specified.</p>
{{ return }}
{{ end }}
{{ $jsonResource := .Page.Resources.GetMatch $file }}
{{ if not $jsonResource }}
<p>Could not find the chat log file: {{ $file }}</p>
{{ return }}
{{ end }}
{{ $json := $jsonResource | transform.Unmarshal }}
{{ if not $json }}
<p>Failed to parse the chat log JSON file.</p>
{{ return }}
{{ end }}
{{ range $json }}
<div class="chat-log">
<h2 class="chat-title">{{ .title }}</h2>
<div class="chat-messages">
{{ $messages := slice }}
{{ range .chat.history.messages }}
{{ $messages = $messages | append . }}
{{ end }}
<!-- Create a map of messages by ID -->
{{ $messageMap := dict }}
{{ range $messages }}
{{ $messageMap = merge $messageMap (dict (printf "%s" .id) .) }}
{{ end }}
<!-- Render root messages -->
{{ range (where $messages "parentId" "==" nil) }}
{{ template "renderMessageWithChildren" dict "message" . "map" $messageMap }}
{{ end }}
</div>
</div>
{{ end }}
{{/* Recursive template to render messages */}}
{{ define "renderMessageWithChildren" }}
{{ $message := .message }}
{{ $map := .map }}
<!-- Render current message -->
<div class="chat-message {{ $message.role }}">
<strong>{{ if eq $message.role "user" }}User{{ else }}{{ $message.model }}{{ end }}:</strong>
<div style="white-space: pre-wrap;">{{ $message.content }}</div>
</div>
<!-- Render children recursively -->
{{ range $message.childrenIds }}
{{ $child := index $map . }}
{{ template "renderMessageWithChildren" dict "message" $child "map" $map }}
{{ end }}
{{ end }}
Now we’ll need CSS code. My theme will load any CSS that I put in assets/css/extended/
so I added a file in there called renderchat.css
. Here’s the CSS code for the chat log:
/* Chat container */
.chat-log {
margin: 20px 0;
padding: 10px;
border: 1px solid var(--hugo-chat-border-color, #444);
border-radius: 5px;
background-color: var(--hugo-chat-bg, #222); /* Dark-friendly */
color: var(--hugo-chat-text-color, #ddd); /* Text color */
}
/* Title styling */
.chat-title {
font-size: 1.5rem;
margin-bottom: 10px;
text-align: center;
color: var(--hugo-chat-title-color, #fff);
}
/* Chat messages container */
.chat-messages {
display: flex;
flex-direction: column;
gap: 10px; /* Spacing between messages */
}
/* Chat message bubbles */
.chat-message {
max-width: 60%;
padding: 10px 15px;
border-radius: 15px;
display: inline-block;
line-height: 1.5;
background-color: var(--hugo-chat-message-bg, rgba(255, 255, 255, 0.1)); /* Semi-transparent */
color: var(--hugo-chat-message-color, inherit);
text-align: left;
}
/* User-specific styling */
.chat-message.user {
align-self: flex-end;
font-weight: bold;
background-color: var(--hugo-chat-user-bg, rgba(0, 150, 136, 0.2)); /* Soft teal with transparency */
color: var(--hugo-chat-user-color, #fff); /* White text */
}
/* Assistant-specific styling */
.chat-message.assistant {
align-self: flex-start;
font-style: italic;
background-color: var(--hugo-chat-assistant-bg, rgba(100, 100, 100, 0.2)); /* Gray with transparency */
color: var(--hugo-chat-assistant-color, #fff); /* White text */
}
Example#
I’m using page bundles with this site, which makes it easy to just drop a chat log file downloaded straight from Open WebUI into my bundle, and referencing it with a shortcode like this (and note how I switched models partway through the chat, and the shortcode picked up on this):