HugoStarter

scanlines — Hugo Starter Template

By wthouse

scanlines is a retro, minimalist Hugo theme inspired by DEC VT220/VT100 CRT terminals, implemented in pure CSS with no JavaScript, featuring terminal color schemes and CRT visual effects.

Explore the design

Compare the page layouts and mobile experience. Open any screenshot for a closer look.

3 previews
Desktop homepage1 / 3
Desktop captureTop of page

Actual screenshot captured by the server browser.

All pages & views 3

Screenshots show visual appearance; interactive behavior may differ.

Recorded 2026-10-03View source

What stands out

A quick read of the recorded project description.

01

CRT visual effects implemented in pure CSS, including scanlines, phosphor glow, screen flicker, vignette, and screen curvature, each toggleable and adjustable in intensity

02

Four historical phosphor color schemes—amber (P3), green (P1), blue, and white—plus support for custom hex color overrides

03

No JavaScript; fonts and assets are self-hosted with no external CDN requests

04

Homepage can be set to blog or profile mode; profile mode provides a landing page with name, bio, social icons, and custom buttons

05

Header supports loading a custom ASCII art file from the static directory as the site title; the bottom status bar shows the site title, section, reading time, and similar information

06

Supports Chroma syntax highlighting (monochrome or multicolor), collapsible table of contents, tags and categories, reading time, and SEO output such as Open Graph, Twitter cards, JSON-LD, and RSS

Template Details

scanlines is a Hugo theme whose visual style references classic CRT terminals such as the DEC VT220 and VT100. It offers four phosphor color schemes—amber (P3), green (P1), blue, and white—and includes CRT effects such as scanlines, phosphor glow, screen flicker, vignette, and screen curvature. All effects can be toggled individually and their intensity adjusted in the configuration. The theme does not rely on JavaScript; interactions and visual effects are handled entirely in CSS, and fonts and assets are self-hosted with no external CDN requests.

The homepage supports two modes: blog mode displays the site tagline and recent posts, while profile mode serves as a personal landing page showing name, bio, social icons, and custom buttons, and hides the regular navigation. Post pages support a collapsible table of contents, tags and categories, reading time, summaries, and Chroma-based syntax highlighting (optionally monochrome or multicolor). The theme also provides SEO-related output, including semantic HTML, meta tags, Open Graph, Twitter cards, JSON-LD structured data, and RSS.

Configuration options are centralized under the [params.scanlines] namespace, covering color schemes, homepage mode, CRT effects, accessibility, header, table of contents, status bar, layout, typography, syntax highlighting, and social links. The header can load a custom ASCII art file as the site title, and the bottom status bar displays the site title, current section, and contextual information, hidden on mobile. For accessibility, the theme responds to prefers-reduced-motion and provides toggles for high contrast, reduced animation, and fully disabling CRT effects.

Several limitations apply before use: Hugo Extended 0.146.0 or later is required; installing via Hugo Modules also requires Go 1.18+, while submodule, clone, and ZIP methods only need Git. The default font glass (Glass TTY VT220) covers only ASCII and the DEC multinational character set (roughly equivalent to Latin-1), so typographer = false must be set in hugo.toml; otherwise Hugo rewrites quotes and dashes into curly quotes and em dashes that the font lacks. Switching to fira (Fira Code) avoids this issue. Syntax highlighting requires noClasses = false; otherwise Hugo inlines monokai colors and the theme's syntax styles and colored toggle stop working. Images in posts receive partial grayscale processing when CRT effects are enabled, and the scanline overlay applies only to images wrapped with the Hugo figure shortcode; plain Markdown images get only grayscale and lazy loading.

HugoStarter

Is it right for your project?

Use Cases

  • Building a personal blog with a retro terminal look, showing recent posts and tags
  • Creating a personal landing page that presents name, bio, social links, and custom buttons via profile mode
  • Publishing technical articles organized with syntax highlighting, a collapsible table of contents, and tag/category taxonomies
  • Static sites that need no JavaScript, self-hosted assets, and no external CDN dependency

Suitable For

  • Bloggers using Hugo who want a CRT terminal visual style
  • Personal sites that need either a blog or profile homepage form
  • Static site projects that prefer no JavaScript and self-hosted fonts and assets
  • Users with clear requirements for retro color schemes and terminal details such as the status bar and ASCII header

Getting started & customization

Use these recorded setup notes alongside the repository instructions for your chosen version.

  1. 1

    Requires Hugo Extended 0.146.0 or later; installing via Hugo Modules also requires Go 1.18+, while submodule, clone, and ZIP methods only need Git

  2. 2

    When using the default fontFamily = "glass", set [markup.goldmark.extensions] typographer = false in hugo.toml to avoid curly quotes and em dashes falling back due to missing glyphs

  3. 3

    Syntax highlighting requires [markup.highlight] noClasses = false in hugo.toml; otherwise the theme's syntax styles and colored toggle do not take effect

  4. 4

    All theme options live under the [params.scanlines] namespace and can be configured as needed for color schemes, homepage mode, CRT effects, accessibility, header, table of contents, status bar, layout, typography, and social links

  5. 5

    When CRT effects are enabled, post images receive partial grayscale processing, and the scanline overlay applies only to images wrapped with the figure shortcode

