feat: initial style

This commit is contained in:
2026-06-21 10:43:31 +00:00
parent 452a44277e
commit 4ea3a144da
15 changed files with 361 additions and 0 deletions
+3
View File
@@ -0,0 +1,3 @@
theme-details
public
.hugo_build.lock
+21
View File
@@ -0,0 +1,21 @@
# starless
Minimal Hugo theme and demo site.
## Run
```bash
hugo server
```
## Build
```bash
hugo
```
## Shape
- `themes/starless`: the theme
- `content/`: the site about the theme
- `theme-details/`: reference material
+13
View File
@@ -0,0 +1,13 @@
+++
title = "Starless"
+++
Starless is a small Hugo theme for dark, text first sites.
I built it to keep one shape and get out of the way: a left rail, a narrow reading column, and simple navigation.
There is no asset pipeline here. No client side framework either. Just Hugo templates and enough styling to hold the page together.
This site is both the demo and the docs. If something feels too clever, it probably does not belong in the theme.
Start with the guide if you want to use it. It is short on purpose.
+11
View File
@@ -0,0 +1,11 @@
+++
title = "Guide"
summary = "The short version of what Starless gives you and what it skips."
weight = 10
+++
Starless gives you a homepage, section pages, single pages, and a sidebar menu. That is the whole pitch.
It is meant for people who want a dark shell and plain content, not a huge pile of options. If you want every part configurable from front matter, you will outgrow this fast.
The rest of this section covers setup, the few things worth changing, and the files that actually matter.
+13
View File
@@ -0,0 +1,13 @@
+++
title = "Customize"
summary = "Change the title, menu, and footer strings first. Leave the rest alone until it bothers you."
weight = 12
+++
The fast path is to change four things in `hugo.toml`: `baseURL`, `title`, `params.sidebarFooter`, and `params.homeFooter`.
Then adjust `menus.main`. The sidebar shape comes from the menu, so you do not need a special data file or extra config layer.
If you want a different voice on the homepage, edit `content/_index.md`. If you want layout changes, start in `themes/starless/layouts/_default/baseof.html`.
That is enough for most forks. The theme stays easier to live with if you change one obvious file at a time.
+16
View File
@@ -0,0 +1,16 @@
+++
title = "Files"
summary = "The theme is small enough that you can learn it in one pass."
weight = 13
+++
The files that matter are not hard to find.
- `hugo.toml` sets the theme, site title, footer text, and sidebar menu.
- `content/` holds the homepage and this short guide.
- `themes/starless/layouts/_default/baseof.html` builds the page shell and the shared styling.
- `themes/starless/layouts/partials/sidebar.html` renders the left rail.
- `themes/starless/layouts/partials/menu-tree.html` renders the nested menu links.
- `themes/starless/layouts/_default/home.html`, `list.html`, and `single.html` handle the main content area.
If you are trying to understand the theme, read those files in that order. There is not much else hiding off to the side.
+13
View File
@@ -0,0 +1,13 @@
+++
title = "Install"
summary = "Start a Hugo site, copy the theme, and point the config at it."
weight = 11
+++
If you fork this repo, you already have the theme and the demo site in one place.
If you want to drop Starless into another Hugo site, copy the `themes/starless/` folder into that project and set `theme = "starless"` in `hugo.toml`.
After that, add a small `menus.main` block so the sidebar has something to render. The current config in this repo is enough to copy and trim.
Run `hugo server` and edit from there. The theme is simple enough that most changes show up where you expect.
+34
View File
@@ -0,0 +1,34 @@
baseURL = "https://example.org/"
locale = "en-us"
title = "Starless"
theme = "starless"
enableRobotsTXT = true
disableHugoGeneratorInject = true
[params]
description = "Starless is a small Hugo theme for dark, text first sites."
sidebarFooter = "Built with Hugo."
homeFooter = "Small on purpose."
[[menus.main]]
name = "Guide"
pageRef = "/docs"
weight = 10
[[menus.main]]
name = "Install"
pageRef = "/docs/install"
parent = "Guide"
weight = 11
[[menus.main]]
name = "Customize"
pageRef = "/docs/customize"
parent = "Guide"
weight = 12
[[menus.main]]
name = "Files"
pageRef = "/docs/files"
parent = "Guide"
weight = 13
@@ -0,0 +1,116 @@
<!DOCTYPE html>
<html class="dark" lang="{{ site.Language.Locale | default `en` }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{{ if .IsHome }}{{ site.Title }}{{ else }}{{ .Title }} | {{ site.Title }}{{ end }}</title>
<meta name="description" content="{{ with .Description }}{{ . }}{{ else }}{{ site.Params.description }}{{ end }}">
<script src="https://cdn.tailwindcss.com?plugins=forms,container-queries"></script>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Cormorant+Garamond:ital,wght@0,400;0,600;1,400&family=JetBrains+Mono:wght@400;700&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&display=swap" rel="stylesheet">
<script>
tailwind.config = {
darkMode: "class",
theme: {
extend: {
colors: {
surface: "#161413",
"surface-dim": "#161413",
"surface-bright": "#3d3937",
"surface-container-lowest": "#0c0b0a",
"surface-container-low": "#1d1a19",
"surface-container": "#211e1d",
"surface-container-high": "#2c2826",
"surface-container-highest": "#373130",
"on-surface": "#eae4e2",
"on-surface-variant": "#d2c7c5",
primary: "#d18c81",
"on-primary": "#3e1c15",
"primary-container": "#5b2c23",
"on-primary-container": "#ffdacf",
secondary: "#e2b8b1",
"on-secondary": "#412b26",
"secondary-container": "#5a413b",
"on-secondary-container": "#ffdacf",
tertiary: "#c9c3a3",
"on-tertiary": "#312e18",
"tertiary-container": "#48442c",
"on-tertiary-container": "#e6dfbc",
error: "#ffb4ab",
"on-error": "#690005",
"error-container": "#93000a",
"on-error-container": "#ffdad6",
background: "#161413",
"on-background": "#eae4e2",
outline: "#968d8a",
"outline-variant": "#4d4644",
"inverse-surface": "#eae4e2",
"inverse-on-surface": "#322f2e",
"inverse-primary": "#97483c"
},
borderRadius: {
DEFAULT: "0.25rem",
lg: "0.5rem",
xl: "0.75rem",
full: "9999px"
},
spacing: {
"container-max": "1120px",
"stack-lg": "32px",
"margin-mobile": "16px",
gutter: "24px",
"stack-sm": "4px",
"stack-md": "12px",
base: "8px"
},
fontFamily: {
"body-md": ["JetBrains Mono", "monospace"],
"body-lg": ["JetBrains Mono", "monospace"],
"display-lg": ["Cormorant Garamond", "serif"],
"headline-md": ["Cormorant Garamond", "serif"],
"label-sm": ["JetBrains Mono", "monospace"],
"display-lg-mobile": ["Cormorant Garamond", "serif"]
},
fontSize: {
"body-md": ["14px", { lineHeight: "24px", fontWeight: "400" }],
"body-lg": ["16px", { lineHeight: "28px", fontWeight: "400" }],
"display-lg": ["42px", { lineHeight: "1.2", fontWeight: "400" }],
"headline-md": ["24px", { lineHeight: "32px", fontWeight: "400" }],
"label-sm": ["12px", { lineHeight: "16px", fontWeight: "400" }],
"display-lg-mobile": ["32px", { lineHeight: "40px", fontWeight: "400" }]
}
}
}
}
</script>
<style>
.material-symbols-outlined {
font-variation-settings: 'FILL' 0, 'wght' 400, 'GRAD' 0, 'opsz' 24;
}
.tree-item {
position: relative;
}
.tree-item::before {
content: '';
position: absolute;
left: -12px;
top: 0;
bottom: 0;
width: 1px;
background-color: rgba(234, 228, 226, 0.1);
}
</style>
</head>
<body class="bg-surface text-on-surface font-body-md min-h-screen flex antialiased">
<div class="flex w-full max-w-7xl mx-auto px-8 py-16 gap-16">
{{ partial "sidebar.html" . }}
<main class="flex-1 max-w-3xl pt-2">
{{ block "main" . }}{{ end }}
</main>
</div>
</body>
</html>
@@ -0,0 +1,14 @@
{{ define "main" }}
<div class="prose prose-invert max-w-none text-body-md text-on-surface/90 space-y-6">
{{ .Content }}
</div>
<div class="mt-12">
<a class="inline-flex items-center text-on-surface-variant hover:text-primary transition-colors font-body-md italic mb-4" href="{{ `/docs/` | relLangURL }}">
Read the guide <span class="material-symbols-outlined ml-1 text-[18px]">arrow_forward</span>
</a>
<hr class="border-on-surface/10">
</div>
<div class="mt-auto pt-32 pb-8 font-display-lg italic text-on-surface-variant text-lg">
{{ site.Params.homeFooter }}
</div>
{{ end }}
@@ -0,0 +1,27 @@
{{ define "main" }}
<div class="prose prose-invert max-w-none text-body-md text-on-surface/90 space-y-6">
<p>{{ .Title }}</p>
{{ .Content }}
</div>
<div class="mt-12">
<a class="inline-flex items-center text-on-surface-variant hover:text-primary transition-colors font-body-md italic mb-4" href="{{ `/` | relLangURL }}">
Home <span class="material-symbols-outlined ml-1 text-[18px]">arrow_back</span>
</a>
<hr class="border-on-surface/10">
</div>
<div class="mt-8 divide-y divide-on-surface/10">
{{ range .Pages.ByWeight }}
<article class="py-5">
<p class="mb-3"><a class="hover:text-primary transition-colors" href="{{ .RelPermalink }}">{{ .Title }}</a></p>
{{ with .Params.summary }}
<p class="text-on-surface/90">{{ . }}</p>
{{ else }}
{{ with .Summary }}<p class="text-on-surface/90">{{ . | plainify }}</p>{{ end }}
{{ end }}
</article>
{{ end }}
</div>
<div class="mt-auto pt-32 pb-8 font-display-lg italic text-on-surface-variant text-lg">
{{ site.Params.homeFooter }}
</div>
{{ end }}
@@ -0,0 +1,15 @@
{{ define "main" }}
<div class="prose prose-invert max-w-none text-body-md text-on-surface/90 space-y-6">
<p>{{ .Title }}</p>
{{ .Content }}
</div>
<div class="mt-12">
<a class="inline-flex items-center text-on-surface-variant hover:text-primary transition-colors font-body-md italic mb-4" href="{{ printf "/%s/" .Section | relLangURL }}">
{{ .Section }} <span class="material-symbols-outlined ml-1 text-[18px]">arrow_back</span>
</a>
<hr class="border-on-surface/10">
</div>
<div class="mt-auto pt-32 pb-8 font-display-lg italic text-on-surface-variant text-lg">
{{ site.Params.homeFooter }}
</div>
{{ end }}
@@ -0,0 +1,29 @@
{{- range .ByWeight -}}
<div class="flex flex-col">
<a class="flex items-center {{ if .HasChildren }}text-on-surface{{ else }}text-on-surface-variant{{ end }} hover:text-primary transition-colors py-1 text-left w-full group" href="{{ .URL }}">
<span class="material-symbols-outlined text-[16px] mr-1 text-on-surface-variant group-hover:text-primary">{{ if .HasChildren }}expand_more{{ else }}chevron_right{{ end }}</span>
{{ .Name }}
</a>
{{- with .Children -}}
<div class="ml-6 flex flex-col gap-1 text-on-surface-variant text-label-sm tree-item mt-1 mb-2">
{{- range .ByWeight -}}
{{- if .HasChildren -}}
<div class="flex flex-col">
<a class="flex items-center hover:text-on-surface transition-colors py-0.5" href="{{ .URL }}">
<span class="material-symbols-outlined text-[14px] mr-1 text-on-surface-variant">expand_more</span>
{{ .Name }}
</a>
<div class="ml-5 flex flex-col gap-1 text-on-surface-variant text-label-sm tree-item mt-1 italic">
{{ range .Children.ByWeight }}
<a class="hover:text-on-surface transition-colors py-0.5" href="{{ .URL }}">{{ .Name }}</a>
{{ end }}
</div>
</div>
{{- else -}}
<a class="hover:text-on-surface transition-colors py-0.5 italic" href="{{ .URL }}">{{ .Name }}</a>
{{- end -}}
{{- end -}}
</div>
{{- end -}}
</div>
{{- end -}}
@@ -0,0 +1,24 @@
<aside class="w-72 flex-shrink-0 flex flex-col gap-12 border-r border-on-surface/10 pr-8">
<header>
<a class="font-display-lg text-display-lg text-on-surface" href="{{ `/` | relLangURL }}">{{ site.Title }}</a>
</header>
<div class="relative">
<span class="material-symbols-outlined absolute left-2 top-1.5 text-on-surface-variant text-[18px]">search</span>
<input class="w-full bg-transparent text-on-surface border border-outline/30 rounded py-1.5 pl-8 pr-3 focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary transition-colors placeholder-on-surface-variant/50 text-label-sm" placeholder="Search" type="text" aria-label="Search">
</div>
<nav class="flex flex-col gap-1 text-sm" aria-label="Primary">
{{ with site.Menus.main }}
{{ partial "menu-tree.html" . }}
{{ end }}
</nav>
{{ with site.Params.sidebarFooter }}
<div class="mt-auto pt-8 font-display-lg italic text-on-surface-variant text-lg">
{{ . }}
</div>
{{ end }}
{{/* ponytail: search stays visual-only until a real index is worth the runtime and markup */}}
</aside>
+12
View File
@@ -0,0 +1,12 @@
name = "starless"
license = "MIT"
licenselink = "https://opensource.org/licenses/MIT"
description = "A minimal dark editorial Hugo theme."
homepage = "https://example.org/"
demosite = "https://example.org/"
tags = ["blog", "minimal", "dark", "editorial"]
features = ["blog", "docs", "responsive", "no-javascript"]
min_version = "0.161.0"
[author]
name = "ruinivist"