LabCodeHub öffentliche Ansicht
Anmelden
Küpper / Quildrop öffentlich
Branch: main
Quildrop / README-de.md
Verlauf Rohdaten
R Rüdiger Küpper fix: add sitemap and robots.txt
89f2d506 vor 14 Tagen
README-de.md 520 Zeilen · 19.0 KB · Markdown

QuillDrop

QuillDrop ist ein modernes, minimalistisches Blog-CMS, geschrieben in Go. Es kombiniert die Geschwindigkeit eines Static Site Generators mit der Flexibilität eines dynamischen HTTP-Servers - ohne externe Datenbank, ohne JavaScript-Frameworks, ohne Overhead.

Philosophie

Write. Save. Published.

QuillDrop folgt dem Prinzip der maximalen Einfachheit: Markdown-Dateien schreiben, speichern - fertig. Kein Build-Tool-Chaos, kein Node.js, keine Datenbank. Ein einzelnes Go-Binary erledigt alles.

Features

Dual-Mode Betrieb

QuillDrop unterstützt zwei Betriebsmodi in einem einzigen Binary:

  • quilldrop serve - Startet einen dynamischen HTTP-Server für lokale Entwicklung und Vorschau. Ideal zum Schreiben und sofortigen Testen neuer Posts.
  • quilldrop generate - Generiert eine komplette statische Website als HTML-Dateien. Perfekt für Deployment auf Nginx, Apache, CDN oder GitHub Pages.

Markdown mit YAML-Frontmatter

Posts und Seiten werden als einfache Markdown-Dateien mit YAML-Frontmatter geschrieben:

---
title: "Mein neuer Blogpost"
date: 2025-11-06 12:00:00
author: "Max Mustermann"
cover: "/images/posts/2025/11/cover.webp"
tags: [Kubernetes, DevOps, Self-Hosted]
categories: [Technik]
preview: "Kurze Vorschau des Posts..."
draft: false
toc: true
---

# Hier beginnt der Post

Normales Markdown mit allen Extras...

Unterstützte Frontmatter-Felder:

FeldBeschreibung
titleTitel des Posts
dateVeröffentlichungsdatum (mehrere Formate unterstützt)
updateLetzte Aktualisierung
authorAutor des Posts
cover / featureImageCover-Bild (mit Fallback)
tagsListe von Tags
categoriesListe von Kategorien
previewBenutzerdefinierte Vorschau (sonst automatisch aus erstem Absatz)
draftEntwurf - wird nicht veröffentlicht
tocInhaltsverzeichnis automatisch generieren
hidePost verstecken
topPost oben anpinnen

Erweitertes Markdown-Rendering

QuillDrop nutzt Goldmark als Markdown-Engine mit folgenden Erweiterungen:

  • GitHub Flavored Markdown (GFM) - Tabellen, Strikethrough, Autolinks, Task-Listen
  • Syntax Highlighting - Über 200 Programmiersprachen mit dem Dracula-Theme via Chroma
  • Emoji-Support - Shortcodes wie :rocket:, :tada:, :satellite:
  • Automatische Heading-IDs - Für Ankerverlinkung und Inhaltsverzeichnis
  • Raw HTML - Einbettung von HTML direkt im Markdown
  • Hugo-Kompatibilität - {{</* rawhtml */>}} Shortcodes werden automatisch verarbeitet

Responsives Design mit Dark/Light Theme

Das mitgelieferte Theme bietet:

  • Dark Mode als Default mit einem hellen Alternativ-Theme
  • Theme Toggle mit localStorage-Persistenz (bleibt nach Reload erhalten)
  • Futuristisches Design - Dunkle Hintergrunde, Cyan-Akzente, subtile Glow-Effekte
  • Responsive Layout - Mobile-first, optimiert für alle Bildschirmgrößen
  • Hamburger-Navigation auf mobilen Geräten mit Fullscreen-Overlay und eigenem Stacking Context
  • Dropdown-Menus für verschachtelte Navigation (Touch-optimiert auf Mobile)
  • Integrierte Suche — Lupe in der Navbar mit Ctrl+K Shortcut
  • Typographie - Inter als Textfont, JetBrains Mono für Code und Metadaten

Navigation und Menü

Das Navigationsmenü wird vollständig über die config.yaml konfiguriert und unterstützt verschachtelte Dropdown-Menüs:

menu:
  - label: "Home"
    url: "/"
  - label: "Projekte"
    children:
      - label: "VM-Manager"
        url: "/sites/projekte/vm-manager"
      - label: "VM-Tracker"
        url: "/sites/projekte/vm-tracker"
      - label: "QuillDrop"
        url: "/sites/projekte/quilldrop"
  - label: "Über mich"
    url: "/sites/ueber-mich"
  - label: "Tags"
    url: "/tags"

Neue Menüpunkte und Untermenüs können jederzeit durch einfaches Erweitern der YAML-Konfiguration hinzugefügt werden.

Pagination

Die Startseite zeigt eine konfigurierbare Anzahl von Posts pro Seite (Standard: 5). Die Pagination bietet:

  • Intelligente Seitennummerierung - Zeigt erste und letzte Seite, plus ein Fenster um die aktuelle Seite herum
  • Ellipsis bei vielen Seiten (1 ... 10 11 12 13 14 ... 23)
  • Neuere/Ältere Buttons für schnelle Navigation
  • Pretty URLs - /page/2, /page/3, etc.
  • SEO-freundlich: /page/1 wird automatisch auf / umgeleitet (301)

Tags und Kategorien

QuillDrop unterstützt sowohl Tags als auch Kategorien zur Strukturierung von Inhalten:

  • Tag-Übersicht unter /tags/ mit Anzahl der Posts pro Tag
  • Tag-Seiten unter /tags/kubernetes/ mit allen Posts eines Tags
  • Kategorie-Übersicht unter /categories/ mit Anzahl der Posts pro Kategorie
  • Kategorie-Seiten unter /categories/technik/ mit allen Posts einer Kategorie
  • Tag- und Kategorie-Badges auf Post-Cards und Einzelseiten
  • Tags und Kategorien werden aus dem YAML-Frontmatter (tags, categories) ausgelesen

Volltextsuche

QuillDrop enthält eine integrierte Client-seitige Suche, die komplett ohne Backend auskommt:

  • Suchindex — Beim Generieren wird eine search-index.json mit allen Posts erstellt
  • Lazy Loading — Der Suchindex wird erst beim ersten Öffnen der Suche geladen
  • Multi-Term-Suche — Mehrere Suchbegriffe werden mit UND verknüpft
  • Felder — Durchsucht Titel, Vorschau, Tags und Kategorien
  • Keyboard-ShortcutCtrl+K / Cmd+K öffnet die Suche
  • Lupe in der Navbar — Klick auf das Such-Icon öffnet das Suchfeld
  • Debounce — Suchergebnisse erscheinen nach 200ms Tippverzögerung
  • Maximal 8 Treffer mit Highlighting der Suchbegriffe
  • Escape oder Klick außerhalb schließt die Suche
  • Kein externer Dienst, kein Framework — reines Vanilla JavaScript

Artikel-Navigation

Am Ende jedes Blog-Posts wird eine Navigation zum vorherigen und nächsten Artikel angezeigt:

  • Neuerer Artikel (← links) — Verlinkt zum chronologisch neueren Post
  • Älterer Artikel (→ rechts) — Verlinkt zum chronologisch älteren Post
  • Beim neuesten Artikel wird nur "Älterer Artikel" angezeigt
  • Beim ältesten Artikel wird nur "Neuerer Artikel" angezeigt
  • Zeigt jeweils den Titel des verlinkten Artikels an

Inhaltsverzeichnis (Table of Contents)

Posts können ein automatisch generiertes Inhaltsverzeichnis aktivieren:

  • Aktivierung über toc: true im Frontmatter
  • Unterstützt H1, H2 und H3 Überschriften
  • Relative Einrückung — Das TOC erkennt die minimale Heading-Ebene und rückt relativ dazu ein
  • Automatische Anchor-Links zu den jeweiligen Überschriften
  • Wird client-seitig generiert für schnelle Seitenladezeit

Statische Seiten

Neben Blog-Posts unterstützt QuillDrop statische Seiten für:

  • Impressum, Datenschutzerklärung
  • Über mich / About
  • Projektseiten (mit Unterseiten)
  • Beliebige weitere Seiten