Read repository instructions

License & source material

Usage conditions & limitations

Free to use · keep license notice

This entry covers the free version in the public repository under the MIT license; the free scope is the code of that version and does not imply that external services or third-party assets are free.

Must comply with when using

  • The code of this version may be used, modified, used commercially, and distributed free of charge.
  • When distributing copies or substantial portions of the code, retain the original author's copyright notice and the full MIT license notice.
  • The code is provided as is; warranties and limitations of liability are governed by the original license and applicable law.

Additional costs & items to verify

  • Hugo Extended 0.146.0 or later is required; standard Hugo cannot process SCSS and the 0.146+ template system.
  • Go 1.18+ is required only when installing via Hugo Modules; submodule, clone, and ZIP methods only need Git.
  • When using the default glass font, typographer must be disabled in hugo.toml; otherwise curly quotes and em dashes fall back to other fonts due to missing glyphs.
  • Syntax highlighting requires noClasses = false in hugo.toml; otherwise Hugo inlines monokai colors and the theme's syntax styles and colored toggle stop working.
  • The scanline overlay applies only to images wrapped with the Hugo figure shortcode; plain Markdown images get only grayscale and lazy loading, with no overlay effect.
  • The theme has no built-in search; adding search requires an external engine or Pagefind, which adds JavaScript to the site.
  • Integrations such as comments and analytics require third-party scripts loaded at runtime from others' origins, with third-party trust and CSP configuration requirements.
  • Demo images, fonts, icons, and other third-party assets must be checked against their respective licenses; the code's MIT license alone is not sufficient to judge them.
  • External services such as domains, hosting, databases, payments, or AI may incur separate charges.
View Original Text Basis

Permission is hereby granted, free of charge

Original License Text

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

Original README

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

Original README

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

Original README

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

Original README

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

Original README

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

Original README

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

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

Compiled by DeepSeek based on repository license and README ·2026-10-03. Results only cover the materials read; dependencies, images, fonts, and subsequent term changes are subject to their respective original texts.

Project checks & description sources

Template Information

Source platforms
Hugo Themes
Documentation and maintenance reference score
More documented · 83 / 100
Technologies
Hugo
Website type
Starter
How this score is calculated

Our heuristic uses license records (up to 30), a demo link (12), a preview (10), stars (15), recorded maintenance (15), description completeness (8), feature records (5) and classification data (5). It is not a code, security or performance test, or a Google score. A link does not establish tested functionality.

What to verify for this project

Repository update recorded
2026-08-28
Screenshot last checked
2026-10-03

A demo link is listed. Check it with your own content and viewport sizes; its presence does not confirm that forms, authentication or payments work.

The catalog identifies Hugo as the primary stack. Check the actual dependency manifest and lockfile for versions and hosting requirements. These notes use recorded metadata, not a code audit or a deployment test.

Use a selection guide →

How this description was prepared

AI-assisted description based on catalog records and repository material. Repository authors are not automatically the reviewers of this description.

Automatically checked against source and license rules; no manual editorial review.

Inspect the recorded source material

SHA-256: daae8d9860a01d176e44f3279decb959ce2b57e98280ac1a0bdf8eb41ee97720

2026-10-03T03:17:11.793Z

Source file / repository
<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)
Report a correction

Explore similar templates

Compare previews and descriptions within the same stack and category.

hugo-xmin

hugo-xmin

hugo-xmin is an extremely minimal Hugo theme written by Yihui Xie for template beginners. HTML and CSS total about 140 lines, with no external dependencies, and it uses the MIT license.

Hugo · Starter

hugo-theme-gallery

hugo-theme-gallery

A Hugo Extended photo gallery theme that organizes images with Page Bundles, automatically generating album lists and gallery pages with a Justified layout and PhotoSwipe lightbox.

Hugo · Starter

reveal-hugo

reveal-hugo

reveal-hugo is a Hugo theme that converts Markdown content into Reveal.js-based HTML presentations. It supports slide separation with `---`, shortcodes for fragments, slides, sections, notes, Markdown, and MathJax, and organizes content as root or section presentations with order controlled by weight.

Hugo · Starter

anatole

anatole

Anatole is a minimalistic two-column Hugo theme ported from farbox-theme-Anatole, featuring dark mode, multilingual and RTL support, and optional portfolio, comments, analytics, KaTeX, and Mermaid integrations. It suits personal blogs, portfolios, or documentation sites built with Hugo.

Hugo · Starter

hugo-theme-diary

hugo-theme-diary

A Hugo diary-style theme ported from the Hexo theme Journal, with a grid homepage for essays and daily notes. It supports six languages, dark mode, table-of-contents scroll positioning, reading time, code highlighting, and configurable sidebar, fonts, and colors.

Hugo · Starter

risotto

risotto

risotto is a minimalist, responsive Hugo theme inspired by terminal ricing aesthetics. It uses semantic HTML and pure CSS with no JavaScript, and its layout relies on CSS Grid for native responsiveness without manual breakpoints.

Hugo · Starter