À la recherche d'un moteur de blog pour ce site, je m'étais fixé les caractéristiques suivantes :

  • Administration minimale
  • Style modifiable
  • Simple
  • Gratuit
  • Avec mon nom de domaine
  • Pas de publicité
  • Contenu ré-utilisable
  • URL arbitraires
  • Power-user

Rien que ça... Mais j'étais prêt à faire une concession de taille : une solution technique ne me rebute pas, du moment qu'elle reste simple.

Plateformes classiques

Blogger

Premier essai : la vieillissante plateforme Blogger, reprise par Google. Pas convaincu :

  • Les thèmes proposés sont un peu passés de mode
  • La prévisulation n'aboutit pas avec certains thèmes (ceux qui ont justement l'air moins vieux)
  • Système de commentaires G+ peu pratique
  • Contenu exporté souillé par de nombreuses balises HTML

Wordpress.com

C'est la version "cloud" de Wordpress. Une Rolls disponible en ligne, mais...

  • URL partiellement figées (avec la date dedans)
  • Thèmes gratuits limités et peu ou pas configurables
  • Nom de domaine propre en supplément
  • Publicité possible sur la version gratuite.

Les prix ne sont pas excessifs et c'est certainement une excellente solution si vous voulez une solution clé en main. Prenez la version payante, ajoutez votre nom de domaine en supplément et achetez un des nombreux thèmes du catalogue.

Trop facile :-)

Pourquoi ne pas installer WP sur mon serveur ? Parce que c'est une pièce d'infrastructure de plus à administrer. Base de données, mises à jour de sécurité du blog... Idéalement en double : sur ma machine comme environnement de développement et sur mon serveur en production. À terme, migration majeure à prévoir.

Un peu trop pour l'usage basique que j'en fais. Sans doute mon expérience avec DotClear (du temps ou il faisait jeu égal avec Wordpress) m'a refroidi.

JBake + GitHub Pages + Disqus

Mon choix s'est porté sur un combo qui pour l'instant me plaît bien :

JBake

Image JBake

JBake is a Java based open source static site/blog generator for developers.

Le descriptif est un peu trompeur : il n'est pas nécessaire d'être développeur. Il suffit d'avoir Java 6 (ou plus récent) installé et d'être prêt à adapter quelques fichiers de templates avant de générer un site statique. Certainement pas pour le grand public mais si vous avez un quelques connaissances techniques, c'est à mon sens moins compliqué que d'installer un DotClear / Wordpress sur un hébérgement mutualisé.

Le thème de base, plutôt moche, est basé sur la précédente version de Bootstrap. À vous de faire (un peu) mieux, par exemple en vous inspirant de Bootswatch et en adaptant les templates JBake ou en recommençant from scratch.

Incorporer un thème bootswatch n'est pas aussi commode qu'on le voudrait, car il faut alors mixer l'existant de JBake et le thème bootswatch. Il est sans doute plus simple de repartir d'un thème bootswatch et d'en dériver les templates que de tenter de faire correspondre des morceaux bootswatch avec ceux de JBake (surtout quand les versions ne correspondent pas).

Les templates sont en Freemarker. Rien de bien sorcier, par exemple pour lister vos posts sur la page d'accueil :

<#list posts as post>
    <#if (post.status == "published")>



${post.title}




${post.date?string("dd MMMM yyyy")}


${post.body}



</#if>
</#list>

Le contenu peut être formaté en AsciiDoc, Markdown et HTML, ce qui est bien pratique. Vous éditez donc vos billets localement, avec l'éditeur de votre choix. La seule contrainte concerne les headers de chaque billet. JBake en a besoin pour générer l'output statique.

title=Blogguer sous GitHub avec JBake
date=2014-01-29
type=post
tags=blog, blogger, github.io, jbake, wordpress
status=published
~~~~~~

La page que vous être en train de lire est le résultat après génération du contenu statique.

Un billet peut être mode draft. Cela veut dire qu'il n'apparaîtra pas dans la liste des billets, mais il sera malgré tout accessible directement par une URL non publiée :

http://blog.ackx.net/blogguer-sous-github-avec-jbake-draft.html

La structure de vos billets est libre. Autrement dit, vous pouvez les classer par année, par mois, par catégorie, ou... pas du tout! Cette structure se retrouve dans l'URL du billet. Par exemple, la structure suivante :

