Hugo启动器

scanlines — Hugo 启动器模板

作者 wthouse

scanlines 是一个受 DEC VT220/VT100 CRT 终端启发的复古极简 Hugo 主题,纯 CSS 实现、无 JavaScript,自带终端配色与 CRT 视觉效果。

看看你的网站会是什么样

浏览真实页面截图,比较内容排版与手机效果。点击下方缩略图切换,放大查看整页细节。

3 个预览视图
桌面端首页1 / 3
桌面端截图首屏预览

由服务器浏览器实际访问页面后截取。

全部页面与视图 3

截图用于了解视觉与布局,交互效果请以实际项目为准。

采集于 2026-10-03查看来源

值得关注的模板亮点

从已有项目资料中,快速了解它的特点。

01

纯 CSS 实现的 CRT 视觉效果,包括扫描线、磷光辉光、屏幕闪烁、暗角和屏幕曲率,可逐项开关并调节强度

02

提供琥珀(P3)、绿色(P1)、蓝色和白色四种历史磷光配色,也支持自定义十六进制颜色覆盖

03

无 JavaScript,字体与资源自托管,不请求外部 CDN

04

首页可选 blog 或 profile 两种模式,profile 模式提供姓名、简介、社交图标和自定义按钮的落地页

05

页头支持从 static 目录加载自定义 ASCII 艺术文件作为站点标题,底部状态栏显示站点标题、栏目和阅读时间等信息

06

支持 Chroma 语法高亮(单色或多色)、可折叠目录、标签与分类、阅读时间,以及 Open Graph、Twitter 卡片、JSON-LD 和 RSS 等 SEO 输出

模板详细介绍

scanlines 是一个 Hugo 主题,视觉风格参考 DEC VT220、VT100 等经典 CRT 终端。它提供琥珀(P3)、绿色(P1)、蓝色和白色四种磷光配色,并带有扫描线、磷光辉光、屏幕闪烁、暗角和屏幕曲率等 CRT 效果,所有效果都可在配置中单独开关和调节强度。主题不依赖 JavaScript,交互与视觉效果由纯 CSS 完成,字体和资源自托管,不请求外部 CDN。

首页支持两种模式:blog 模式展示站点标语与近期文章,profile 模式作为个人落地页,显示姓名、简介、社交图标和自定义按钮,并隐藏常规导航。文章页支持可折叠目录、标签与分类、阅读时间、摘要,以及基于 Chroma 的代码高亮(可选单色或多色)。主题还提供 SEO 相关输出,包括语义化 HTML、meta 标签、Open Graph、Twitter 卡片、JSON-LD 结构化数据和 RSS。

可配置项集中在 [params.scanlines] 命名空间下,涵盖配色、首页模式、CRT 效果、无障碍、页头、目录、状态栏、布局、排版、语法高亮和社交链接。页头可加载自定义 ASCII 艺术文件作为站点标题,底部状态栏显示站点标题、当前栏目和上下文信息,在移动端隐藏。无障碍方面,主题响应 prefers-reduced-motion,并提供高对比度、减少动画和完全关闭 CRT 效果的开关。

使用前需注意若干限制:需要 Hugo Extended 0.146.0 或更高版本;若使用 Hugo Modules 方式安装还需 Go 1.18+,而子模块、克隆和 ZIP 方式只需 Git。默认字体 glass(Glass TTY VT220)只覆盖 ASCII 与 DEC 多国字符集(大致相当于 Latin-1),因此需在 hugo.toml 中设置 typographer = false,否则 Hugo 会把引号和破折号改写为该字体缺失的弯引号和长破折号;改用 fira(Fira Code)则无此问题。代码高亮需设置 noClasses = false,否则 Hugo 会内联 monokai 颜色,主题的语法样式和 colored 开关将失效。文章中的图片在开启 CRT 效果时会应用部分灰度处理,扫描线叠加只作用于用 Hugo figure 短代码包裹的图片,普通 Markdown 图片只有灰度和懒加载。

