Hugo作品集博客

devsheet — Hugo 作品集模板

作者 fadli0029

devsheet 是一个极简等宽字体风格的 Hugo 主题,面向开发者作品集与技术博客,支持 LaTeX 公式、代码高亮和明暗主题切换。

看看你的网站会是什么样

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

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

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

全部页面与视图 3

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

采集于 2026-09-30查看来源

值得关注的模板亮点

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

01

零第三方请求:KaTeX、Fuse.js 和字体等资源均内置于仓库,CI 检查外部子资源

02

明暗主题切换,默认跟随系统偏好,在首次绘制前应用以避免闪烁

03

基于 Fuse.js 的搜索,覆盖标题、标签和正文前 200 字符,支持 Ctrl/Cmd+K 与方向键导航

04

支持 KaTeX 数学公式与 Chroma 语法高亮,代码块带复制按钮

05

无 JavaScript 的多状态图片标签页,以及可选的目录和标题编号

06

键盘可访问性:可见焦点环、跳转链接、尊重 prefers-reduced-motion、两种主题均满足 AA 对比度

模板详细介绍

devsheet 是一个基于 Hugo 的极简等宽字体主题,主要面向开发者个人作品集和技术博客。主题强调零第三方请求:KaTeX、Fuse.js 以及 Crimson Pro 和 Maple Mono 字体等资源都内置于仓库中,CI 会检查并阻止外部子资源重新出现。

功能上,它提供明暗主题切换(默认跟随系统偏好并在首次绘制前应用)、基于 Fuse.js 的标题/标签/正文前 200 字符搜索(快捷键 Ctrl/Cmd+K)、移动端折叠菜单、代码块复制按钮、KaTeX 数学公式、Chroma 语法高亮、可选目录与标题编号、无 JavaScript 的多状态图片标签页、RSS 自动发现、Open Graph 与 Twitter Card 元信息,以及打印样式表。主题要求 Hugo 0.122.0 或更新版本,不需要 extended 构建。

使用限制方面,数学公式需要站点自行配置 Goldmark 的 passthrough 扩展;搜索需要 home 输出中包含 JSON;RSS 输出键会替换 Hugo 默认值,需保留 RSS;主题不提供 Sass 或图片处理。

Hugo作品集博客

适合你的项目吗?

适用场景

  • 开发者搭建个人作品集网站,展示项目与文章
  • 技术博客撰写包含 LaTeX 公式和代码示例的文章
  • 需要严格控制第三方请求、避免 CDN 依赖的静态站点
  • 部署在 GitHub Pages 项目子目录下的 Hugo 站点

适合人群

  • 使用 Hugo 的开发者个人站点
  • 偏好等宽字体与极简排版的技术写作者
  • 需要数学公式渲染和语法高亮的技术博客
  • 关注隐私、希望避免外部 CDN 请求的站点所有者

上手与定制指南

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

  1. 1

    要求 Hugo 0.122.0 或更新版本,不需要 extended 构建

  2. 2

    可通过 git submodule 或 Hugo Module 安装,也可复制 exampleSite 作为起点

  3. 3

    数学公式需在站点配置中启用 Goldmark passthrough 扩展并列出分隔符

  4. 4

    搜索功能需要在 [outputs] home 中包含 "JSON",否则主题会完全省略搜索按钮

  5. 5

    自定义 CSS 可放在站点根目录的 assets/css/custom.css,会最后加载并覆盖主题样式

查看仓库使用说明

授权与来源资料

使用条件与限制

免费使用 · 保留许可声明

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

使用时需要遵守

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

额外费用与待核对事项

  • 使用该主题需要 Hugo 0.122.0 或更新版本;不需要 extended 构建。
  • 数学公式功能需在站点配置中启用 Goldmark passthrough 扩展并列出分隔符,主题无法代为提供该配置。
  • 搜索功能要求 home 输出中包含 JSON,否则主题会完全省略搜索按钮、对话框与 Fuse.js 脚本。
  • 在 [outputs] 中声明某类页面会替换 Hugo 默认值,需自行保留 RSS 等输出,否则会静默删除站点订阅源。
  • 行内美元符号数学默认关闭,需显式开启 mathInlineDollar 并添加对应 passthrough 分隔符,且会与普通文本中的美元符号冲突。
  • KaTeX、Fuse.js 及 Crimson Pro、Maple Mono 字体等内置资源保留各自许可证,使用前应查阅 THIRD-PARTY.md 确认。
  • 演示图片、字体、图标及其他第三方素材需按各自许可核对,不能仅凭代码的 MIT 许可判断。
  • 域名、托管、数据库、支付或 AI 等外部服务可能另外收费。
