Diese Website programmieren

Projekt-Steckbrief

  • Schwierigkeitsgrad: Mittel 3/5
  • Kosten: 0€
  • Zeitaufwand: ~15h

Die Idee

Die Idee entstand durch mein MobFobAmp-Projekt, für das ich kein Github-Repository hatte, da es keinen Code oder ähnliche Dokumentation gab. Also beschloss ich eine Website einzurichten, auf der ich Anleitungen für dieses Open-Hardware-Projekt bereitstellen kann, damit andere das Projekt nachbauen können. Ich wollte eine einfach zu hostende Lösung, die nicht zu viel Arbeit beim Einrichten erfordert. Da ich keinen eigenen Server habe, habe ich um Hilfe gebeten. moritzmar empfahl mir, für den Anfang “Github-Pages” als Site-Host zu verwenden, um eine einfache automatische Bereitstellung und globale Reichweite zu gewährleisten. Also habe ich das mal ausprobiert.

Erste Schritte

Eine statische Site kam mir genau Recht. Ohne die Notwendigkeit einer Datenbank oder eines großen Content-Management-Frameworks bleibt mein Site-Layout einfach und minimalistisch; ich wollte am Anfang nur dieses eine Projekt hosten. Github empfiehlt die Verwendung von Jekyll

Image: Jekyll Logo
Jekyll Logo [ 1 ]

als Website-Generator. Ich hatte einige Probleme mit dem Windows Subsystem für Linux (WSL), da es meine Terminaleingaben nicht akzeptierte, also folgte ich der Anleitung und verwendete den RubyInstaller, der bei mir sofort funktionierte.

Einrichtung der Site

Mir wurde klar, dass ich vielleicht mehrere meiner Projekte dokumentieren möchte. Deshalb kam ich auf die Idee, Projekte in Gruppen zusammenzufassen, jede mit einer Überschrift, einem kleinen Text und einem Miniaturbild. Wenn man darauf klickt, kommt man auf die jeweilige Projektseite. Das würde eine Menge Programmierarbeit für die Seiteneinrichtung und das Layout bedeuten, mit der ich nicht allzu viel Zeit verbringen wollte - meine anderen Projekte warten…

Erster Versuch mit Themes

Also folgte ich einer weiteren Anregung von Github-Pages: Die Verwendung von vordefinierten “Themes”. Zuerst habe ich das Agency Theme verwendet. Es hat eine tolle Landing Page mit einem großen Bild und unterstützt Sammlungen, die das von mir gewünschte Gruppieren von Projekten ermöglichen. Leider ist das Thema ein “Remote-Thema”, so dass die Anpassungsmöglichkeiten begrenzt waren, z. B. konnte ich eine Sammlung nicht auf eine andere Seite verweisen lassen, sondern es öffnete sich immer ein “Popup”, und das wollte ich einfach nicht. (Später habe ich herausgefunden, dass Remote-Layouts überschrieben werden können, aber da war es zu spät, denn ich hatte bereits zu einem anderen Theme-Anbieter gewechselt…) Das Theme, das ich derzeit verwende, ist das “Minimal Mistakes Theme” (siehe Fußzeile der Website), das sehr gut dokumentiert ist. Nach dem Herunterladen und ein paar ersten Schritten kämpfte ich mit benutzerdefinierten Farben (_sass) und den Kollektionen - wieder einmal - da ich zunächst nicht verstand, wie Jekyll die Bindungen hinter den Kulissen durchführt. Einige meiner Schwierigkeiten sind in den Blog-Beiträgen vom Juni 2021 zu finden.

Seitenlayouts: Hero Screens

Um die Navigation einfach und intuitiv zu gestalten, sollte man sich ein paar Gedanken darüber machen, wie das Layout der Seite aussehen soll. Die Herangehensweise wird sich bei jedem Seitentyp aufgrund der unterschiedlichen Komplexität und Dokumentstruktur unterscheiden. Image: landing hero Auf der Landing-/Homepage zum Beispiel soll die Navigation mitlaufen, so dass die Kategorien der Website immer sichtbar sind. Sie soll ein großes, breites Overlay-Bild mit der Seitenbeschreibung erhalten. Darunter sollen die neuesten Beiträge aufgelistet werden. Dies ist das Beispiel für die “Hero Pages” der Kollektion: Image: collection hero Die Projekte und ihre Inhalte enthalten eine Seitennavigation in der linken Seitenleiste, können ein scrollbares Panoramabild enthalten und haben eine breite Einstellung, um eine große Menge an Text im Inhaltsbereich anzuzeigen.

