Moin moin und hallo,

wilkommen zu meinem ersten Artikel nach meinem zweiten größeren Relaunch meines Blogs.
Das alte Design hat mich nicht mehr so richtig zufrieden gestellt und außerdem wollte ich einen “neuen” Trend ausprobieren, nämlich “Flat File CMS”.


Wie der Name es schon ein wenig andeutet, wird bei einem solchen CMS der Inhalt nicht in einer Datenbank vorgehalten, sondern in Form von einfachen Dateien. Das hat natürlich so seine Vor- als auch Nachteile gegenüber herkömmlichen Systemen wie Wordpress oder Typo3:

Vorteile

  • Einfaches offline Management der Inhalte
  • bessere Performanz
  • kann in jedem Web-Container eingespielt werden
  • Revision aller Inhalte per z.B. Git
  • Striktere Trennung von Templates und Inhalten
  • Fokus auf statische Inhalte

Nachteile

  • Für das Schreiben der Markdown Inhalte muss ein lokaler Texteditor verwendet werden
  • Inhalte müssen gebaut und in einen Web-Container hochgeladen werden
  • an Stelle eines WYSIWYG-Editors arbeitet man in der Regel mit Markdowns
  • Authoren und Redaktion nicht ohne weiteres von einander, durch z.B. Berechtigungen, trennbar
  • Funktionalitäten, die eine Session benötigen, z.B. Warenkorb-Systeme, sind nur mit Hilfe anderer Dienste umsetzbar

Ziel

Was möchte ich denn eigentlich mit einem Flat-File CMS ?
Die Abwägung der Vorteile zu Nachteilen hat mich schlussendlich dazu bewegt meinen Blog um zu strukturieren.
Denn die meisten vermeidlichen Nachteile lassen sich mit heutigen Web-Technologien (z.B. Micro-Services) beseitigen und die Vorteile aber bleiben. Mein Ziel ist also mit Hifle eines Selbstexperiments fest zu stellen, ob man ernsthafte Webseiten mit einem Flat-File CMS betreiben und Web-Applikationen integrieren kann.
Ich habe dabei einpaar Ideen, wie ich meinen Blog um z.B. eine E-Learning Applikation erweitern kann, dazu aber in einem späteren Artikel mehr.

Flat-File CMS Wintersmith

Das System für das ich mich entshcieden habe nennt sich Wintersmith.
Es baut auf ein Technologien auf, die ich bereits in anderen Projekten mit Sails JS erfoglreich einsetzen konnte und entsprechend zuversichtlich bin, dass alles so funktioneirt, wie ich es mir vorstelle:

Ich erlaube es mir mal die original Dokumentation zu zitieren und die Projektstruktur einer Wintersmith Webseite zu beschreiben:

├── config.json               <- site configuration
├── contents
│   ├── about.md
│   ├── archive.json
│   ├── articles              <– each article has its own directory
│   │   ├── another-test
│   │   │   └── index.md
│   │   ├── bamboo-cutter
│   │   │   ├── index.md
│   │   │   └── taketori_monogatari.jpg
│   │   ├── hello-world
│   │   │   └── index.md
│   │   ├── markdown-syntax
│   │   │   └── index.md
│   │   └── red-herring
│   │       ├── banana.png
│   │       └── index.md
│   ├── authors               <- author metadata, check author.pug
│   │   ├── baker.json
│   │   └── the-wintersmith.json
│   ├── css
│   │   └── main.css
│   └── feed.json
├── plugins
│   └── paginator.coffee      <- paginator plugin
├── templates
│   ├── archive.pug
│   ├── article.pug
│   ├── author.pug
│   ├── feed.pug
│   ├── index.pug
│   └── layout.pug
└── views
    └── articles.coffee       <- view that lists articles

Templates

Wie aus der Projektstruktur schon ersichtlich ist, sind die Templates alle unter “/templates” an zu legen. Jede Seite kann ein eigenes Layout definieren, oder ein bestehendes nutzen. Dabei steht einem alles zur Verfügung was Jade bereits stellt, plus zusätzliche Infromationen, die Wintersmith integriert, z.B. Zugriff auf alle Dateien im “contents” Verzeichnis.

Beispiel layout.pug

doctype html
block vars
  - var bodyclass = null;