Seiten werden als Markdown-Dateien im sites/-Verzeichnis abgelegt. Verschachtelte Verzeichnisse werden automatisch erkannt - z.B. wird sites/projekte/vm-tracker/index.md unter /sites/projekte/vm-tracker erreichbar.

RSS Feed

Automatisch generierter RSS 2.0 Feed unter /index.xml mit:

  • Den letzten 20 Posts
  • Titel, Link, Vorschau und Veröffentlichungsdatum
  • RSS-Autodiscovery im HTML-Head
  • RSS-Icon in der Navigation
  • URL /index.xml für Kompatibilität mit bestehenden Blog-Setups

Sitemap

Parallel zum RSS-Feed wird eine sitemap.xml nach dem sitemaps.org-Protokoll 0.9 erzeugt - unter /sitemap.xml sowohl im dynamischen Server als auch in der statischen Generierung. Enthalten sind:

  • Startseite und alle Pagination-Seiten (/page/2/, ...)
  • Alle Blog-Posts (lastmod aus update, sonst date)
  • Alle statischen Seiten aus sites/
  • Tag- und Kategorie-Übersichten sowie alle einzelnen Tag-/Kategorie-Seiten

Die Sitemap lässt sich in der Config an- und abschalten (Default: aktiv):

sitemap:
  enabled: true   # false schaltet /sitemap.xml komplett ab

robots.txt

Ebenfalls automatisch erzeugt: eine robots.txt unter /robots.txt. Sie verweist automatisch auf die Sitemap, sobald diese aktiviert ist, und lässt sich in der Config konfigurieren (Default: aktiv):

robots:
  enabled: true
  userAgent: "*"        # optional, Default "*"
  disallow:             # optional
    - /search-index.json
  allow:                # optional
    - /

Ohne eigene allow/disallow-Regeln wird Allow: / geschrieben, d.h. die ganze Seite ist freigegeben:

User-agent: *
Allow: /

Sitemap: https://blog.kuepper.nrw/sitemap.xml

Ist sitemap.enabled: false oder baseURL leer, entfällt die Sitemap:-Zeile.

Cover-Bilder

Posts können ein Cover-Bild definieren, das sowohl auf der Startseite (als Post-Card) als auch auf der Einzelansicht angezeigt wird:

  • 21:9 Aspect Ratio auf Post-Cards mit Zoom-on-Hover Effekt
  • Volle Breite auf der Einzelpost-Seite
  • Lazy Loading für optimale Performance
  • Fallback von cover auf featureImage

Architektur

Projektstruktur

quilldrop/
├── main.go                          # CLI Entry Point
├── config.yaml                      # Konfiguration
├── content/                         # Blog-Posts (Markdown)
│   ├── 2025-11-06-mein-post.md
│   └── ...
├── sites/                           # Statische Seiten
│   ├── ueber-mich.md
│   ├── impressum.md
│   └── projekte/
│       └── mein-projekt/
│           └── index.md
├── static/                          # Seiten-Assets (Icons, Bilder, ...)
│   ├── icons/
│   └── images/
├── themes/                          # Themes — ein Verzeichnis je Theme
│   └── default/
│       ├── templates/
│       │   ├── base.html            # Base Layout + Navbar + Suche
│       │   ├── home.html            # Homepage + Pagination
│       │   ├── post.html            # Einzelner Post + Prev/Next Navigation
│       │   ├── page.html            # Statische Seite
│       │   ├── tags.html            # Tag-Übersicht
│       │   ├── tag.html             # Tag-Seite
│       │   ├── categories.html      # Kategorie-Übersicht
│       │   └── category.html        # Kategorie-Seite
│       └── static/                  # Theme-Assets (werden nach /static/ gemerged)
│           ├── css/style.css
│           └── js/
│               ├── theme.js         # Dark/Light Toggle + TOC Generator
│               └── search.js        # Client-seitige Volltextsuche
├── internal/
│   ├── config/config.go             # YAML Config Loader
│   ├── content/
│   │   ├── post.go                  # Post Struct + FlexTime + Tags/Categories
│   │   ├── parser.go                # Markdown + Frontmatter Parser
│   │   └── page.go                  # Statische Seiten Parser
│   ├── server/server.go             # HTTP Server
│   ├── generator/
│   │   ├── generator.go             # Static Site Generator
│   │   ├── robots.go                # robots.txt Generator
│   │   └── search.go                # Search-Index Generator (JSON)
│   └── templates/
│       ├── render.go                # Template Engine + Functions (lädt das Theme)
│       ├── rss.go                   # RSS Feed Generator
│       └── sitemap.go               # sitemap.xml Generator
└── output/                          # Generierte statische Dateien