Image: project hero

Die “hero screen”-Skizzen für die Layouts dieser Website finden Sie hier.

Sammlungen / Kollektionen

Sammlungen (englisch “Collections”) sind eine gute Möglichkeit, Inhalte zu gruppieren. Sehen Sie sich meine Open Hardware Projekte Seite an. Sie können alle Projekte in dieser Kategorie mit einem kleinen Teaser-Bild und einer Beschreibung finden, um einen Überblick zu bekommen.

So kann die Konfiguration der Sammlung aussehen:

  • Überlegen Sie sich einen passenden Namen für Ihre Sammlung, z.B. electronics.
  • Der Name der Sammlung wird in _config.yml als collections: electronics definiert.
  • Der Sammlungsname muss in #defaults als type: electronics gesetzt werden, damit Jekyll weiß, wie der tatsächliche Inhalt zu interpretieren ist.
  • Eine Sammlungsseite muss erstellt werden (z.B. im Ordner _pages) mit dem Attribut collection: electronics. Dies ist die Seite, die die Übersicht der Artikel in der Sammlung anzeigt.
  • Es muss ein Ordner mit demselben Namen wie der Name der Sammlung mit führendem Unterstrich erstellt werden: _electronics.
  • Alle Dokumente in diesem Ordner werden nach einem vollständigen Bauvorgang automatisch auf der Sammlungsseite angezeigt.
  • Diese Dokumente sollten ein “front matter” (Abschnitt vor dem eigentlichen Inhalt in der Datei, gekennzeichnet mit ---) erhalten, damit sie wie in der entsprechenden _layouts-Datei beschrieben angezeigt werden können, z.B. collection. Vergisst man dies, wirft einem Jekyll in der Konsole seitenlange, unverständliche Fehlermeldungen um die Ohren.

Mehr als das Standard-Theme

Ich habe zwar einige Theme-Standardeinstellungen überschrieben, verwende aber zumeist die bestehendenTheme-Infrastruktur. Dennoch hat meine Seite ein paar spezielle Anforderungen, so dass ich das Theme anpassen und neue Funktionen hinzufügen musste. Diese werden in den folgenden Abschnitten beschrieben.

Seitenleiste: Seitennavigation

Da der Navigationsbaum meiner Website ziemlich flach ist und ich nicht viele Seiten habe, zu denen ich navigieren muss, wollte ich, dass die linke Seitenleiste die Seitennavigation und nicht die Website-Navigation enthält. Daher bräuchte ich keine rechte Seitenleiste, so dass mehr Platz für den Seiteninhalt zur Verfügung stünde.

Inhaltsverzeichnis auf der linken Seite

Wie hier und dort geschrieben, war ich nie 100%ig zufrieden damit, wie meine Projektseiten aussahen: Image:  Projektseite bevor ich toc_left einrichtete

Die ursprüngliche Idee des Themes ist, dass der Inhalt von zwei Seitenleisten eingerahmt wird. Die linke kann entweder Autoreninformationen, benutzerdefinierte Inhalte oder die Seitennavigation anzeigen. Der Inhaltsbereich ist zwischen breit und normal konfigurierbar, wobei in letzterem Fall Platz für eine zweite Seitenleiste auf der rechten Seite bleibt. Die rechte Seitenleiste ist so konfigurierbar, dass sie entweder gar nicht vorhanden ist oder das Inhaltsverzeichnis der Seite anzeigt.

Das Ziel war also die rechte Seitenleiste für mein Design zu eliminieren und statt der Seitennavigation in der linken Seitenleiste die Seitennavigation dorthin zu verschieben.

Wo das Design der Seitenleiste definiert wird

Es geht um den Ordner /_layouts, in dem Informationen darüber gespeichert werden, wie ein Seitenlayout aussehen soll. Das fragliche Seitendesign heißt single.html und ruft an einer bestimmten Stelle include sidebar.html auf, das sich in /_includes/sidebar.html befindet. Also habe ich mir einen neuen Parameter ausgedacht, mit dem ich die Anzeige des Inhaltsverzeichnisses in der linken Seitenleiste steuern kann, habe toc_left gewählt und eine Bedingung hinzugefügt:

<div class="sidebar sticky">
<!-- ...
{.% if page.toc_left %}
    {.% include toc_left nav=page.toc_left %}
{.% endif %}
... -->
</div>

(Trick: Ich musste jinja code auskommentieren und mit ... anführen, denn Liquid würde sie sonst selbst als Kommandos erkennen)

Implementierung des Inhaltsverzeichnisses

Es sollte in der linken Seitenleiste erscheinen. Also muste ich nur eine Datei namens toc_left erzeugen, die den Generator für das Inhaltsverzeichnis wie folgt aufruft:

<aside class="toc_left">
<nav class="toc" markdown="1">
<header><h4 class="nav__title"><i class="fas fa-file-alt"></i>
<!-- ...
{.{ include.title | .default: site.data.ui-text[site.locale].toc_label }}</h4></header>
{.% include toc.html sanitize=true html=content h_min=1 h_max=6 class="toc__menu" skip_no_ids=true %} 
... -->
</nav>
</aside>

Audio-Einbettungen

Audio-Embeds sind diese kleinen Player-ähnlichen Dinger auf einer Website, die oft zu einer Streaming-Plattform oder ähnlichem weiterleiten. Ich brauche sie für einige meiner Audio-Projekte wie dieses mobfobamp: nur eine Überschrift und der Player darunter.

Image: embed-audio

Dieser Beitrag hat mir sehr geholfen, so dass ich es einfach in das _include einfügen konnte, es ein wenig modifizieren konnte, und es funktionierte auf Anhieb.

Platzierung des Favicons

Ich folgte dieser Anleitung, um ein Favicon für die Website zu platzieren.

Image: favicon

Der Pfad des Favicons muss unabhängig von dem Ordner, in dem sich die gerenderte Seite befindet, gültig sein. Ich musste ../ entsprechend der Tiefe der Seiten in der Ordnerstruktur der Website hinzufügen, um sicherzustellen, dass das Favicon nicht nur auf der Startseite, sondern auch auf Unterseiten angezeigt werden kann.

Optimierung für Suchmaschinen

Da meine Website einige Wochen lang nicht von Suchmaschinen gefunden wurde, beschloss ich, eine so genannte “SEO” (Suchmaschinenoptimierung) durchzuführen. Deshalb fügte ich jekyll-seo-tag hinzu und überarbeitete z.B. alle meine Links nach Juliette Sinibardy’s SEO 101. Danach habe ich meine Webseite dem Web-Analyse-Audit von Lighthouse unterzogen. Image: Lighthouse Audit Ergebnisse Für einen ersten Versuch sieht es meiner Meinung nach ziemlich gut aus. Das größte Problem auf der Leistungsseite scheint der CSS-Overhead zu sein.

Sicherheitsrichtlinie für Inhalte

Der Lighthouse-Audit hat gezeigt, dass es eine gute Idee wäre, externe Skripte - wie sie die Basisversion meines Themes enthält - einzuschränken. Also habe ich eine Content Security Policy (CSP) wie folgt eingeführt:

webrick:
  headers:
    Content-Security-Policy: 
      default-src 'self'; 
      script-src 'self'; 
      connect-src 'self'; 
      img-src 'self'; 
      style-src 'self' 
      font-src 'self;

Mit dieser strikten Auslegung werden Inhalte Dritter gar nicht mehr geladen (aber leider meine eigenen teils auch nicht).

Anfänglich wurde das Hintergrundbild meiner Homepage nicht angezeigt, meine eingebetteten Audiodateien konnten nicht abgespielt werden und alle Icons, die von extern geladen wurden, waren ebenfalls weg. Das Hinzufügen von media-src: 'self'; und etwas mehr Lektüre in Jakob Wilforss’ Blog und vor allem Lighthouses eigene Vorschläge halfen bei der Lösung dieses Problems. Mit Hilfe der Web developer Tools des Browsers habe ich die fehlenden Ressourcen ermittelt, die das Theme im Hintergrund zu laden versucht, so dass mein aktualisiertes CSP wie folgt aussieht:

webrick:
  headers:
    Content-Security-Policy:
      default-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net/; 
      script-src 'self';
      connect-src 'self';
      img-src 'self' 'unsafe-inline' https://upload.wikimedia.org/wikipedia/commons/ https://raw.githubusercontent.com;
      style-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net/;
      font-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net/; 
      media-src 'self'; 
      object-src 'none';
      base-uri 'none';

Update

Ende 2021 bin ich vom Nachladen von Inhalten über Drittanbieter (oben namentlich Font Awesome und Wikimedia) auf die eigene, statische Bereitstellung übergegangen. Somit gibt es keine Dritten mehr, die beim Aufruf meiner Seite etwas von Ihnen mitbekommen - und die Seite lädt etwas schneller. Meine Content Security Policy habe ich wieder auf die Obere der beiden Darstellungen zurückgedreht, media-src 'self'; aber beibehalten.

Fehler

Hier sammele ich Fehler, deren Lösung trivial erscheint, die mich aber dennoch ganze Abende gekostet haben.

Jekyll serve: UTF-8 incompatible character encoding

Image: bundle error when front matter is missing Man gibt bundle exec jekyll serve ein und erhält einen seltsamen UTF-8 “incompatible character encoding” Fehler? Die Ursache ist einfach: Eine der zu konvertierenden Dateien hat höchstwahrscheinlich keinen Header, der in das “Front matter” der Seite übersetzt werden kann, die aus dieser Datei generiert wird. Einfach die übliche Kopfzeile zur fraglichen Datei hinzufügen und schon funktioniert es wieder:

---
title: "Feeds and Speeds database"
excerpt: "for (light) CNC milling machines"
header:
  image: "blah/testimage.jpg"
[...]
---

Webseite wird nicht dargestellt: 404

Dieser Fehler war besonders fies versteckt, denn auf meinem Rechner als localhost wird die Seite einwandfrei dargestellt - nur “in Produktion” erscheint, wenn ich die Seite aufrufe, gar nichts - nicht einmal meine selbstgebaute Fehlerseite.

Ursache: neuerdings verwende ich das permalink: Attribut in der Frontmatter von Seiten, die übersetzt werden sollen und auf einer tieferen Ebene liegen - für diese möchte ich die Links kurz halten, daher bekommen sie manuell erstellte Permalinks. Nur wenn ich ihnen ein “trailing slash” gebe, lassen sie sich auch online aufrufen. Beispiel:

# Falsch:
---
title: "This Page won't be displayed"
permalink: /projects-software/pageerror
# [...]
---
# Richtig:
---
title: "This Page will be displayed!"
permalink: /projects-software/nopageerror/
# [...]
# Wird auf dem deutschen Blog zu:
# https://blog.schallbert.de/projects-software/nopageerror/
---

Website-Hosting

Diese Seite ist selbst ein normales Gitea-Repository. Es wird automatisch mit einer von Github Actions entlehnten Aktion gebaut, sobald Änderungen zum Main des Repositorys hinzugefügt werden.

Update Jan-2024

Inzwischen bin ich von Github-Pages nach Gitea umgezogen und hoste meine Webpräsenz nun selber. Dennoch sind alle Inhalte dieser Seite weiterhin als Repository verfügbar und können leicht von mir gewartet und auf Stand gebracht werden. Außerdem schütze ich die Site nun vor unautorisiertem Zugriff

Zusammenfassung

Sich damit vertraut zu machen wie Jekyll die Seite erstellt, wie das Theme mit meinen Befehlen interagiert und wie man das Verhalten des Themes überschreibt, hat einige Stunden gekostet. Aber ich denke, dass diese Seite eine klare Struktur und ein mehr oder weniger “professionelles” Aussehen besitzt - und ich musste nicht eine einzige Zeile JavaScript oder HTML schreiben, um das zu erreichen. Toll!

  • Inhalt in Markdown *.md geschrieben
  • Grundlegende Konfiguration der Seite in YAML _config.yml
  • Seitenlayouts in html und jinja *.html, abgelegt in _layouts und _includes
  • Seitenvariablen und Aussehen in SASS *.scss, automatische Generierung von css-Dateien

Lust mitzumachen oder Beiträge beizusteuern?

Sie haben Ideen, Kritik oder interessante Dinge, die Sie mir mitteilen möchten? Nehmen Sie gern über meine Diskussions-Seite Kontakt auf.