html(lang='en')
  head
    block head
      meta(charset='utf-8')
      meta(http-equiv='X-UA-Compatible', content='IE=edge,chrome=1')
      meta(name='viewport', content='width=device-width')
      title
        block title
          = locals.name
      link(rel='alternate', href=locals.url+'/feed.xml', type='application/rss+xml', title=locals.description)
      link(rel='stylesheet', href='http://fonts.googleapis.com/css?family=Lora:400,700,400italic,700italic|Anonymous+Pro:400,700,400italic,700italic|Merriweather:400,700,300')

      link(rel='stylesheet', href=contents['bootstrap-3.3.6-dist'].css['bootstrap.min.css'].url)
      link(rel='stylesheet', href=contents.styles['animate.css'].url)
      link(rel='stylesheet', href=contents.styles['theme-superhero.min.css'].url)
      link(rel='stylesheet', href=contents.styles['page.less'].url)

      script(src=contents['bootstrap-3.3.6-dist'].js['jquery-2.2.4.min.js'].url)
      script(src=contents['bootstrap-3.3.6-dist'].js['bootstrap.min.js'].url)

  body(class=bodyclass)

    header.jumbotron

      .container
        div.logo
          block header
            h1
              a(href=locals.url)= locals.name
            p.description= locals.description
      include ./_top-navigation.pug


    div#content
      block full-width-content
      .container
        block content

    .container
        block bottom-navigation

    footer.well
      .container
        block footer
          section.about
            !=contents['about.md'].html
          section.copy
            p &copy; #{ new Date().getFullYear() } #{ locals.owner }

Inhalte werden dabei in Form von Markdown Dateien gepflegt und direkt als HTML eingebunden:

section.about
    !=contents['about.md'].html

Eine Markdown Datei sieht z.B. dann wie folgt aus:

---
title: About me
author: roman-fetsch
date: 2016-06-21 15:00
template: about-me.pug
---

# Über mich

![Mein Foto](/images/me.jpg)

Ich entwickele seit 2006 beruflich Software, mit dem Schwerpunkt auf Web-Applikationen und mobile Lösungen…und liebe es!

Software Engineer bei der CSE GmbH, Gründer und Geschäftsführer der Firma Q2B GmbH

Außerdem bin ich jetzt auch eine Webseite: [roman-fetsch.de](http://roman-fetsch.de "Title") 

Und bei Twitter: [rofetsch](https://twitter.com/rofetsch)

Das alle Blog-Artikel in dem “/articles”-Verzeichnis liegen und jeder ein eigenes Verzeichnis mit einer “index.md” und den Artikel-bezogenen Assets hat, ist eine Konvention die man für den Default Einsatz getroffen hat.
Diese Konvention lässt sich aber ohne weiteres ändern, da sämtlicher Jade Code und die zusätzlichen Konfigurationen im JSON Format vorliegen.
Ich persönlich finde aber diese Konvention als sehr hilfreich und möchte mich dabei bleiben.

In der ‘config.json’ schlussendlich ist nichts unerwartetes zu finden. Nur die Konfiguration, die Wintersmith zum Arbeiten braucht, wie z.B. Wintersmith-Plugins und externe Bibliotheken:

config.json

{
  "locals": {
    "url": "http://localhost:8080",
    "name": "Software Kraut",
    "owner": "Roman Fetsch",
    "description": "Software Engineering for fun and living."
  },
  "plugins": [
    "wintersmith-less",
    "./plugins/paginator.coffee"
  ],
  "require": {
    "moment": "moment",
    "_": "underscore",
    "typogr": "typogr"
  },
  "pug": {
    "pretty": true
  },
  "markdown": {
    "smartLists": true,
    "smartypants": true
  },
  "paginator": {
    "perPage": 3
  }
}

Die Konfiguration musste ich bisher auch nur einmal zu Projektbeginn ändern. Die Installation aller Plugins erfoglt nämlich per Wintersmith CLI:

~$> wintersmith plugin install wintersmith-less

Fazit

Am Ende der langen Reise wird aus dem Template und dem Content eine HTML Datei erzeugt: Die Konfiguration musste ich bisher auch nur einmal zu Projektbeginn ändern. Die Installation aller Plugins erfoglt nämlich per Wintersmith CLI:

~$> wintersmith build

Dazu wird ein eigenes “/build” Verzeichnis angelegt in dem auch alle Web-Ressourcen zu finden sind.

Build Verzeichnis

Meine Erfahrung bisher war, dass man schon noch etwas Zeit investieren muss um das Gesamsystem sauber auf zu setzen (Keywords, Plugins, Seitenstruktur, Automatisierung Deployment-Prozess, usw.). Dannach aber die eigentliche Autoren-Arbeit, mit Hilfe von Markdown, sehr einfach von der Hand geht. Der Fokus liegt, wie gewünscht nur noch auf den Schreibprozess und nicht etwaige Formatierungen.

Eine weitere Möglichkeit Wintersmith zu nutzen wäre z.B. zur Erzeugung von Code, sprich einer modelgetriebenen Software-Entwicklung. Dieses möchte ich aber in einem anderen Artikel evaluieren.

Meinen alten Blog gibt es übrigens noch eine Zeitlang hier zu finden.


#### In diesem Sinne, bis demnächst!