查看原文依据

Permission is hereby granted, free of charge

许可证原文

Requires Hugo 0.122.0 or newer.

README 原文

Math needs the passthrough extension

README 原文

It needs `"JSON"` in `[outputs] home`

README 原文

Each key in `[outputs]` **replaces** Hugo's default for that page kind rather than extending it

README 原文

`$…$` for **inline** math is off by default and gated behind `mathInlineDollar = true`.

README 原文

Vendored assets keep their own licenses; see [THIRD-PARTY.md](THIRD-PARTY.md).

README 原文
https://github.com/fadli0029/devsheet/blob/main/LICENSEhttps://github.com/fadli0029/devsheet/blob/main/README.md

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

项目核对记录与介绍依据

模板资料

来源平台
GitHub
资料与维护参考分
资料较完整 · 88 / 100
技术栈
Hugo
网站类型
作品集 · 博客
这个分数如何计算

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

这个项目需要核对什么

记录的仓库更新时间
2026-09-22
截图检查日期
2026-10-01

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

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

查看具体选型方法 →

介绍的制作与核对状态

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

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

查看当时使用的来源资料

SHA-256: 78fdc922b129988116406e29daa3d39a96edbc8f94ba03c1f67e5b366ad3611c

2026-10-01T14:13:57.048Z

来源文件 / 仓库
# devsheet

Minimal monospace Hugo theme for developer portfolios and technical blogs.