Hugo启动器

适合你的项目吗?

适用场景

  • 搭建带有复古终端外观的个人博客,展示近期文章与标签
  • 制作个人落地页,通过 profile 模式呈现姓名、简介、社交链接和自定义按钮
  • 发布技术文章,使用代码高亮、可折叠目录和标签分类组织内容
  • 需要无 JavaScript、资源自托管、不依赖外部 CDN 的静态站点

适合人群

  • 使用 Hugo 并希望获得 CRT 终端视觉风格的博客作者
  • 需要 blog 或 profile 两种首页形态的个人站点
  • 偏好无 JavaScript、自托管字体与资源的静态站点项目
  • 对复古配色和终端细节(如状态栏、ASCII 页头)有明确需求的用户

上手与定制指南

结合仓库当前版本的说明,按下面的资料检查内容、配置与运行要求。

  1. 1

    需要 Hugo Extended 0.146.0 或更高版本;使用 Hugo Modules 安装还需 Go 1.18+,子模块、克隆和 ZIP 方式只需 Git

  2. 2

    使用默认 fontFamily = "glass" 时,应在 hugo.toml 中设置 [markup.goldmark.extensions] typographer = false,避免弯引号和长破折号因字体缺失而回退

  3. 3

    代码高亮需在 hugo.toml 中设置 [markup.highlight] noClasses = false,否则主题的语法样式和 colored 开关不生效

  4. 4

    所有主题选项位于 [params.scanlines] 命名空间下,可按需配置配色、首页模式、CRT 效果、无障碍、页头、目录、状态栏、布局、排版和社交链接

  5. 5

    开启 CRT 效果时文章图片会应用部分灰度处理,扫描线叠加仅作用于 figure 短代码包裹的图片

查看仓库使用说明

授权与来源资料

使用条件与限制

免费使用 · 保留许可声明

本次收录的是公开仓库中采用 MIT 许可的免费版本;免费范围为该版本代码,不代表外部服务或第三方素材免费。

使用时需要遵守

  • 允许免费使用、修改、商用和分发该版本代码。
  • 分发代码副本或实质性部分时,保留原作者版权声明和完整 MIT 许可声明。
  • 代码按现状提供;担保与责任限制以原许可证及适用法律为准。

额外费用与待核对事项

  • 必须使用 Hugo Extended 0.146.0 或更高版本,普通版 Hugo 无法处理 SCSS 与 0.146+ 模板系统。
  • 仅当采用 Hugo Modules 方式安装时才需要 Go 1.18+;子模块、克隆和 ZIP 方式只需 Git。
  • 使用默认 glass 字体时必须在 hugo.toml 中关闭 typographer,否则弯引号和长破折号会因字体缺失而回退到其他字体。
  • 代码高亮必须在 hugo.toml 中设置 noClasses = false,否则 Hugo 内联 monokai 颜色,主题语法样式与 colored 开关失效。
  • 扫描线叠加仅作用于用 Hugo figure 短代码包裹的图片,普通 Markdown 图片只有灰度与懒加载,无叠加效果。
  • 主题不含内置搜索;如需搜索须自行引入外部引擎或 Pagefind 等,会向站点添加 JavaScript。
  • 评论、分析等集成需自行引入第三方脚本,运行时从他人源加载代码,存在第三方信任与 CSP 配置要求。
  • 演示图片、字体、图标及其他第三方素材需按各自许可核对,不能仅凭代码的 MIT 许可判断。
  • 域名、托管、数据库、支付或 AI 等外部服务可能另外收费。
查看原文依据

Permission is hereby granted, free of charge

许可证原文

**Hugo Extended** v0.146.0 or later (SCSS processing; render hooks use the 0.146+ template system)

README 原文

**Go** 1.18+ — only for the Hugo Modules install shown above.

README 原文

set > `[markup.goldmark.extensions] typographer = false` in your `hugo.toml`.

