hugo-theme-tui

TUI
Log | Files | Refs | README | LICENSE

README.md (7604B)


      1 # hugo-theme-tui
      2 
      3 A terminal-UI Hugo theme. Box-drawn frame around the page, lazygit-style
      4 row hovers on lists, restrained Nord palette, monospace typography, and a
      5 dot-matrix glyph marker on the frame border.
      6 
      7 Built for personal sites — bio + projects + a blog.
      8 
      9 ```
     10 ╭── whoami.md ──────────────────────────────────── • • • • ▏──╮
     11 │                                                              │
     12 │  user@example.com ~/                  [whoami]  projects  …  │
     13 │  ────────────────────────────────────────────────────────    │
     14 │  Your Name                                                   │
     15 │  one-line tagline                                            │
     16 │                                                              │
     17 │  ── about ──────────────────────────────────────────────     │
     18 │   · bullet one                                               │
     19 │   · bullet two                                               │
     20 │   · bullet three                                             │
     21 │                                                              │
     22 ╰──────────────────────────────────────────────────────────────╯
     23 ```
     24 
     25 To try it locally: clone the repo, then `hugo server --source exampleSite
     26 --themesDir ../..`. The rest of this README documents only what is
     27 specific to this theme — see `exampleSite/hugo.toml` for a full working
     28 example.
     29 
     30 ## Theme-specific parameters
     31 
     32 | Param                     | Type    | Default          | Purpose                                                       |
     33 | ------------------------- | ------- | ---------------- | ------------------------------------------------------------- |
     34 | `brandUser`               | string  | `"user"`         | Left side of the `user@host` brand line in the header.        |
     35 | `brandHost`               | string  | `"example.com"`  | Right side of the brand line.                                 |
     36 | `brandLabel`              | string  | `"whoami"`       | Label of the first nav link (always points to `/`).           |
     37 | `about.title`             | string  | site title       | H1 on the homepage.                                           |
     38 | `about.description`       | string  | —                | Subtitle under the homepage H1.                               |
     39 | `marker.home`             | []string| `["Д","О","М"]` | Dot-matrix word on the homepage.                              |
     40 | `marker.projects`         | []string| `["К","О","Д"]` | Dot-matrix word on the projects page.                         |
     41 | `marker.posts_list`       | []string| `["П","О","С","Т"]` | Dot-matrix word on the posts list.                        |
     42 | `marker.posts_single`     | []string| `["С","Т","А","Т"]` | Dot-matrix word on a single post.                         |
     43 | `marker.fallback`         | []string| `["С","Т","А","Т"]` | Dot-matrix word on any other page.                        |
     44 | `socialLinks`             | array   | —                | Tiles in the homepage socials grid (see below).               |
     45 
     46 ## The dot-matrix marker
     47 
     48 The bracketed dots on the frame's top border are the theme's signature.
     49 Each "word" is a list of single characters; each character is rendered
     50 from a 5×5 bitmap in `layouts/partials/cyrillic-svg.html`.
     51 
     52 The bitmap font ships with **eight Cyrillic glyphs**: `А Д К М О П С Т`.
     53 Anything outside that set renders nothing — so if you want to use
     54 different letters, add their bitmaps to the `$font` dict in that partial.
     55 Each entry is a list of five 5-char strings of `1`/`0`. E.g. to add
     56 Cyrillic `Р`:
     57 
     58 ```go-html-template
     59 "Р" (slice "11110" "10001" "11110" "10000" "10000")
     60 ```
     61 
     62 ## Nav
     63 
     64 The first nav link is always the home link; its label comes from
     65 `brandLabel`. The remaining links are read from `[[menu.main]]` — add or
     66 remove entries to change the nav. Active state is auto-detected from the
     67 current page URL (matches the menu entry's URL or any descendant of it).
     68 
     69 ```toml
     70 [[menu.main]]
     71 identifier = "projects"
     72 name = "projects"
     73 url = "/projects/"
     74 weight = 10
     75 ```
     76 
     77 ## Socials grid
     78 
     79 The homepage renders a tile grid driven by `params.socialLinks`. Each
     80 entry needs four fields:
     81 
     82 ```toml
     83 [[params.socialLinks]]
     84 key   = "email"                   # small-caps label inside the tile
     85 value = "hello@example.com"       # value shown below the key
     86 url   = "mailto:hello@example.com"
     87 icon  = "email"                   # see icon list below
     88 ```
     89 
     90 Built-in icons: `email`, `linkedin`, `github`, `git`, `rss`, `pgp`,
     91 `coffee`. To add more, edit `layouts/partials/icon.html` and add another
     92 `{{ else if eq $name "your-name" }}<svg …></svg>` branch — the SVGs
     93 inherit the current text color via `stroke="currentColor"`.
     94 
     95 ## Projects page
     96 
     97 The projects page reads its entries from **page params**, not from child
     98 pages. Create `content/projects.md` with `type = "projects"` and a
     99 `[[projects]]` array:
    100 
    101 ```toml
    102 +++
    103 title = "projects"
    104 type = "projects"
    105 layout = "projects"
    106 
    107 [[projects]]
    108 title = "my-project"
    109 url   = "https://github.com/…"   # optional — omit for a plain row
    110 lang  = "rust"                    # shown in the left column, bracketed
    111 desc  = "one-line description"
    112 +++
    113 ```
    114 
    115 The `lang` column is rendered as `[rust]` and is purely visual — it can
    116 be any short string.
    117 
    118 ## Posts
    119 
    120 Standard Hugo `content/posts/*.md`. Theme-specific behaviours:
    121 
    122 - Posts are grouped by year on the posts list (`GroupByDate "2006"`).
    123 - The frame title on a single post is `── <basename>.md ──`.
    124 - A table of contents auto-renders **above** the article when the post
    125   has any `##`/`###` headings. Hugo's TOC settings apply (`markup.tableOfContents`).
    126 - `tags` in front matter render as `[#tag]` chips in the post-list row.
    127 
    128 ## Customising
    129 
    130 Theme structure:
    131 
    132 ```
    133 layouts/
    134   _default/   baseof, list, single, projects
    135   partials/   head, header, footer, socials, icon, cyrillic-svg
    136   posts/      list, single
    137   index.html  homepage
    138 static/css/   shared, tui, pattern, custom
    139 ```
    140 
    141 Override any partial or stylesheet by creating a same-named file at the
    142 same path inside **your site's** `layouts/` or `static/` directory.
    143 Example: to add an analytics script in `<head>` without forking the
    144 theme, create `layouts/partials/head.html` in your site and Hugo will use
    145 that one instead.
    146 
    147 The CSS is four small files (~700 LOC total):
    148 
    149 | File          | Holds                                                      |
    150 | ------------- | ---------------------------------------------------------- |
    151 | `shared.css`  | Nord palette CSS variables, font import, body reset        |
    152 | `tui.css`     | All component styles (frame, header, sections, rows, …)    |
    153 | `pattern.css` | Border-anchored marker positioning                          |
    154 | `custom.css`  | Adjustments for Hugo-rendered markdown (TOC, images, …)    |
    155 
    156 ## Known limitations
    157 
    158 - The marker bitmap font ships with 8 Cyrillic glyphs only — extend it
    159   in `cyrillic-svg.html` to use other characters.
    160 - Only a dark theme (Nord). No light-mode toggle.
    161 - The projects page reads from a page-param array, not from child pages.
    162   If you want one-page-per-project, you'll need to add a layout.
    163 
    164 ## License
    165 
    166 [MIT](./LICENSE) — Fedor Vinogradov, 2026.