Technologie-Stack

KomponenteTechnologie
SpracheGo (Standard Library + minimale Dependencies)
HTTP Servernet/http (Go Standard Library)
Templateshtml/template, zur Laufzeit aus themes/<name>/templates/ geladen
MarkdownGoldmark + GFM + Emoji + Chroma
KonfigurationYAML via gopkg.in/yaml.v3
Syntax HighlightingChroma (Dracula Theme)
FontsInter + JetBrains Mono (Google Fonts)
CSSVanilla CSS mit Custom Properties
JavaScriptVanilla JS — Theme Toggle, Suche, TOC (kein Framework)

Dependencies

QuillDrop hat bewusst minimale Abhängigkeiten - kein Web-Framework, kein CSS-Framework, kein JS-Framework:

  • github.com/yuin/goldmark - Markdown Parser (CommonMark-konform)
  • github.com/yuin/goldmark-emoji - Emoji Shortcodes
  • github.com/yuin/goldmark-highlighting/v2 - Syntax Highlighting
  • github.com/alecthomas/chroma/v2 - Syntax Highlighting Engine
  • gopkg.in/yaml.v3 - YAML Parser

Themes

Templates und deren Assets liegen ausserhalb des Binaries in themes/<name>/. Dadurch
kann dasselbe QuillDrop-Binary beliebig viele Websites bedienen, jede mit eigenem Design:

themes/
├── default/
│   ├── templates/       # Pflicht: base, home, post, page, tags, tag, categories, category
│   └── static/          # Optional: CSS, JS, Theme-Bilder
└── newdesign/
    ├── templates/
    └── static/

Das aktive Theme wird in der config.yaml gewählt:

themesDir: "themes"   # Default
theme: "default"      # liest aus themes/default/

Oder temporär per Flag, z. B. um ein Redesign zu testen:

./quilldrop serve -theme newdesign
./quilldrop generate -theme newdesign

Neues Theme anlegen:

cp -r themes/default themes/newdesign      # oder: make new-theme NAME=newdesign
# themes/newdesign/templates/*.html und themes/newdesign/static/css/style.css anpassen
./quilldrop serve -theme newdesign -dev

Live-Reload: Mit -dev werden die Templates bei jedem Request neu aus dem
Theme-Verzeichnis gelesen — Änderungen an HTML, CSS und JS sind nach einem
Browser-Reload sichtbar, ohne den Server neu zu starten (im Dev-Modus wird
zusätzlich Cache-Control: no-store gesetzt, damit der Browser nichts
zwischenspeichert). Ein fehlerhaftes Template liefert eine 500 statt einer halb
gerenderten Seite; die genaue Fehlermeldung mit Datei und Zeile steht im
Server-Log. Ohne -dev werden die Templates wie bisher einmal beim Start
geparst. Neue oder geänderte Markdown-Dateien erfordern weiterhin einen Neustart.

Ein Theme muss alle acht Templates enthalten (base.html, home.html, post.html,
page.html, tags.html, tag.html, categories.html, category.html);
fehlt eines oder existiert das Theme nicht, bricht QuillDrop mit einer klaren
Fehlermeldung ab.

Statische Assets werden gemerged: zuerst themes/<name>/static/, danach das
eigene static/ der Seite — gleichnamige Dateien der Seite gewinnen also
(z. B. static/icons/favicon.ico). Das Design gehört ins Theme (CSS, JS),
seitenspezifisches Material bleibt in static/ (Icons, Bilder). Beides wird unter
/static/ ausgeliefert; static/images/ und static/videos/ zusätzlich unter
/images/ und /videos/.

Konfiguration

Die gesamte Konfiguration erfolgt über eine einzige config.yaml:

title: "Mein Blog"
description: "Tech Blog - DevOps, Kubernetes, Self-Hosted"
author: "Max Mustermann"
baseURL: "https://mein-blog.de"
port: 8080
postsPerPage: 5
contentDir: "content"
sitesDir: "sites"
staticDir: "static"
outputDir: "output"
themesDir: "themes"
theme: "default"

