Ghost Themes: Custom Fonts lokal hosten

Ghost Themes: Custom Fonts lokal hosten

Im Dezember 2024 wurde für Ghost Core ein neues Feature eingeführt: Custom Fonts. Der Anwender hat dadurch jetzt die Möglichkeit, in den Admin-Einstellungen des Ghost-Blogs die Schriftart des Themes aus einer Vorauswahl von Fonts festzulegen.

Das hat aber einen entscheidenen Nachteil: Die Schriftarten werden alle samt vom externen CDN bunny.net nachgeladen. Das grundsätzliche Problem ist dabei, dass das im Ghost-Standard unmittelbar passiert, bevor der Besucher die Gelegenheit dem zu wiedersprechen. Um diversen Problemen aus dem Weg zu gehen, wäre daher ratsam, wenn die Schriftarten direkt vom eigenen Webservice bereitgestellt würden – vgl. dazu diesen Artikel.

Leider gibt es aktuell nicht die Möglichkeit über das UI eine andere Quelle für die Schriftarten anzugegeben. Also bleibt uns nur die Möglichkeit, das verwendete Theme direkt anzupassen. Einen ersten Hinweis dazu liefert der oben bereits zitierte Artikel zu den Custom Fonts.

Wichtiger Hinweis vorweg: Wir können die neue Schriftauswahl in den Ghost-Einstellungen nicht direkt auf lokales Schrifthosting umstellen. Wir können lediglich die vom Theme vorgegebene Default-Schriftart auf lokales Hosting umstellen. Die Schriftauswahl in Ghost muss daher zu jedem Zeitpunkt auf der Default-Schriftart des Themes verbleiben. Eine Veränderung der Schriftart darf nur direkt über den Sourcecode des Themes erfolgen, sonst verwendet Ghost wieder das bunny.net CDN:

Design & Branding Einstellungen von Ghost
Screenshot Design & Branding Ghost Einstellungen

Das Theme

Im Folgenden möchte die Anpassung an dem von mir verwendeten Attila-Theme zeigen. Für die zukünftige bessere Wartbarkeit, habe ich mir einen Fork des originalen Repos erstellt und für meine Anpassungen einen eigenen Branch custom-prod erzeugt.

Um zukünftig Updates des Themes durch den Maintainer möglichst wenig Aufwand zu haben, versuche ich soweit wie möglich mit Overlays zu arbeiten und den Standard-Code des Themes nicht anzupassen. Das gilt für die Schriftarten, CSS-Anpassungen und für die Anzeige des Feature-Images im Listing der Blogposts auf der Startseite. Für weitere Details dazu Verweise ich auch auf die README.md im Doc-Root des Git-Repos.


Grundsätzliches Vorgehen

  1. Schriftart z. B. bei Google-Fonts auswählen und lokal herunterladen.
  2. Schriftartdateien im Ordner ./assets/fonts des lokal ausgepackten Themes ablegen.
  3. Die Datei _fonts.scss unter ./src/sass anlegen und die Schriftarten dort konfigurieren.
  4. Die Datei _overrides.scss unter ./src/sass anlegen und hier ggf. abweichende Zuweisung der Schriftarten konfigurieren. Das ist z. B. erforderlich, wenn man für den Footer eine andere Schriftart als im Standard des Themes möchte.
  5. In der Datei styles.scss unter ./src/sass die beiden Dateien aus Schritt drei und vier hier einbinden und unter --gh-font-body: und --gh-font-heading: die Default-Schriftarten festlegen.
  6. Dann mittels grunt build und grunt compress ein neues ZIP-File des Themes inkl. der Änderungen bauen und fertig für den Einsatz in Ghost machen. Das ZIP-File wird im Ordner ./dist erzeugt.

Fonts lokal bereitstellen

Mittels des Google Webfonts Helper kann man sich die Fonts und die entsprechenden CSS-Snippets leicht besorgen:

Screenshot Google Webfonts Helper
/* aclonica-regular - latin */
@font-face {
  font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */
  font-family: 'Aclonica';
  font-style: normal;
  font-weight: 400;
  src: url('../fonts/aclonica-v25-latin-regular.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
}

Beispiel _fonts.scss

Aus diesen Snippets bauen wir dann die eigene _fonts.scss zusammen und legen sie unter ./src/sass ab.

CSS Overrides erstellen

Die Datei _overrides.scss zu erzeugen ist dabei optional und ist nur notwendig, wenn man die verwendeten Schriftarten an einigen Stellen ändern möchte. Die Idee ist auch hier, die Standard styles.scss soweit wie möglich nicht zu verändern, damit zukünftige Aktualisierungen des Themes sich leicht einpfelegen lassen.

/* Minimal overrides to keep upstream styles intact.
Use Fira Sans for UI/meta text while preserving serif only inside article content.
Keep all non-default changes consolidated here for easy diffing. */

body {
font-family: var(--gh-font-heading);
}

.post-content {
font-family: var(--gh-font-body);
}

.post-meta,
.post-footer,
.post-nav-meta,
.nav-header,
.nav-footer,
.nav-header .nav-wrapper-control,
.nav-header .nav-members,
.nav-footer .nav-wrapper {
font-family: var(--gh-font-heading);
}

Beispiel _overrides.scss

In der styles.scss nehmen wir jetzt nur minimale Anpassungen vor. Zum einen laden wir die bei den CSS-Files für die Schriftarten, die Overrides und legen die beiden Default-Schriftarten des Themes für die Headlines und den Body fest:

/* 
===========================
   Includes
===========================
*/

...

@use "fonts";
@use "overrides";

...

/* 
===========================
Basics
===========================
*/

...

:root {
	--gh-font-body: "Libre Baskerville Local", "Libre Baskerville", Georgia, serif;
	--gh-font-heading: "Fira Sans", system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
}

...

Beispiel style.scss


Das Theme bauen

Build-Voraussetzungen unter macOS

Damit das Theme (z. B. Attila/Fork) lokal gebaut und als ZIP gepackt werden kann, sollten diese Dinge installiert und eingerichtet sein:

  • Homebrew (Paketmanager)
  • Git (für Clone/Fork/Updates)
  • Xcode Command Line Tools (für make, clang, node-gyp)
  • nvm (Node Version Manager)
  • Node.js LTS über nvm (empfohlen: Node 18 oder 20)
  • npm (kommt mit Node)
  • Python 3
  • (optional) grunt-cli global – alternativ kannst du immer npx nutzen

Buildumgebung vorbereiten

Node.js in der LTS-Version 18 oder 20 installieren und laden:

nvm install 18
nvm use 18

Das Theme lokal herunterladen, ggf. entpacken und in den Pfad des Themes wechseln. Zum Beispiel das Git-Repo lokal auschecken:

git clone https://github.com/meese-evo/attila.git

cd attila-fork

Dependencies installieren:

npm ci

Python der Buildumgebung bereitstellen:

export npm_config_python="/opt/homebrew/opt/python@3.11/bin/python3.11"

Build ausführen und ZIP-Archiv erstellen

npx grunt build

npx grunt compress

Das ZIP-File des Themes befindet sich jetzt im Ordner ./dist und kann direkt in Ghost hochgeladen und bereitgestellt werden.

Ghost Admin → Settings → Theme → Upload themedist/<theme-name>.zip