Add news posts with banner summaries on the home page
Posts live in content/post/; the five latest are summarised on the home page. Builds for check/deploy go to build/ so they do not collide with a running hugo server writing to public/. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YDRjtmAiNpo5mK5N3d7QwZ
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
/public/
|
||||
/build/
|
||||
/resources/_gen/
|
||||
.hugo_build.lock
|
||||
__pycache__/
|
||||
|
||||
@@ -1,28 +1,31 @@
|
||||
OC ?= ../oc
|
||||
# not public/: a running `hugo server` renders there, with its live-reload script
|
||||
BUILD ?= build
|
||||
# test server: the web share of barbel-lescar, mounted from the file manager (smb://barbel-lescar/web)
|
||||
DEPLOY_DIR ?= /run/user/$(shell id -u)/gvfs/smb-share:server=barbel-lescar,share=web/oldcomputers
|
||||
DEPLOY_URL ?= https://barbel.synology.me/oldcomputers/
|
||||
|
||||
.PHONY: content build check serve deploy
|
||||
.PHONY: content build check serve deploy post
|
||||
|
||||
content: ## regenerate content/ and static/media/ from the extraction repo
|
||||
python3 $(OC)/scripts/05_hugo.py --target $(CURDIR)
|
||||
|
||||
build: ## build the site into public/
|
||||
rm -rf public
|
||||
hugo --panicOnWarning --minify
|
||||
build: ## build the site into $(BUILD)/
|
||||
rm -rf $(BUILD)
|
||||
hugo --panicOnWarning --minify -d $(BUILD)
|
||||
|
||||
check: build ## build, then verify every internal link and image
|
||||
python3 tools/check_links.py public
|
||||
python3 tools/check_links.py $(BUILD)
|
||||
|
||||
serve: ## local preview on http://localhost:1313
|
||||
hugo server
|
||||
|
||||
deploy: ## build, check, and copy public/ to DEPLOY_DIR (served at DEPLOY_URL)
|
||||
rm -rf public
|
||||
hugo --panicOnWarning --minify
|
||||
python3 tools/check_links.py public
|
||||
post: ## new post: make post NAME=my-title, then edit content/post/<today>-my-title.md
|
||||
@test -n "$(NAME)" || { echo "usage: make post NAME=my-title"; exit 1; }
|
||||
hugo new content post/$(shell date +%F)-$(NAME).md
|
||||
|
||||
deploy: check ## build, check, and copy $(BUILD)/ to DEPLOY_DIR (served at DEPLOY_URL)
|
||||
@test -d "$(dir $(DEPLOY_DIR))" || { echo "share not mounted: $(dir $(DEPLOY_DIR))"; exit 1; }
|
||||
mkdir -p "$(DEPLOY_DIR)"
|
||||
rsync -r --size-only --info=stats1 public/media/ "$(DEPLOY_DIR)/media/"
|
||||
rsync -rc --delete --exclude=/media/ --info=stats1 public/ "$(DEPLOY_DIR)/"
|
||||
rsync -r --size-only --info=stats1 $(BUILD)/media/ "$(DEPLOY_DIR)/media/"
|
||||
rsync -rc --delete --exclude=/media/ --info=stats1 $(BUILD)/ "$(DEPLOY_DIR)/"
|
||||
|
||||
@@ -9,16 +9,29 @@ Static rebuild of old-computers.com with [Hugo](https://gohugo.io/) (0.158 or ne
|
||||
| `content/{museum,machine-tabs,companies,software,history,magazine,fun}/` | generated, replaced on every `make content` |
|
||||
| `static/media/` | generated (copied images and documents) |
|
||||
| `data/slugs.json` | generated, keeps URLs stable between runs — do not delete |
|
||||
| `content/post/` | written by hand: news posts, see below |
|
||||
| `content/_index.md`, `layouts/`, `assets/`, `hugo.toml`, `tools/` | written by hand |
|
||||
| `public/` | build output, not versioned |
|
||||
| `build/`, `public/` | build output (`make build`, `hugo server`), not versioned |
|
||||
|
||||
Content pages are Markdown with YAML front matter and can be corrected by hand, but a later
|
||||
`make content` overwrites them: lasting fixes belong in the extraction repository.
|
||||
|
||||
## Posts
|
||||
|
||||
make post NAME=my-title
|
||||
|
||||
creates `content/post/<today>-my-title.md` (any `.md` file in `content/post/` is a post). The
|
||||
date comes from the file name unless `date:` is set; `author:` is optional. For a banner, put an
|
||||
image under `static/media/` and set `banner: /media/....jpg`. Write the text in Markdown and
|
||||
remove `draft: true` to publish. The five most recent posts appear on the home page with their
|
||||
banner, date, author and summary (`summary:` in the front matter, or the text before
|
||||
`<!--more-->`, or the first lines); all posts are listed under News. Posts are never touched by
|
||||
`make content`.
|
||||
|
||||
## Usage
|
||||
|
||||
make content # regenerate from ../oc (OC=path to use another location)
|
||||
make build # build into public/
|
||||
make build # build into build/
|
||||
make check # build + verify every internal link and image
|
||||
make serve # preview on http://localhost:1313
|
||||
make deploy # build and copy to the test server (share must be mounted; see DEPLOY_DIR/DEPLOY_URL)
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
---
|
||||
title: "{{ replace (replaceRE `^\d{4}-\d{2}-\d{2}-` "" .File.ContentBaseName) "-" " " | title }}"
|
||||
author:
|
||||
# banner: image shown on the home page and at the top of the post, e.g. /media/posts/my-image.jpg
|
||||
# (file stored under static/media/)
|
||||
banner:
|
||||
# summary: optional; without it the text before <!--more--> (or the first lines) is used
|
||||
draft: true
|
||||
---
|
||||
|
||||
Write the post here.
|
||||
@@ -111,3 +111,21 @@ table { border-collapse: collapse; }
|
||||
.comments li { margin-bottom: 12px; overflow-wrap: anywhere; }
|
||||
.comments .meta { margin: 0 0 6px; font-size: 0.9rem; }
|
||||
.prev-next { display: flex; justify-content: space-between; gap: 16px; margin-top: 24px; }
|
||||
|
||||
.posts { display: grid; gap: 16px; }
|
||||
.post-summary {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 280px) 1fr;
|
||||
gap: 16px;
|
||||
background: var(--panel);
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 4px;
|
||||
padding: 12px;
|
||||
}
|
||||
.post-summary:not(:has(.banner)) { grid-template-columns: 1fr; }
|
||||
.post-summary .banner img { display: block; width: 100%; aspect-ratio: 16 / 9; object-fit: cover; border-radius: 2px; }
|
||||
.post-summary h3 { margin: 0 0 2px; font-size: 1.15rem; }
|
||||
.post-summary .meta { margin: 0 0 8px; font-size: 0.85rem; }
|
||||
.post-summary p:last-child { margin-bottom: 0; }
|
||||
.post-banner { display: block; width: 100%; max-height: 420px; object-fit: cover; margin: 0 0 16px; border-radius: 4px; }
|
||||
@media (max-width: 600px) { .post-summary { grid-template-columns: 1fr; } }
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
---
|
||||
title: News
|
||||
---
|
||||
@@ -6,6 +6,10 @@ disableKinds = ["rss", "sitemap"]
|
||||
# pages keep working when the site is served from a sub-directory
|
||||
relativeURLs = true
|
||||
|
||||
# a post named 2026-10-11-my-title.md gets its date from the file name (and the URL /post/my-title/)
|
||||
[frontmatter]
|
||||
date = ["date", ":filename", ":default"]
|
||||
|
||||
[params]
|
||||
description = "The Old-Computers.com museum of computers, consoles and pongs, rebuilt from the Wayback Machine archive."
|
||||
|
||||
@@ -21,6 +25,10 @@ relativeURLs = true
|
||||
collection = "collections"
|
||||
|
||||
[menus]
|
||||
[[menus.main]]
|
||||
name = "News"
|
||||
pageRef = "/post"
|
||||
weight = 5
|
||||
[[menus.main]]
|
||||
name = "Museum"
|
||||
pageRef = "/museum"
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
{{/* dict "page" <post> "width" <px> -> URL of the post banner, resized when it is a bundle image */}}
|
||||
{{- $url := "" -}}
|
||||
{{- with .page.Params.banner -}}
|
||||
{{- with $.page.Resources.GetMatch . -}}
|
||||
{{- if and (eq .MediaType.MainType "image") (ne .MediaType.SubType "svg") -}}
|
||||
{{- $url = (.Resize (printf "%dx" $.width)).RelPermalink -}}
|
||||
{{- else -}}
|
||||
{{- $url = .RelPermalink -}}
|
||||
{{- end -}}
|
||||
{{- else -}}
|
||||
{{- $url = . -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- return $url -}}
|
||||
@@ -0,0 +1,11 @@
|
||||
<article class="post-summary">
|
||||
{{ with partial "banner.html" (dict "page" . "width" 640) }}
|
||||
<a class="banner" href="{{ $.RelPermalink }}"><img src="{{ . }}" alt="" loading="lazy"></a>
|
||||
{{ end }}
|
||||
<div>
|
||||
<h3><a href="{{ .RelPermalink }}">{{ .Title }}</a></h3>
|
||||
<p class="meta">{{ if not .Date.IsZero }}<time datetime="{{ .Date.Format "2006-01-02" }}">{{ .Date.Format "2 January 2006" }}</time>{{ end }}{{ with .Params.author }}{{ if not $.Date.IsZero }} · {{ end }}{{ . }}{{ end }}</p>
|
||||
<div class="summary">{{ .Summary }}</div>
|
||||
{{ if .Truncated }}<p><a href="{{ .RelPermalink }}">Read more →</a></p>{{ end }}
|
||||
</div>
|
||||
</article>
|
||||
+13
-2
@@ -1,14 +1,25 @@
|
||||
{{ define "main" }}
|
||||
<h1>{{ .Title }}</h1>
|
||||
<div class="content">{{ .Content }}</div>
|
||||
{{ with site.GetPage "/post" }}
|
||||
{{ $posts := .RegularPages.ByDate.Reverse }}
|
||||
{{ if $posts }}
|
||||
<h2>{{ .Title }}</h2>
|
||||
<div class="posts">
|
||||
{{ range first 5 $posts }}{{ partial "post-summary.html" . }}{{ end }}
|
||||
</div>
|
||||
{{ if gt (len $posts) 5 }}<p><a href="{{ .RelPermalink }}">All posts →</a></p>{{ end }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
<h2>Sections</h2>
|
||||
<div class="cards">
|
||||
{{ range site.Menus.main }}
|
||||
{{ with .Page }}
|
||||
{{ with .Page }}{{ if ne .Section "post" }}
|
||||
<a class="card" href="{{ .RelPermalink }}">
|
||||
<strong>{{ .Title }}</strong>
|
||||
<span>{{ len .RegularPages }} {{ if eq (len .RegularPages) 1 }}page{{ else }}pages{{ end }}</span>
|
||||
</a>
|
||||
{{ end }}
|
||||
{{ end }}{{ end }}
|
||||
{{ end }}
|
||||
</div>
|
||||
<h2>Browse the museum</h2>
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
{{ define "main" }}
|
||||
<h1>{{ .Title }}</h1>
|
||||
<div class="content">{{ .Content }}</div>
|
||||
<div class="posts">
|
||||
{{ range .RegularPages.ByDate.Reverse }}{{ partial "post-summary.html" . }}{{ end }}
|
||||
</div>
|
||||
{{ end }}
|
||||
@@ -0,0 +1,13 @@
|
||||
{{ define "main" }}
|
||||
<article class="post">
|
||||
<p class="crumbs"><a href="{{ .Parent.RelPermalink }}">{{ .Parent.Title }}</a></p>
|
||||
<h1>{{ .Title }}</h1>
|
||||
<p class="meta">{{ if not .Date.IsZero }}<time datetime="{{ .Date.Format "2006-01-02" }}">{{ .Date.Format "2 January 2006" }}</time>{{ end }}{{ with .Params.author }}{{ if not $.Date.IsZero }} · {{ end }}{{ . }}{{ end }}</p>
|
||||
{{ with partial "banner.html" (dict "page" . "width" 1000) }}<img class="post-banner" src="{{ . }}" alt="">{{ end }}
|
||||
<div class="content">{{ .Content }}</div>
|
||||
<nav class="prev-next">
|
||||
{{ with .PrevInSection }}<a href="{{ .RelPermalink }}">← {{ .Title }}</a>{{ end }}
|
||||
{{ with .NextInSection }}<a href="{{ .RelPermalink }}">{{ .Title }} →</a>{{ end }}
|
||||
</nav>
|
||||
</article>
|
||||
{{ end }}
|
||||
Reference in New Issue
Block a user