README 原文

Add `[markup.highlight]` with `noClasses = false` > to your `hugo.toml` so code uses the theme's terminal styling.

README 原文

The additional scanline overlay applies to images wrapped in a `<figure>` — i.e. those inserted with Hugo's `figure` shortcode.

README 原文

There's no built-in search: every client-side option (Fuse.js, Pagefind, Lunr) ships JavaScript, which the theme deliberately doesn't.

README 原文

The snippets below load code > from someone else's origin at runtime, so that provider can change what > executes on your site.

README 原文
https://github.com/wthouse/scanlines/blob/main/LICENSEhttps://github.com/wthouse/scanlines/blob/main/README.md

DeepSeek 根据仓库许可证和 README 整理 ·2026-10-03。结果仅覆盖已读取资料,依赖、图片、字体及后续条款变更以各自原文为准。

项目核对记录与介绍依据

模板资料

来源平台
Hugo Themes
资料与维护参考分
资料较完整 · 83 / 100
技术栈
Hugo
网站类型
启动器
这个分数如何计算

本站按许可资料(最高30分)、演示链接(12分)、预览图(10分)、Star数(15分)、记录的维护时间(15分)、描述完整度(8分)、功能记录(5分)和分类资料(5分)计算。它不是代码、安全或性能测试,也不是 Google 评分;有链接不代表已实测可用。

这个项目需要核对什么

记录的仓库更新时间
2026-08-28
截图检查日期
2026-10-03

已收录演示链接。请用你的内容与屏幕尺寸检查;有演示不代表表单、认证或支付已经可用。

目录记录的主要技术栈是 Hugo。请通过依赖清单和锁文件核对实际版本与托管要求。这些说明基于收录资料,不代表代码审计或部署实测。

查看具体选型方法 →

介绍的制作与核对状态

介绍由 AI 辅助整理目录与仓库资料。仓库作者不等于这篇介绍的审核者。

已完成服务器许可规则与 AI 来源核对;未经过人工编辑审核。

查看当时使用的来源资料

SHA-256: daae8d9860a01d176e44f3279decb959ce2b57e98280ac1a0bdf8eb41ee97720

2026-10-03T03:17:11.793Z

来源文件 / 仓库
<p align="center">
  <img src="https://raw.githubusercontent.com/wthouse/scanlines/main/images/logo.svg" alt="Scanlines" width="100%">
</p>

