diff --git a/.project.el.gpg b/.project.el.gpg
deleted file mode 100644
index c7f837c..0000000
Binary files a/.project.el.gpg and /dev/null differ
diff --git a/project.el b/project.el
new file mode 100644
index 0000000..39587b6
--- /dev/null
+++ b/project.el
@@ -0,0 +1,270 @@
+(setq domainname "https://her.esy.fun")
+(setq base-dir (concat (projectile-project-root) "src"))
+(setq publish-dir (concat (projectile-project-root) "_site"))
+(setq assets-dir (concat base-dir "/"))
+(setq publish-assets-dir (concat publish-dir "/"))
+(setq rss-dir base-dir)
+(setq rss-title "Subscribe to articles")
+(setq publish-rss-dir publish-dir)
+(setq css-path "/css/minimalist.css")
+(setq author-name "Yann Esposito")
+(setq author-email "yann@esposito.host")
+
+(require 'org)
+(require 'ox-publish)
+(require 'ox-html)
+(require 'org-element)
+(require 'ox-rss)
+
+(setq org-link-file-path-type 'relative)
+(setq org-publish-timestamp-directory
+ (concat (projectile-project-root) "_cache/"))
+
+(defvar org-blog-head
+ (concat
+ ""
+ ""
+ ""
+ ""))
+
+(defun menu (lst)
+ "Blog menu"
+ (concat
+ ""
+ (mapconcat 'identity
+ (append
+ '("Home"
+ "Posts"
+ "About")
+ lst)
+ " | ")
+ ""))
+
+
+(defun str-time-to-year-float (date-str)
+ (/ (float-time
+ (apply 'encode-time
+ (mapcar (lambda (x) (if (null x) 0 x))
+ (parse-time-string date-str))))
+ (* 365.25 24 60 60)))
+
+(defvar blog-creation-date "2019-07-01")
+
+(defun y-date (date-str)
+ "Number of year since the begining of this blog"
+ (let ((y (- (str-time-to-year-float date-str)
+ (str-time-to-year-float blog-creation-date))))
+ (format "∆t=%.2f" y)))
+
+(defun get-from-info (info k)
+ (let ((i (car (plist-get info k))))
+ (when (and i (stringp i))
+ i)))
+
+(defun org-blog-preamble (info)
+ "Pre-amble for whole blog."
+ (concat
+ "
"
+ (menu '("
↓ bottom ↓"))
+ "
"
+ (format "%s" (car (plist-get info :title)))
+ "
"
+ (when-let ((date (plist-get info :date)))
+ (format "
%s"
+ (format-time-string "%Y-%m-%d"
+ (org-timestamp-to-time
+ (car date)))))
+ (when-let ((subtitle (car (plist-get info :subtitle))))
+ (format "
%s
" subtitle))
+ "
"))
+
+(defun rand-obfs (c)
+ (let ((r (% (random) 20)))
+ (cond ;; ((eq 0 r) (format "%c" c))
+ ((<= 0 r 10) (format "%d;" c))
+ (t (format "%X;" c)))))
+
+(defun obfuscate-html (txt)
+ (apply 'concat
+ (mapcar 'rand-obfs txt)))
+
+(defun org-blog-postamble (info)
+ "Post-amble for whole blog."
+ (concat
+ ""
+ ;; TODO install a comment system
+ ;; (let ((url (format "%s%s" domainname (replace-regexp-in-string base-dir "" (plist-get info :input-file)))))
+ ;; (format "
comment"
+ ;; (url-hexify-string url)))
+ "
"
+ (menu '("
↑ Top ↑"))
+ "
"))
+
+(defun org-blog-sitemap-format-entry (entry _style project)
+ "Return string for each ENTRY in PROJECT."
+ (when (s-starts-with-p "posts/" entry)
+ (format (concat "@@html:")
+ "\n"))
+ (goto-char (point-max))
+ (search-backward "")
+ (insert "\n
\n")
+ (save-buffer)
+ (kill-buffer))
+ file-path))
+
+(defun org-blog-publish-attachment (plist filename pub-dir)
+ "Publish a file with no transformation of any kind.
+FILENAME is the filename of the Org file to be published. PLIST
+is the property list for the given project. PUB-DIR is the
+publishing directory.
+Take care of minimizing the pictures using imagemagick.
+Return output file name."
+ (unless (file-directory-p pub-dir)
+ (make-directory pub-dir t))
+ (or (equal (expand-file-name (file-name-directory filename))
+ (file-name-as-directory (expand-file-name pub-dir)))
+ (let ((dst-file (expand-file-name (file-name-nondirectory filename) pub-dir)))
+ (if (string-match-p ".*\\.\\(png\\|jpg\\|gif\\)$" filename)
+ (shell-command (format "~/.nix-profile/bin/convert %s -resize 800x800\\> +dither -colors 16 -depth 4 %s"
+ filename
+ dst-file))
+ (copy-file filename dst-file t)))))
+
+(setq org-publish-project-alist
+ `(("orgfiles"
+ :base-directory ,base-dir
+ :exclude ".*drafts/.*"
+ :base-extension "org"
+ :publishing-directory ,publish-dir
+
+ :recursive t
+ :publishing-function org-blog-publish-to-html
+
+ :with-toc nil
+ :with-title nil
+ :with-date t
+ :section-numbers nil
+ :html-doctype "html5"
+ :html-html5-fancy t
+ :html-head-include-default-style nil
+ :html-head-include-scripts nil
+ :htmlized-source t
+ :html-head-extra ,org-blog-head
+ :html-preamble org-blog-preamble
+ :html-postamble org-blog-postamble
+
+ :auto-sitemap t
+ :sitemap-filename "archive.org"
+ :sitemap-title "Blog Posts"
+ :sitemap-style list
+ :sitemap-sort-files anti-chronologically
+ :sitemap-format-entry org-blog-sitemap-format-entry
+ :sitemap-function org-blog-sitemap-function)
+
+ ("assets"
+ :base-directory ,assets-dir
+ :base-extension ".*"
+ :exclude ".*\.org$"
+ :publishing-directory ,publish-assets-dir
+ :publishing-function org-blog-publish-attachment
+ :recursive t)
+
+ ("rss"
+ :base-directory ,rss-dir
+ :base-extension "org"
+ :html-link-home ,domainname
+ :html-link-use-abs-url t
+ :rss-extension "xml"
+ :publishing-directory ,publish-rss-dir
+ :publishing-function (org-rss-publish-to-rss)
+ :exclude ".*"
+ :include ("archive.org")
+ :section-numbers nil
+ :table-of-contents nil)
+
+ ("blog" :components ("orgfiles" "assets" "rss"))))
+
+;; add target=_blank and rel="noopener noreferrer" to all links by default
+(defun my-org-export-add-target-blank-to-http-links (text backend info)
+ "Add target=\"_blank\" to external links."
+ (when (and
+ (org-export-derived-backend-p backend 'html)
+ (string-match "href=\"http[^\"]+" text)
+ (not (string-match "target=\"" text))
+ (not (string-match (concat "href=\"" domainname "[^\"]*") text)))
+ (string-match "