+ content
    + blog
        + 2013
            + foo.md
            + bar.md

Sera traduite par les URL suivantes :

 http://votre.site/blog/2013/foo.html
 http://votre.site/blog/2013/bar.html

Si par contre vous ne souhaitez pas faire apparaître d'information de date ou de catégorie dans les URI, comme c'est le cas sur ce blog, placez simplement tout le contenu directement dans le répertoire content.

 + content
    + blogguer-sous-github-avec-jbake.md
    + the-matrix-animation-html5.md

Qui donne ici :

http://blog.ackx.net/blogguer-sous-github-avec-jbake.html
http://blog.ackx.net/the-matrix-animation-html5.html

J'aime ! Quand votre contenu est prêt, vous générez le site statique (en supposant que jbake est dans votre PATH) :

youri@gyros blog.ackx.net> jbake
JBake v2.2.0 (2013-10-23 22:24) [http://jbake.org]
Baking has started...
Processing [./content/about.html]... done!
Processing [./content/automatisez-avec-cuisine.md]... done!
...
Rendering [output/about.html]... done!
Rendering [output/blogguer-sous-github-avec-jbake-draft.html]... done!
...
Copying [./assets/css/asciidoctor.css]... done!
Copying [./assets/css/bootstrap.min.css]... done!
...
...finished!
Baked 16 items in 3325ms

De l'ordre de 3-4 secondes pour générer quelques pages : on peut considérer cela comme très lent. Votre contenu est prêt à être servi dans le répertoire output. Localement, n'importe quel serveur fera l'affaire mais vous pouvez utiliser directement JBake et y accéder via http://localhost:8820/ :

youri@gyros blog.ackx.net> jbake-s

Note : si vous préférez les gems aux pom.xml, Jekyll est l'approche proposée par GitHub.

font-awesome

Une petite ligne qui change pas mal de choses...

    <link href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css" rel="stylesheet">

Et vous avez accès à des pictogrammes awesome.

GitHub Pages

Image JBake

Votre site statique en HTML est généré, fort bien; et maintenant, où le déployer ? N'importe quel serveur HTML fera l'affaire. J'aurais aisément pu utiliser mon instance Amazon EC2 micro et profiter d'une de mes recettes Cuisine pour FabricSSH pour déployer tout cela facilement.

Mais un petit git push est une idée sympathique… Enter GitHub Pages ! Suivez les instructions en les adaptant à notre approche JBake qui génère ses artifacts dans output.

C'est facile

  1. Créez un repo publique username.github.io. Pour ce blog, YouriAckx.github.io.
  2. À la racine de votre projet JBake, clonez le repo : git clone https://github.com/username/username.github.io
  3. Renomez username.github.io en output. À présent, le produit de jbake est "lié" à votre blog GitHub.
  4. Lancez la cuisson de votre blog : jbake
  5. Commit des changements
  6. Push vers GitHub : git push
  7. Admirez le résultat en ligne à l'adresse http://username.github.io (il faut qq minutes de patience après le premier push)

Honnêtement, compte tenu du fait que j'ai déjà un serveur Ubuntu en place, j'aurais tout aussi bien pu me contenter d'un tar/gzip/scp et le tour était joué, mais c'était l'occasion d'essayer la version GitHub du blogging. Cela reste bien pratique si vous n'avez aucune infrastructure à votre disposition.

Votre nom de domaine

Vous pouvez associer votre nom de domaine à votre blog GitHub Pages.

  1. Pour faire pointer un sous-domaine vers votre blog, ajoutez un record CNAME vers username.github.io. Cela se passe chez votre fournisseur (GoDaddy, OVH, …)

    youri@gyros blog.ackx.net> dig blog.ackx.net +nostats +nocomments +nocmd
    ;blog.ackx.net.        IN    A
    blog.ackx.net.   21561   IN    CNAME  youriackx.github.io.
    
  2. À la racine de votre repo (dans notre setup, elle coïncide avec le répertoire output de JBake), ajoutez un fichier CNAME qui reprend votre sous-domaine

    youri@gyros blog.ackx.net> cat output/CNAME
    blog.ackx.netyouri
    
  3. Commit + Push

C'est également possible avec un apex; voyez la page d'aide à ce sujet.

Avantages et inconvénients

Petits plus : avec GitHub, vous bénéficiez de leur Content Delivery Network ainsi que de leur protection contre les attaques de déni de service.

Petit moins : tout ce que vous poussez vers GitHub reste gravé dans la pierre des internets. Si vos deviez retirer un contenu litigieux ou gênant, n'importe qui pourrait encore y accéder via l'historique du repo…

Disqus

Image JBake

Ah, les commentaires ! Disqus donne le ton en la matière et pas uniquement pour les sites statiques. Certains sites de taille respectable leur délèguent la gestion des commenentaires pour ne pas avoir à en supporter la charge.

Il est paradoxal pour moi d'utiliser Disqus alors que je le bloque avec Ghostery…. Mais je fais pareil avec Google Analytics, bloqué chez moi mais déployé sur la plupart des sites que je gère. La contradiction n'est qu'apparente : si la plupart des gens ne prennent pas la peine de les bloquer et/ou que cela ne les dérange pas, il n'y a pas de raison de se passer de ces services.

Ouvrez un compte Disqus et suivez les instructions pour l'installation.

Dans JBake, vous devrez modifier post.ftl pour les commentaires sur chaque page et index.ftl ainsi que footer.ftl si vous souhaitez renseigner un compteur de comm' pour chaque post.

Variables JBake

Pour éviter de vous répéter et d'harcoder des valeurs dans vos templates, ajoutez deux variables au fichier jbake.properties (yourshortname est le nom de votre blog sur Disqus) et n'oubliez pas d'adapter le host :

site.host=http://mon.boblog.com
disqus.no.comments=0 Comments
disqus.username=yourshortname

Commentaires sur les pages

Dans post.ftl, ajoutez une ligne à l'endroit où doivent apparaitre les commentaires :

<div id="disqus_thread"></div>

Et un peu de javascript, tel que proposé sur la page d'installation Disqus et remis à la sauce JBake :

<script type="text/javascript">
var disqus_shortname = '${config.disqus_username}'; // Required - Replace example with your forum shortname
var disqus_identifier = '${content.uri}';
var disqus_title = "${content.title}";
var disqus_url = '${config.site_host}${content.uri}';

/* * * DON'T EDIT BELOW THIS LINE * * */
(function() {
    var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
    dsq.src = '//' + disqus_shortname + '.disqus.com/embed.js';
    (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
})();
</script>

<noscript>
    Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a>
</noscript>

content.uri et content.title sont pré-définis dans JBake. config.site_host est la variable site.host définie plus haut (remarquez que le . est devenu _ et qu'elle est préfixée par config). En pratique, ça donne quelque chose comme ça :

content.uri = /blog/2014/un-bo-post.html
content.title = Un bô post
config.site_host = http://mon.boblog.com
config.disqus_username = yourshortname

Compteur sur la page d'accueil

Même principe. Plaçons le javascript dans footer.ftl :

<script type="text/javascript">
var disqus_shortname = '${config.disqus_username}'; // required: replace example with your forum shortname

/* * * DON'T EDIT BELOW THIS LINE * * */
(function () {
var s = document.createElement('script'); s.async = true;
s.type = 'text/javascript';
s.src = 'http://' + disqus_shortname + '.disqus.com/count.js';
(document.getElementsByTagName('HEAD')[0] || document.getElementsByTagName('BODY')[0]).appendChild(s);
}());
</script>

Et le compteur vient se loger dans index.ftl

<a href="${post.uri}#disqus_thread" data-disqus-identifier="${post.uri}">${config.disqus_no_comments}</a>

Remarquez que j'identifie le post via l'attribut data-disqus-identifier.

Commit+Push et le tour est joué.

Réglages

Sur votre page d'administration Disqus, vous pouvez choisir la modération des commenentaires ou pas, obliger à s'identifier avec de commenter, etc.

Your data are belong to us

Bien entendu, gardez à l'esprit que vous confiez une partie de votre contenu à un tiers, avec toutes les questions que cela entraîne en cas de fermeture ou plus vraissemblement de dégradation ou de modification tarifaire du service à terme.

Bonus

Le template complet de ce blog est disponible sous GitHub.

Source