init: scaffold OPENBUREAU site with shibui-derived theme

- Hugo site for openbureau.ch (Deutsch, i18n-ready for EN/IT)
- Theme themes/openbureau/ = local copy of shibui, customized via
  site-level layouts and assets to keep the theme reference clean
- Editorial typography stack: Newsreader serif body, Space Grotesk
  display, Inter for listings, IBM Plex Mono for technical meta
- Content structure: library/ (Theorie, Büroführung, Software) with
  manifest and colophon at root; software is a library category, not
  a separate top-level
- Three views over one source: Journal (chronological home),
  Library (atlas grouped by section + tag cloud), single articles

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-23 20:25:29 +02:00
commit 00c3343b1d
87 changed files with 2929 additions and 0 deletions
+25
View File
@@ -0,0 +1,25 @@
<!DOCTYPE html>
<html
lang="{{ site.Language.Locale | default site.Language.Lang }}"
dir="{{ or site.Language.Direction `ltr` }}"
>
<head>
{{ partial "head.html" . }}
</head>
<body>
<a href="#main-content" class="skip-link">Skip to content</a>
<header role="banner" class="site-header">
<a href="{{ "/" | relURL }}" class="wordmark-link">OPENBUREAU</a>
<nav class="site-nav" aria-label="Site">
{{ partial "menu.html" (dict "menuID" "main" "page" .) }}
</nav>
</header>
<main id="main-content" role="main">{{ block "main" . }}{{ end }}</main>
{{ if not .IsHome }}
<nav class="page-foot-nav" aria-label="Breadcrumb">
{{ partial "header.html" . }}
</nav>
{{ end }}
<footer role="contentinfo">{{ partial "footer.html" . }}</footer>
</body>
</html>
+41
View File
@@ -0,0 +1,41 @@
{{ define "main" }}
{{ partial "terms.html" (dict "taxonomy" "tags" "page" .) }}
<article class="single">
<header class="single-header">
<h1>{{ .Title }}</h1>
{{ with .Params.summary }}
<p class="single-summary text-muted">{{ . }}</p>
{{ end }}
</header>
{{/* Table of Contents */}}
{{ $hasToC := .Params.toc | default true }}
{{ $headers := findRE "<h[2-6]" .Content }}
{{ if and $hasToC (ge (len $headers) 1) }}
<nav class="toc">
<strong>Inhalt</strong>
<div class="toc-content">{{ .TableOfContents }}</div>
</nav>
{{ end }}
<div class="single-content">
{{ .Content }}
</div>
<div class="time">
{{ partial "date.html" .Date }}
{{ $showReadingTime := .Params.showreadingtime | default site.Params.showreadingtime | default true }}
{{ if and $showReadingTime .ReadingTime }}
<span class="reading-time"> · {{ .ReadingTime }} min Lesezeit</span>
{{ end }}
{{ $showLastMod := .Params.showlastmod | default site.Params.showlastmod | default false }}
{{ if and $showLastMod .Lastmod }}
{{ if ne (.Lastmod.Format "2006-01-02") (.Date.Format "2006-01-02") }}
<span class="lastmod"> · Zuletzt aktualisiert: {{ .Lastmod.Format "2006-01-02" }}</span>
{{ end }}
{{ end }}
</div>
</article>
{{ end }}
+17
View File
@@ -0,0 +1,17 @@
<div class="footer-grid">
<div class="footer-mark">OPENBUREAU</div>
<nav class="footer-nav" aria-label="Footer">
<ul>
<li><a href="/manifest/">Manifest</a></li>
<li><a href="/colophon/">Colophon</a></li>
<li><a href="https://openstudio.kgva.ch">Forum ↗</a></li>
<li><a href="https://gitea.kgva.ch">Code ↗</a></li>
<li><a href="/index.xml">RSS</a></li>
</ul>
</nav>
<p class="footer-tagline">
Sammlung, Plattform, Praxis.<br>
Texte unter <a href="https://creativecommons.org/licenses/by-sa/4.0/">CC BY-SA 4.0</a>.
</p>
<p class="footer-credit">© {{ now.Year }} · Karim Gabriele Varano</p>
</div>
+49
View File
@@ -0,0 +1,49 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="color-scheme" content="light" />
<title>{{ if .IsHome }}{{ site.Title | upper }}{{ else }}{{ printf "%s | %s" (.Title | upper) (site.Title | upper) }}{{ end }}</title>
{{ with .Description | default site.Params.description }}<meta name="description" content="{{ . }}" />{{ end }}
<link rel="canonical" href="{{ .Permalink }}" />
{{/* Open Graph */}}
<meta property="og:title" content="{{ .Title }}" />
{{ with .Description | default site.Params.description }}<meta property="og:description" content="{{ . }}" />{{ end }}
<meta property="og:type" content="{{ if .IsPage }}article{{ else }}website{{ end }}" />
<meta property="og:url" content="{{ .Permalink }}" />
{{ with site.Params.ogImage }}<meta property="og:image" content="{{ . | absURL }}" />{{ end }}
{{/* Twitter Card */}}
<meta name="twitter:card" content="summary" />
<meta name="twitter:title" content="{{ .Title }}" />
{{ with .Description | default site.Params.description }}<meta name="twitter:description" content="{{ . }}" />{{ end }}
{{/* RSS */}}
{{ with .OutputFormats.Get "rss" -}}
{{ printf `<link rel="%s" type="%s" href="%s" title="%s" />` .Rel .MediaType.Type .Permalink site.Title | safeHTML }}
{{ end }}
{{/* JSON-LD for articles */}}
{{ if .IsPage }}
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Article",
"headline": "{{ .Title }}",
"url": "{{ .Permalink }}",
"datePublished": "{{ .Date.Format "2006-01-02T15:04:05Z07:00" }}",
"dateModified": "{{ .Lastmod.Format "2006-01-02T15:04:05Z07:00" }}"
{{- with site.Params.author }},
"author": { "@type": "Person", "name": "{{ .name | default . }}" }
{{- end }}
{{- with $.Description | default site.Params.description }},
"description": "{{ . }}"
{{- end }}
}
</script>
{{ end }}
{{ partialCached "head/favicon.html" . }}
{{ partialCached "head/css.html" . }}
+41
View File
@@ -0,0 +1,41 @@
{{ define "main" }}
{{ .Content }}
{{ $library := where site.RegularPages "Section" "library" }}
{{ $journal := first 20 $library.ByDate.Reverse }}
<section class="journal" aria-label="Journal — neueste Beiträge">
<header class="journal-header">
<h2>Journal</h2>
<p class="text-muted">Was zuletzt geschrieben wurde.</p>
</header>
<ol class="journal-list">
{{ range $journal }}
<li class="journal-entry">
<a class="journal-entry-link" href="{{ .RelPermalink }}">
<div class="journal-meta">
{{ with .Parent }}
<span class="journal-section">{{ .Title }}</span>
{{ end }}
<time class="journal-date" datetime="{{ .Date.Format "2006-01-02" }}">{{ .Date.Format "2006-01-02" }}</time>
</div>
<h3 class="journal-title">{{ .LinkTitle }}</h3>
{{ with .Params.summary }}
<p class="journal-summary">{{ . }}</p>
{{ end }}
{{ with .Params.tags }}
<ul class="journal-tags">
{{ range . }}<li>#{{ . }}</li>{{ end }}
</ul>
{{ end }}
</a>
</li>
{{ end }}
</ol>
{{ if gt (len $library) 20 }}
<p class="more"><a href="/library/">→ Alle Beiträge in der Library</a></p>
{{ end }}
</section>
{{ end }}
+59
View File
@@ -0,0 +1,59 @@
{{ define "main" }}
{{ .Content }}
{{ if .IsSection }}
{{ if eq .Path "/library" }}
{{/* Library root: Atlas — gruppiert nach Untersection */}}
<section class="atlas">
{{ range .Sections.ByWeight }}
<article class="atlas-section">
<h2><a href="{{ .RelPermalink }}">{{ .Title }}</a></h2>
{{ with .Params.description }}<p class="text-muted">{{ . }}</p>{{ end }}
<ul class="atlas-list">
{{ range first 6 .RegularPages.ByDate.Reverse }}
<li>
<a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a>
<span class="list-meta text-muted"> · {{ partial "date.html" .Date }}</span>
</li>
{{ end }}
</ul>
{{ if gt (len .RegularPages) 6 }}
<p class="more"><a href="{{ .RelPermalink }}">alle in {{ .Title }} →</a></p>
{{ end }}
</article>
{{ end }}
{{/* Tag-Cloud */}}
{{ with site.Taxonomies.tags }}
<article class="atlas-tags">
<h2>Tags</h2>
<ul class="tag-cloud">
{{ range $name, $taxonomy := . }}
<li><a href="/tags/{{ $name | urlize }}/">{{ $name }} <span class="text-muted">({{ len $taxonomy }})</span></a></li>
{{ end }}
</ul>
</article>
{{ end }}
</section>
{{ else }}
{{/* Library subsection: chronologisch */}}
<div class="time-list">
<ul>
{{ range .RegularPages.ByDate.Reverse }}
<li class="list-item">
<div class="list-title-row">
<div class="list-title">
<a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a>
{{ with .Params.summary }}
<div class="list-summary text-muted">{{ . }}</div>
{{ end }}
</div>
<div class="list-meta">{{ partial "date.html" .Date }}</div>
</div>
</li>
{{ end }}
</ul>
</div>
{{ end }}
{{ end }}
{{ end }}