[![Build](https://github.com/wthouse/scanlines/actions/workflows/build.yml/badge.svg)](https://github.com/wthouse/scanlines/actions/workflows/build.yml)
[![Release](https://img.shields.io/github/v/release/wthouse/scanlines?color=FFB000&label=release)](https://github.com/wthouse/scanlines/releases/latest)
[![Hugo](https://img.shields.io/badge/hugo-%E2%89%A50.146.0-FFB000)](https://gohugo.io)
[![License: MIT](https://img.shields.io/badge/license-MIT-FFB000)](LICENSE)
[![No JavaScript](https://img.shields.io/badge/javascript-none-FFB000)](#features)

A retro Hugo theme inspired by the look and feel of classic CRT terminals like the DEC VT220 and VT100. Features historically accurate phosphor color schemes, authentic CRT visual effects, and a clean, minimal design.

**[Live demo](https://scanlines.pages.dev)** · [Installation](INSTALLATION.md) · [Configuration](#configuration-reference) · [Changelog](CHANGELOG.md) · [Contributing](CONTRIBUTING.md)

![Scanlines theme - Blog homepage](https://raw.githubusercontent.com/wthouse/scanlines/main/images/homepage_blog.png)

## Features

- **Authentic CRT Effects** - Scanlines, phosphor glow, screen flicker, vignette, and screen curvature
- **Historical Color Schemes** - Amber (P3), Green (P1), Blue, and White phosphor emulation
- **Terminal Status Line** - Fixed 25th-line status bar with blinking cursor (a VT320 feature; the VT220 itself was a 24-line screen)
- **ASCII Art Header** - Load custom ASCII art from a file for your site title
- **Two Homepage Modes** - Blog (recent posts) or Profile (landing page with buttons)
- **Responsive Design** - Mobile-first with collapsible navigation and TOC
- **Syntax Highlighting** - Chroma integration with monochrome or colored modes
- **SEO Optimized** - Semantic HTML, meta tags, Open Graph, Twitter cards, JSON-LD structured data, RSS
- **Fully Configurable** - All options namespaced under `params.scanlines`
- **No External Dependencies** - Self-hosted WOFF2 fonts and assets
- **No JavaScript** - Pure CSS effects and interactions
- **Translatable** - All UI strings run through Hugo's i18n system (ships `i18n/en.toml`)
- **Render Hooks** - Lazy-loaded images, heading permalinks, and external links that open in a new tab
- **Accessibility** - Respects `prefers-reduced-motion`, configurable contrast, VT220-style reverse-video focus

## Quick Start

```bash
# Initialize Hugo module (if not already)
hugo mod init github.com/your-username/your-site
```

Add to your `hugo.toml`:

```toml
[module]
  [[module.imports]]
    path = "github.com/wthouse/scanlines"
```

```bash
# Download/update the theme and start the server (requires hugo-extended)
hugo mod get -u
hugo server
```

> **Typography:** on the default `fontFamily = "glass"`, set
> `[markup.goldmark.extensions] typographer = false` in your `hugo.toml`. A VT220
> could only display ASCII and the DEC Multinational Character Set (roughly
> Latin-1), and Glass TTY VT220 matches that repertoire. Left on, Hugo rewrites
> quotes and dashes into curly quotes and em dashes, which that font lacks — so
> they fall back to a different face mid-sentence. Fira Code has the full
> repertoire, so `fontFamily = "fira"` needs no change.

> **Code blocks:** Hugo's default highlighter inlines its own (monokai) colors,
> which clash with the theme. Add `[markup.highlight]` with `noClasses = false`
> to your `hugo.toml` so code uses the theme's terminal styling. See
> [Syntax Highlighting](#syntax-highlighting).

## Requirements

- **Hugo Extended** v0.146.0 or later (SCSS processing; render hooks use the 0.146+ template system)
- **Go** 1.18+ — only for the Hugo Modules install shown above. The submodule,
  clone and ZIP methods in [INSTALLATION.md](INSTALLATION.md) need nothing but Git.
- No other build tools, package managers or CDN requests

## Configuration Reference

All theme options are namespaced under `[params.scanlines]` in your `hugo.toml`.

### Basic Options

```toml
[params.scanlines]
  # Color scheme: "amber" (default), "green", "blue", "white"
  colorScheme = "amber"

  # Homepage style: "blog" (default) or "profile"
  # "blog"    — site tagline + recent posts
  # "profile" — profile header + buttons (landing page, nav hidden)
  homepage = "blog"

  # Favicon path (relative to static folder)
  favicon = "/favicon.ico"

  # Date format (Go date format string)
  dateFormat = "2006-01-02"

  # Show reading time on posts
  showReadingTime = true

  # Show tags on post listings
  showTags = true

  # Section that holds your posts. The homepage, archive and 404 read from it —
  # change this if your content lives in e.g. content/articles/.
  contentSection = "posts"

  # Default Open Graph / Twitter share image, used when a page sets no `image`.
  # Pages with a `summary_large_image` card need this (or a per-page image).
  ogImage = "/images/og-default.png"

```

### Homepage Modes

**Blog mode** (default): Shows a tagline and recent posts with tags.

**Profile mode**: A landing page with your name, bio, social icons, and configurable buttons. Navigation is hidden — visitors navigate via the buttons you define.

![Profile mode](https://raw.githubusercontent.com/wthouse/scanlines/main/images/homepage_profile.png)

```toml
[params.scanlines]
  homepage = "profile"

[params.scanlines.profile]
  name = "Your Name"
  subtitle = "Your Title"
  avatar = "/images/avatar.png"  # Optional
  bio = "A brief bio about yourself."

  # Buttons shown on profile homepage
  [[params.scanlines.profile.buttons]]
    name = "Posts"
    url = "/posts/"
  [[params.scanlines.profile.buttons]]
    name = "About"
    url = "/about/"
```

### Custom Colors

Override the default color scheme with custom hex values:

```toml
[params.scanlines.colors]
  foreground = "#FFB000"
  background = "#0D0A00"
  backgroundSecondary = "#1A1400"
  accent = "#FF8C00"
  link = "#FFB000"
  linkHover = "#FFD966"
```

### CRT Visual Effects

```toml
[params.scanlines.effects]
  enabled = true           # Master toggle for all effects
  scanlines = true         # Horizontal scanline overlay
  scanlineOpacity = 0.4    # 0.0 - 1.0
  flicker = false          # Screen flicker animation
  flickerIntensity = 0.03  # 0.0 - 1.0 (0.03 barely visible, 0.15 subtle)
  vignette = true          # Phosphor edge fade + subtle screen curvature
  vignetteIntensity = 0.8  # 0.0 - 1.0
  glow = true              # Text phosphor glow
  glowIntensity = 0.8      # 0.0 - 2.0
```

When CRT effects are enabled, images in articles get a partial-grayscale phosphor
treatment so photos sit naturally on the terminal background; hovering eases the
filter back (it doesn't fully restore the original colors). The additional
scanline overlay applies to images wrapped in a `<figure>` — i.e. those inserted
with Hugo's `figure` shortcode. Plain markdown images (`![alt](src)`) get the
grayscale treatment and lazy loading, but no overlay.

### Accessibility

```toml
[params.scanlines.accessibility]
  highContrast = false      # Boost contrast levels
  reduceMotion = false      # Disable all animations
  disableEffects = false    # Turn off all CRT effects entirely
```

The theme also respects the `prefers-reduced-motion` media query automatically:
every animation (screen flicker, the status-line cursor blink, smooth scrolling)
stops. Static effects — scanlines, vignette, glow — stay visible, since they
don't move; use `disableEffects` to remove those too.

### Header

```toml
[params.scanlines.header]
  showTitle = true                  # Show site title or ASCII art (default: true)
  asciiFile = "ascii-header.txt"  # ASCII art file in static/ (leave empty for plain text title)
  showBox = true                  # Show border around header (default: true)
  asciiScale = 1.0                # Multiplier for ASCII art size (1.5 = 50% larger)
```

To use ASCII art, create a text file in your `static/` folder (e.g., `static/ascii-header.txt`). If no file is set, the site title displays as plain text.

### Table of Contents

```toml
[params.scanlines.toc]
  enabled = true
  collapsible = true        # Collapsible toggle
  title = "CONTENTS"
```

Posts show a TOC by default when they have headings; other pages (e.g.
`/about/`) opt in with `toc: true` front matter. A page-level `toc: false`
always hides it.

### Status Line

A fixed status bar at the bottom of the screen. The 25th status line arrived
with the VT320 (DECSSDT/DECSASD) rather than the VT220, which displayed 24
lines — the theme borrows it because it is the detail that reads as "terminal". Displays site title, current section, and contextual info (reading time, post count, or phosphor type). Hidden on mobile.

```toml
[params.scanlines.statusLine]
  enabled = true
```

### Layout

```toml
[params.scanlines.layout]
  containerWidth = "1200px"   # Max width of the container
  contentWidth = "40rem"      # Max width of the content area (80 columns; rem so it tracks baseFontSize)
```

### Typography

```toml
[params.scanlines.typography]
  baseFontSize = "20px"       # Base font size (rem units scale from this)
  fontFamily = "glass"        # "glass" (Glass_TTY_VT220) or "fira" (Fira Code)
```

### Syntax Highlighting

Scanlines styles code with Chroma's **class-based** highlighting, which requires
`noClasses = false` in your `hugo.toml`. Without it, Hugo inlines its own
(monokai) colors and the theme's styling — including the `colored` toggle below —
has no effect:

```toml
[markup.highlight]
  noClasses = false           # required: use the theme's syntax styling
  lineNos = true              # optional: show line numbers
  lineNumbersInTable = true   # optional: keeps line numbers selectable
```

```toml
[params.scanlines.syntax]
  colored = false             # false = monochrome (matches theme)
                              # true = multi-color syntax highlighting
```

### Social Links

```toml
[params.scanlines.social]
  github = ""
  twitter = ""
  linkedin = ""
  mastodon = ""              # Full URL for Mastodon
  medium = ""                # Username (without @)
  hackthebox = ""            # Profile UUID
  bluesky = ""               # Handle (e.g., "you.bsky.social")
  youtube = ""               # Channel handle (without @)
  discord = ""               # User ID
  steam = ""                 # Custom URL ID
  email = "[email protected]"
  rss = true
```

## Page Types

### Home Page
Configurable as either a blog listing or profile landing page (see Homepage Modes above).

### Blog Posts
Create posts in `content/posts/` (or your configured `contentSection`). Supports:
- Inline, collapsible table of contents
- Tags and categories (both render on the post and generate taxonomy pages)
- Reading time
- Post summaries (front-matter `summary` or `description`)

Tags use a `#name` chip; categories use a `/name` chip. Both link to their
taxonomy term pages, which are labelled automatically.

#### Post front matter

Every key is optional. `hugo new posts/my-post.md` starts you off with the
common ones (see `archetypes/posts.md`).

| Key | Type | Effect |
|-----|------|--------|
| `title` | string | Post title — heading, `<title>`, share cards, JSON-LD |
| `date` | date | Publication date. Omit it and the post shows no date in listings |
| `description` | string | Meta description, share-card text, JSON-LD, and RSS. Used as the listing excerpt when `summary` is unset |
| `summary` | string | Listing excerpt. Takes precedence over `description` in listings; also used for the RSS item when `description` is unset. With neither set, listings fall back to Hugo's auto-summary of the opening content |
| `image` | path | Per-page Open Graph / Twitter image and JSON-LD image. Falls back to `scanlines.ogImage` |
| `author` | string | Overrides `params.author` for this post (byline, `article:author`, JSON-LD) |
| `tags` | list | `#tag` chips + tag term pages |
| `categories` | list | `/category` chips + category term pages |
| `toc` | bool | Force the table of contents on or off. Posts default to on when they have headings; other pages default to off |
| `draft` | bool | Hidden unless you build with `-D` |

### Static Pages
Create pages in `content/` (e.g., `content/about.md`). Set `toc: true` in front
matter to give a long page a table of contents.

### Archive Page
A chronological index of every post, grouped by year. Create `content/archive.md`
and point it at the archive layout:

```yaml
---
title: "Archive"
layout: "archives"
---
```

### 404 Page
Custom VT220-style 404 page with VMS-flavored system messages
(`%SYSTEM-W-NOTFOUND, page not found`) and links back to the homepage and posts.

## Extensibility

### Custom CSS

Create `static/css/custom.css` to add your own styles:

```css
/* Override theme styles */
:root {
  --glow-intensity: 1.5;
}
```

### Custom Head Content

Create `layouts/partials/custom_head.html`:

```html
<link rel="preconnect" href="https://example.com">
<script async src="/js/analytics.js"></script>
```

### Custom Footer Content

Create `layouts/partials/custom_footer.html`:

```html
<script src="/js/custom.js"></script>
```

> This partial renders at the very end of `<body>` — after the site footer and
> the fixed status line, outside the page wrapper. It's the right place for
> scripts, but the wrong place for anything that should appear *inside* an
> article (see Comments below).

## Integrations

The theme ships no JavaScript and makes no external requests. Anything below is
opt-in and supplied by your site — the theme just gives you the hook.

> **Third-party scripts are a trust decision.** The snippets below load code
> from someone else's origin at runtime, so that provider can change what
> executes on your site. Subresource Integrity doesn't help here — these vendors
> ship unversioned, frequently-updated files, and a pinned `integrity` hash
> silently breaks on their next release. If that tradeoff matters to you,
> self-host the script (then you *can* pin a hash), and either way keep the
> origin listed in your [CSP](INSTALLATION.md#content-security-policy).

### Comments

Override `layouts/partials/article-footer.html` in your own site so comments
render inside the article where readers expect them. Copy the theme's version as
a starting point:

```bash
cp themes/scanlines/layouts/partials/article-footer.html layouts/partials/
```

The theme's markup is wrapped in a `{{ if or $cats $tags }}` guard, so add your
embed **after** that block's `{{ end }}` — putting it inside means posts with no
tags or categories get no comments:

```go-html-template
{{/* ...theme's taxonomy markup and its closing {{ end }} above... */}}

{{ if .Params.comments | default true }}
<div class="article-comments">
  <script src="https://giscus.app/client.js"
          data-repo="you/your-repo"
          data-mapping="pathname"
          crossorigin="anonymous" async></script>
</div>
{{ end }}
```

Don't use `custom_footer.html` for this — it renders after the status line, so
the widget ends up detached from the post.

### Analytics

Add the snippet to `layouts/partials/custom_head.html` (shown above). Anything
privacy-friendly and self-contained fits the theme's no-external-requests
posture — for example:

```html
<script defer data-domain="example.com" src="https://plausible.io/js/script.js"></script>
```

If you deploy with a strict CSP, remember to allow the origin (see
[INSTALLATION.md](INSTALLATION.md#content-security-policy)).

### Search

There's no built-in search: every client-side option (Fuse.js, Pagefind, Lunr)
ships JavaScript, which the theme deliberately doesn't. Two ways to add it:

- **Zero-JS** — a plain HTML form that hands off to an external engine:

  ```html
  <form action="https://duckduckgo.com/" method="get">
    <input type="hidden" name="sites" value="example.com">
    <input type="search" name="q" aria-label="Search this site">
  </form>
  ```

- **Full-text** — add [Pagefind](https://pagefind.app/) as a post-build step via
  `custom_footer.html`. That does introduce JavaScript to *your* site; the theme
  itself stays clean.

### Math

Hugo renders LaTeX server-side, so math needs no client-side library. Enable the
passthrough extension and add a render hook to your site:

```toml
[markup.goldmark.extensions.passthrough]
  enable = true
  [markup.goldmark.extensions.passthrough.delimiters]
    block  = [['\[', '\]'], ['$$', '$$']]
    inline = [['\(', '\)']]
```

```go-html-template
{{/* layouts/_markup/render-passthrough.html */}}
{{ $opts := dict "output" "mathml" "displayMode" (eq .Type "block") }}
{{ transform.ToMath .Inner $opts }}
```

`displayMode` is what makes `$$…$$` render as a centered display equation rather
than inline.

MathML output needs no stylesheet at all; see the
[Hugo docs](https://gohugo.io/functions/transform/tomath/) for the KaTeX-CSS
variant.

### Translations

All interface strings run through Hugo's i18n system. To translate the theme,
copy the bundled `i18n/en.toml` into your site as `i18n/<lang>.toml`, translate
the values, and set `defaultContentLanguage` in your config. Templates fall back
to English for any missing keys, so partial translations are safe.

## Color Schemes

The theme includes four historically accurate phosphor color schemes. Every
primary foreground/background pair below meets WCAG AAA for normal text (≥7:1);
the dimmed secondary color used for meta lines, captions and the footer meets AA
on every scheme.

| Scheme | Phosphor    | Foreground | Background | Contrast |
|--------|-------------|------------|------------|----------|
| Amber  | P3 (~602nm) | `#FFB000`  | `#0D0A00`  | ~10.8:1 (AAA) |
| Green  | P1 (~525nm) | `#33FF66`  | `#001A00`  | ~13.6:1 (AAA) |
| Blue   | Cool white  | `#6AAFFF`  | `#000A1A`  | ~8.7:1 (AAA)  |
| White  | Paper white | `#E6E6E6`  | `#1A1A1A`  | ~13.9:1 (AAA) |

These are palette ratios, measured with CRT effects off. The scanline and
vignette overlays composite black over the page, so delivered contrast is lower
than the table — most noticeably toward the edges of the viewport, where the
vignette is densest, and on narrow screens. It stays above AA at the reading
position on every scheme, but if you need the full ratios, turn the effects off
with `accessibility.disableEffects` (see [Accessibility](#accessibility)). The
theme also drops both overlays automatically for readers whose OS asks for more
contrast (`forced-colors` / `prefers-contrast: more`).

If you set custom colors via `[params.scanlines.colors]`, verify contrast with a tool like [WebAIM Contrast Checker](https://webaim.org/resources/contrastchecker/). Values are validated as a 3-, 4-, 6- or 8-digit CSS hex color and silently dropped if malformed — invalid hex falls back to the scheme default.

| Green | Blue | White |
|-------|------|-------|
| ![Green](https://raw.githubusercontent.com/wthouse/scanlines/main/images/homepage_profile_green.png) | ![Blue](https://raw.githubusercontent.com/wthouse/scanlines/main/images/homepage_profile_blue.png) | ![White](https://raw.githubusercontent.com/wthouse/scanlines/main/images/homepage_profile_white.png) |

## More Screenshots

| Single Post with TOC | Mobile View |
|---------------------|-------------|
| ![Single post](https://raw.githubusercontent.com/wthouse/scanlines/main/images/single_post.png) | ![Mobile](https://raw.githubusercontent.com/wthouse/scanlines/main/images/mobile_collapsed.png) |

## Fonts

The theme uses two self-hosted fonts:

- **Glass TTY VT220** (default) - Authentic VT220 terminal font (Unlicense)
- **Fira Code** (optional) - Modern monospace alternative (OFL)

Font licensing is documented in [LICENSE-FONTS.md](LICENSE-FONTS.md), which
reproduces the OFL in full for Fira Code and links The Unlicense for Glass TTY
VT220. The theme itself is MIT ([LICENSE](LICENSE)).

## Browser Support

- Chrome/Edge 88+
- Firefox 78+
- Safari 14+
- Mobile browsers (iOS Safari, Chrome Android)

## Credits

- Inspired by the [DEC VT220](https://terminals-wiki.org/wiki/index.php/DEC_VT220) terminal
- [Glass TTY VT220 Font](https://github.com/svofski/glasstty) by Viacheslav Slavinsky
- [Fira Code](https://github.com/tonsky/FiraCode) by Nikita Prokopov

### Themes That Inspired This One

- [PaperMod](https://github.com/adityatelange/hugo-PaperMod) by Aditya Telange - Clean layout patterns, profile mode, and archive page design
- [Terminal](https://github.com/panr/hugo-theme-terminal) by Radek Kozieł - Terminal aesthetic and monospace-first typography
- [BOOTSTRA.386](https://github.com/kristopolous/BOOTSTRA.386) by Chris McKenzie - Proof that retro computing aesthetics belong on the modern web
- [Chicago7](https://github.com/akopdev/hugo-theme-chicago7) by Akop Karapetyan - Retro UI inspiration and nostalgic design sensibility

## License

MIT License - see [LICENSE](LICENSE) for details.

---

Built with [Hugo](https://gohugo.io) | Vibed with [Claude Code](https://claude.ai/code) (Claude Opus 4.6)
反馈内容错误

看看同类模板

对比同技术栈与用途的模板,找到更适合的视觉与内容结构。