![devsheet](https://raw.githubusercontent.com/fadli0029/devsheet/main/images/screenshot.png)

**[Live demo](https://fadli0029.github.io/devsheet/)**

Requires Hugo 0.122.0 or newer. The extended build is **not** required: the theme uses no Sass, no image processing, and no other extended-only feature. CI builds against 0.122.0, 0.128.0 and
0.154.4, extended and non-extended, as blocking checks, plus a non-blocking canary on Hugo `latest`.

## Why

Most blog themes pull fonts from Google, scripts from a CDN, and analytics from
somewhere else. devsheet makes **zero third-party requests**. Everything it needs is
vendored, so your readers' browsers talk to your host and nothing else, no CDN outage
can break your site, and there is no third party to leak visitor IPs to. A CI job
fails the build if any external subresource reappears.

## Features

- Light/dark toggle, remembered across visits, defaulting to the system preference —
  applied before first paint, so there is no flash of the wrong theme
- Search over titles, tags and the first 200 characters of each post (`Ctrl`/`Cmd`+`K`), with arrow-key
  navigation, built on a native `<dialog>` for a real focus trap
- Collapsing mobile menu
- Copy button on every code block
- KaTeX math and Chroma syntax highlighting
- Per-page table of contents and numbered headings, opt-in from front matter
- Figures with several states behind tabs, without JavaScript
- RSS with autodiscovery, canonical URLs, Open Graph, and Twitter Card meta
- Keyboard accessible: visible focus rings, skip link, `prefers-reduced-motion`
  honored, AA contrast in both themes
- Print stylesheet
- Correct under subdirectory deployments such as GitHub Pages project sites

## Install

### As a submodule

```bash
git submodule add https://github.com/fadli0029/devsheet themes/devsheet
```

Then in your `hugo.toml`:

```toml
theme = "devsheet"
```

### As a Hugo Module

```bash
hugo mod init github.com/you/your-site
hugo mod get github.com/fadli0029/devsheet
```

```toml
[module]
  [[module.imports]]
    path = "github.com/fadli0029/devsheet"
```

Go resolves the highest semver tag, so this needs a release tag whose module root
holds `layouts/` and `theme.toml`. Tags at or below `v1.0.2` predate the move to
the standard theme layout and will resolve to an empty site.

### Start from the demo site

If you would rather begin from a working site than a blank one, copy `exampleSite/`
and use it as your project:

```bash
git clone https://github.com/fadli0029/devsheet
cp -r devsheet/exampleSite my-site
cd my-site
git init
git submodule add https://github.com/fadli0029/devsheet themes/devsheet
hugo server
```

### Preview the demo in place

```bash
git clone https://github.com/fadli0029/devsheet
cd devsheet
hugo server --source exampleSite --themesDir ../..
```

The clone directory must be named `devsheet` for `--themesDir` to resolve it, since
that is the name in `theme = "devsheet"`.

## Configuration

```toml
baseURL = "https://example.com/"   # change this before deploying
enableRobotsTXT = true             # generates robots.txt with a sitemap pointer

[params]
  mainSections = ["blog"]          # sections listed on the home page and searched
  author = "your name"
  description = "Site tagline"
  github = "https://github.com/you"
  linkedin = "https://linkedin.com/in/you"
  email = "[email protected]"
  syntaxHighlighting = true
  math = true                      # false drops ~294KB of KaTeX JS+CSS per page
  mathInlineDollar = false         # see Math below before turning this on
  showProjects = true              # show the Projects block on the home page

[outputs]
  home = ["HTML", "RSS", "JSON"]   # JSON builds the search index
  section = ["HTML", "RSS"]
  taxonomy = ["HTML"]
  term = ["HTML"]

[markup]
  [markup.goldmark.renderer]
    unsafe = true                  # allows raw HTML in your markdown
  [markup.highlight]
    noClasses = false              # REQUIRED: without it Chroma inlines its own
    codeFences = true              # colours and ignores the theme's stylesheet
    style = "github"
    tabWidth = 4
```

`noClasses = false` and `syntaxHighlighting = true` are two halves of one switch.
Set only the first and code blocks are unstyled; set only the second and Chroma
inlines monokai colours that ignore light mode entirely.

### mainSections

`mainSections` decides which sections appear under "Recent Posts", which sections
search covers, and which section lists render as dated posts rather than project
cards. Add every writing section you have:

```toml
[params]
  mainSections = ["blog", "notes"]
```

When more than one section is listed, a `[section]` label appears next to each home
page entry so the sections stay distinguishable. Rename those labels without
forking the template:

```toml
[params.sectionLabels]
  bits = "bit"        # renders [bit] instead of [bits]
```

With only one main section no labels are rendered, so `sectionLabels` has no
effect there.

### Math

Write display math as `$$…$$`, inline math as `\(…\)`, and the `\begin{align}` /
`{equation}` / `{gather}` / `{CD}` environments as themselves.

Math needs the passthrough extension, which stops Goldmark mangling LaTeX before
KaTeX sees it (`\\` collapses to `\`, `\,` disappears, `a*b*c` becomes
`a<em>b</em>c`, and `>>` becomes `»`). It is why the minimum Hugo is 0.122.0.
Every delimiter you intend to use must be listed here, including the environments:

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

Hugo's own math documentation lists `\[…\]` as the block delimiter. This theme
omits it on purpose. A passthrough delimiter wins over CommonMark's backslash
escapes, so listing `\[` stops `\[` meaning a literal `[`. Since `[` is
Markdown-significant, that escape gets used in practice, and
`[\[expr.context\]](url)` silently turns its own link text into display math.
`(` carries no meaning in ordinary Markdown text, so `\(` costs nothing to claim
and inline math keeps its LaTeX spelling. Add `['\[', '\]']` back to `block` if
you want the LaTeX display spelling and never escape a bracket; KaTeX is already
configured to render it.

Hugo will not let a theme supply this block for you: the `markup` key defaults to
a `none` merge strategy, so it has to live in each site's own configuration.

`$…$` for **inline** math is off by default and gated behind
`mathInlineDollar = true`. Turning it on also requires adding `['$', '$']` to the
passthrough `inline` list above, or Goldmark mangles it first. On a developer blog
it collides with ordinary prose:
"costs $5 today and $10 tomorrow" and "set $HOME and then $PATH" both become
mangled math. It also makes `\$` render a bare `$` that KaTeX then eats, so a
literal dollar needs `&dollar;`. Prefer `\(…\)` for inline.

### Search

Search is a Fuse.js index built from the home page's JSON output. It needs `"JSON"` in
`[outputs] home`; without it the theme omits the search button, the dialog, and the
Fuse.js script entirely rather than shipping a button that does nothing.

Open with the `search` button or `Ctrl`/`Cmd`+`K`. Arrow keys move through results,
Enter opens, Escape closes.

### RSS

Each key in `[outputs]` **replaces** Hugo's default for that page kind rather than
extending it, so declaring `home = ["HTML", "JSON"]` silently deletes your site feed.
Kinds you do not declare keep their defaults. Keep `"RSS"` in both `home` and `section`.

## Creating Content

### New blog post

```bash
hugo new content blog/YYYY-MM-DD-slug-title.md
```

`hugo new site` scaffolds its own `archetypes/default.md`, and a site archetype
always shadows the theme's. Delete yours to get devsheet's, which strips the date
prefix from the title and takes `date` from the filename:

```bash
rm archetypes/default.md
```

The generated file has `draft: true`; clear it (or build with `-D`) to publish.

```yaml
---
title: "Your Post Title"
date: 2024-12-08
description: "Short description for lists and social previews"
tags: ["systems", "c++"]                # optional, indexed by search
pdf: /pdfs/your-post.pdf                # optional, adds a PDF download link
github: "https://github.com/you/repo"   # optional, adds a GitHub link
---
```

### Frontmatter reference

| Field | Required | Description |
|-------|----------|-------------|
| `title` | Yes | Page title |
| `date` | No | YYYY-MM-DD, determines sort order. Omit it and no date is shown. |
| `description` | No | Project cards, meta description, social previews. Not shown in dated post lists. |
| `tags` | No | Indexed by search, shown as chips in results |
| `pdf` | No | Path to a PDF; shows a download link in the article header |
| `github` | No | Shows a GitHub link in the article header |
| `toc` | No | `true` adds a table of contents of the page's h2 and h3 headings: under the title on narrow screens, a sticky column right of the article from 80em wide |
| `numberedHeadings` | No | `true` numbers h2 as 1, 2, ... and h3 as 1.1, 1.2, ...; the table of contents, if on, shows the same numbers |

### Images

Put them in `static/img/` and reference them as `![alt text](/img/filename.png)`.
Root-relative paths are rewritten against `baseURL`, so they keep working when the
site is served from a subdirectory.

In the dark theme every article image sits on a light backing (`--img-plate`), so a
diagram drawn in dark ink on a transparent background, which is what TikZ and
Mermaid export, stays readable.

### Figures with several states

`figure-states` shows one image at a time with a row of tabs to switch between
them. Each `figure-state` names a tab, an image from the page bundle, its alt text,
and an optional caption written in Markdown. It needs no JavaScript: the tabs are
radio buttons.

```markdown
{{< figure-states label="Memory after each call" >}}
{{< figure-state label="by_value(b)" src="memory-1.svg" alt="Memory after by_value(b)" >}}
The copy constructor runs.
{{< /figure-state >}}
{{< figure-state label="by_lref(b)" src="memory-2.svg" alt="Memory after by_lref(b)" >}}
p becomes another name for b.
{{< /figure-state >}}
{{< /figure-states >}}
```

The build fails if `src` does not name a resource in the page bundle.

## Customizing

Add your own CSS without touching the theme: create `assets/css/custom.css` in your
site root. It loads last, so it overrides everything.

```
your-site/
└── assets/
    └── css/
        └── custom.css
```

Colors are CSS custom properties at the top of `assets/css/main.css`, grouped under
`[data-theme="light"]` and `[data-theme="dark"]`. Redefine them in `custom.css` to
restyle the theme without forking it. The full set is `--bg`, `--bg-secondary`,
`--text`, `--text-muted`, `--link`, `--code-bg`, `--code-border`, `--border`,
`--control-border` and `--img-plate`.

## Deploying

```bash
hugo --minify
```

Output goes to `public/`. Deploy that directory.

`.github/workflows/deploy.yml` publishes `exampleSite` to GitHub Pages and takes the
baseURL from the Pages API, so it is correct whether you are served from
`you.github.io` or `you.github.io/repo/` with no edit after forking. Bump
`HUGO_VERSION` in that file to upgrade Hugo.

## Third-party assets

KaTeX, Fuse.js, and the Crimson Pro and Maple Mono webfonts are vendored, with versions and licenses
recorded in [THIRD-PARTY.md](THIRD-PARTY.md). `scripts/check-no-external.py` runs in
CI and fails the build if any external subresource reappears.

## Repository layout

```
devsheet/
├── theme.toml            # theme metadata
├── LICENSE
├── README.md
├── THIRD-PARTY.md        # vendored asset versions and licenses
├── archetypes/           # `hugo new` scaffolding, reaches consumers
├── layouts/              # templates
├── assets/
│   ├── css/              # main.css, syntax.css
│   └── vendor/           # KaTeX, Fuse.js, and their licenses
├── static/
│   ├── fonts/            # Crimson Pro + Maple Mono (SIL OFL)
│   └── katex/            # KaTeX stylesheet and fonts
├── images/               # theme gallery screenshots
├── scripts/              # CI checks
├── .github/workflows/    # CI and Pages deploy
└── exampleSite/          # the demo site, also the live demo
```

## Contributing

CI must be green: the theme builds across the supported Hugo range with
`--panicOnWarning`, installs cleanly as a consumer would, and ships no external
subresources. Run the checks locally with:

```bash
hugo --source exampleSite --themesDir ../.. --minify --panicOnWarning --destination /tmp/out
python3 scripts/check-no-external.py /tmp/out https://example.com/
```

## License

MIT. See [LICENSE](LICENSE). Vendored assets keep their own licenses; see
[THIRD-PARTY.md](THIRD-PARTY.md).
反馈内容错误

看看同类模板

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