menu:
  - label: "Home"
    url: "/"
  - label: "Tags"
    url: "/tags"
  - label: "Über mich"
    url: "/sites/ueber-mich"
OptionDefaultBeschreibung
title-Titel der Website
description-Beschreibung (Meta-Tag + Hero)
author-Autor der Website
baseURL-Basis-URL für RSS, Sitemap und absolute Links
port8080Port für den dynamischen Server
postsPerPage5Anzahl Posts pro Seite
contentDircontentVerzeichnis für Blog-Posts
sitesDirsitesVerzeichnis für statische Seiten
staticDirstaticVerzeichnis für Seiten-Assets
outputDiroutputAusgabeverzeichnis für statische Generierung
themesDirthemesVerzeichnis mit allen Themes
themedefaultAktives Theme, gelesen aus <themesDir>/<theme>/ (Override: -theme)
menu[]Navigationsmenü mit optionalen Untermenüs
sitemap.enabledtrueErzeugt/serviert /sitemap.xml
robots.enabledtrueErzeugt/serviert /robots.txt (mit Sitemap-Verweis)
robots.userAgent*User-agent-Zeile in der robots.txt
robots.allow[]Zusätzliche Allow:-Regeln
robots.disallow[]Zusätzliche Disallow:-Regeln

Schnellstart

Installation

# Repository klonen
git clone https://github.com/ruedigerp/quilldrop.git
cd quilldrop

# Dependencies laden
go mod download

# Binary bauen
go build -o quilldrop .

Neuen Post erstellen

Eine neue Markdown-Datei im content/-Verzeichnis anlegen:

touch content/2025-12-01-mein-erster-post.md
---
title: "Mein erster Post"
date: 2025-12-01 10:00:00
author: "Max Mustermann"
tags: [Blog, QuillDrop]
preview: "Das ist mein erster Post mit QuillDrop!"
toc: false
---

# Willkommen

Das ist mein erster Post mit **QuillDrop**.

Lokale Vorschau

# Dynamischen Server starten
./quilldrop serve

# Oder direkt mit Go
go run . serve

# Mit Live-Reload für Templates (Theme-Entwicklung)
./quilldrop serve -dev

Dann im Browser: http://localhost:8080

Statische Seite generieren

# HTML-Dateien generieren
./quilldrop generate

# Generierte Dateien befinden sich in output/
ls output/

Die generierten Dateien im output/-Verzeichnis können direkt auf einen Webserver (Nginx, Apache, Caddy) oder CDN deployed werden.

URL-Schema

Alle URLs verwenden konsequent Trailing Slashes, um serverseitige Redirects zu vermeiden:

URLBeschreibung
/Startseite (letzte N Posts)
/page/2/Seite 2 der Post-Liste
/posts/2025-11-06-mein-post/Einzelner Blog-Post
/tags/Tag-Übersicht
/tags/kubernetes/Posts mit Tag "Kubernetes"
/categories/Kategorie-Übersicht
/categories/technik/Posts in Kategorie "Technik"
/sites/ueber-mich/Statische Seite
/sites/projekte/vm-tracker/Verschachtelte Projektseite
/index.xmlRSS Feed
/sitemap.xmlSitemap für Suchmaschinen (falls aktiviert)
/robots.txtCrawler-Regeln + Sitemap-Verweis (falls aktiviert)
/search-index.jsonSuchindex (JSON)
/static/css/style.cssStatische Assets
/images/posts/2025/11/cover.webpBilder

Warum QuillDrop?

  • Keine Datenbank - Dateisystem als einzige Datenquelle
  • Keine Build-Pipeline - Ein go build und fertig
  • Keine JS-Frameworks - Vanilla JavaScript für Theme, Suche und TOC
  • Minimale Dependencies - 5 Go-Packages, alle fokussiert auf Markdown
  • Blitzschnell - Generiert 100+ Posts in unter 3 Sekunden
  • Einzelnes Binary - Templates eingebettet, kein Runtime-Setup
  • Hugo-kompatibel - Bestehende Hugo-Posts mit Frontmatter funktionieren
  • Dual-Mode - Entwicklung mit Server, Produktion mit Static Generator

Lizenz

QuillDrop ist Open Source.