Preface#
Recently, I saw a blog post by "Uncle Qin" titled "Website Restart" mentioning that due to an expired domain left by someone in the blog comments linking to a pornographic website, it led to issues related to pornography. This shows that in the current online environment in mainland China, such minor offenses are being cracked down on more strictly.
To comply and self-censor, I did two things for my blog: first, I migrated the comment system to Giscus, which raised the threshold for comments and put them in a semi-closed state; second, I cleaned up some links in the blog, allowing the remaining links to redirect through a landing page. Coincidentally, I saw "Kongbai" update their blog "HUGO External Link Redirect to Intermediate Page", and I directly copied the style, completing one item on my Todo list.
PS: I believe that a serious personal website can be filed for record. But if you want to do something less serious, what you need is complete identity isolation, not just avoiding filing while exposing many related cross-identity information. No paternalism, love it or leave it.
Definition#
External Link: Fully known as an external link, also known as an inbound link. It refers to links from other websites on the internet that lead to one's own website. Hereinafter referred to as "external link."
Creating a Redirect Page with 3 Files#
My design approach is somewhat different from the first version of "Kongbai's" JS method. I utilized Hugo's built-in template _markup
's render-link.html to base64 encode external links during Hugo's build process using Hugo's built-in base64Encode
command, fully leveraging the features of SSG.
1. Create or Modify render-link.html#
_markup/render-link.html
is Hugo's built-in template for rendering links. If the theme selected for the blog does not have a custom render-link.html, you need to create this file yourself. If the theme has already customized link rendering, you can directly modify this file. The file is located in the layouts
directory at the root of the Hugo project:
layouts/
└── _default/
└── _markup/
├── render-codeblock-bash.html
├── render-codeblock.html
├── render-heading.html
├── render-image.html
├── render-image.rss.xml
└── render-link.html # < --- This file
The content of the file I used:
$domainList
serves as a whitelist.
{{- $domainList := slice "www.eallion.com" "github.com" "twitter.com" -}}
{{- $parsedDestination := urls.Parse .Destination -}}
{{- $host := $parsedDestination.Host -}}
{{- $matched := false -}}
{{- range $domainList -}}
{{- if strings.HasSuffix $host . -}}
{{- $matched = true -}}
{{- break -}}
{{- end -}}
{{- end -}}
{{- if $matched -}}
<a href="/go/?target={{ .Destination }}" target="_blank" rel="noopener noreferrer">{{ .Text | safeHTML}}</a>
{{- else -}}
<a href="/go/?target={{ .Destination | base64Encode }}" target="_blank" rel="noopener noreferrer">{{ .Text | safeHTML}}</a>
{{- end -}}
PS: For the DoIt theme, you only need to modify layouts/partials/plugin/link.html.
Tips: Using
render-link.html
allows the blog to open in a new window, i.e.,target="_blank"
. Many Asian users are searching for this trick.
2. Create Layout Template go.html#
Create a page template, such as go.html
, located in the layouts/_default/go.html
of the Hugo project root. A simple way is to copy single.html
and rename it to go.html
.
layouts/
└── _default/
└── go.html # < --- This file
Here is my content, placing HTML, CSS, and JS in the same page for easier maintenance. Besides ensuring that the <div class="redirect-all">
element is in the correct position in your template, it is basically ready to use.
{{- define "title" }}{{ .Title }} - {{ .Site.Title }}{{ end -}}
{{- define "content" -}}
{{- $params := .Scratch.Get "params" -}}
<style>
.redirect-all {
position: relative;
box-shadow: rgba(0, 0, 0, 0.25) 0px 25px 50px -12px;
border-radius: 10px;
color: #666;
word-break: break-all;
max-width: 800px;
height: 400px;
text-align: center;
font-size: 0.85rem;
overflow: hidden;
margin: 100px auto 0;
background: #fff url(/assets/images/redirect/redirect-light.webp) no-repeat center center / cover;
@include breakpoint('small') {
aspect-ratio: 2 / 1;
height: auto;
}
}
.redirect-nrong {
position: absolute;
bottom: 0;
left: 0;
right: 0;
padding: 1.5rem 1rem
}
.redirect-title {
font-size: 1.25rem;
font-weight: bold;
color: #222;
margin-bottom: 0.5rem;
}
.redirect-info {
margin-top: 6px;
}
.redirect-tis {
display: flex;
align-items: center;
justify-content: center;
gap: 20px;
margin-top: 1rem;
margin-bottom: 2px;
flex-wrap: wrap;
}
.redirect-button {
display: flex;
align-items: center;
border-radius: 3px;
border: none;
background: #006bee;
height: 32px;
padding: 0 14px;
cursor: pointer;
outline: 0;
}
.redirect-button a {
color: #fff !important;
}
[theme=dark] .redirect-all {
background: #fff url(/assets/images/redirect/redirect-dark.webp) no-repeat center center / cover;
color: #999;
}
[theme=dark] .redirect-title {
color: #ddd;
}
</style>
<div class="page single special">
{{- /* Content */ -}}
<div class="content" id="content">
<div class="redirect-all">
<div class="redirect-nrong">
<div class="redirect-title">You are about to leave {{ .Site.Title }} and redirect to the following external link</div>
<a href="" target="_self" rel="noopener noreferrer" id="redirect-link"><span id="redirect-link">Redirect target not specified.</span></a>
<div class="redirect-info">Please identify whether this link is safe, and pay attention to your account and property security.</div>
<div class="redirect-tis">
<div class="redirect-button"><a href='' target="_self" id='direct-link' rel="noopener noreferrer">Go Now</a></div>
</div>
</div>
</div>
</div>
</div>
<script>
const params = new URLSearchParams(window.location.search);
const encodedTarget = params.get('target');
const target = atob(encodedTarget); // Use atob for Base64 decoding
if (target) {
const decodedTarget = decodeURIComponent(target);
document.getElementById('direct-link').href = decodedTarget;
document.getElementById('redirect-link').textContent = '' + decodedTarget; // Display the original address in the new element
document.getElementById('redirect-link').href = decodedTarget;
} else {
const redirectMessageElement = document.getElementById('redirect-link');
redirectMessageElement.textContent = 'Redirect target not specified.';
}
</script>
{{- end -}}
3. Create go.md to Call the Template#
In the content
directory of the Hugo project, create a file named go.md
, where go
will be the link path for the redirect page. The Front matter of the go.md
file should select the corresponding template you just created; if the template name is go.html
, then the layout or type should be set to go
.
---
title: "Redirect"
layout: "go"
type: "go"
... ...
---
4. Background Image#
Place the background image in the static directory:
or in a location you can reference correctly, such as a CDN, and modify the background
url in the <style>
. Additionally, you need to adapt it to your theme's Dark mode.
static/assets/images/redirect/redirect-light.webp
static/assets/images/redirect/redirect-dark.webp
Other Considerations#
This method can only render all Markdown content documents in this blog, i.e., .md
files in the content
directory. If you are accustomed to using {{ Shortcodes }}
for posting, or if the page has custom HTML links, you need to make the link path base64 compatible yourself. This template can parse links like href="/go/?target={{ base64Encode }}"
within the blog, excluding the whitelist.