diff --git a/.project.el b/.project.el
new file mode 100644
index 0000000..be1402b
--- /dev/null
+++ b/.project.el
@@ -0,0 +1,202 @@
+(require 'org)
+(require 'ox-publish)
+(require 'ox-html)
+(require 'org-element)
+(require 'ox-rss)
+
+(defun org-blog-prepare (project-plist)
+ "With help from `https://github.com/howardabrams/dot-files'.
+ Touch `index.org' to rebuilt it.
+ Argument `PROJECT-PLIST' contains information about the current project."
+ (let* ((base-directory (plist-get project-plist :base-directory))
+ (buffer (find-file-noselect (expand-file-name "index.org" base-directory) t)))
+ (with-current-buffer buffer
+ (set-buffer-modified-p t)
+ (save-buffer 0))))
+
+(defvar org-blog-head
+ (concat
+ ""
+ ""
+ ""
+ ""))
+
+(defun menu (lst)
+ "Blog menu"
+ (concat
+ ""))
+
+
+(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 org-blog-preamble (info)
+ "Pre-amble for whole blog."
+ (concat
+ "
"
+ (menu '("
↓ bottom ↓"))
+ "
"
+ (format "%s" (car (plist-get info :title)))
+ (when-let ((date (get-from-info info :date)))
+ (format " - %s" date))
+ "
"
+ "
"))
+
+(defun get-from-info (info k)
+ (let ((i (car (plist-get info k))))
+ (when (and i (stringp i))
+ i)))
+
+(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
+ ""
+ "
"
+ (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 "@@html:@@ %s: @@html:@@ [[file:%s][%s]] @@html:@@"
+ (format-time-string "%Y-%m-%d"
+ (org-publish-find-date entry project))
+ entry
+ (org-publish-find-title entry project))))
+
+(defun org-blog-sitemap-function (title list)
+ "Return sitemap using TITLE and LIST returned by `org-blog-sitemap-format-entry'."
+ (concat "#+TITLE: " title "\n"
+ "#+AUTHOR: Yann Esposito\n"
+ "#+EMAIL: yann.esposito@gmail.com\n"
+ "\n#+begin_archive\n"
+ (mapconcat (lambda (li)
+ (format "@@html:@@ %s @@html:@@" (car li)))
+ (seq-filter #'car (cdr list))
+ "\n")
+ "\n#+end_archive\n"))
+
+(setq base-dir (concat (projectile-project-root) "src"))
+(setq publish-dir (concat (projectile-project-root) "_site"))
+(setq assets-dir (concat base-dir "/assets"))
+(setq publish-assets-dir (concat publish-dir "/assets"))
+(setq rss-dir base-dir)
+(setq publish-rss-dir publish-dir)
+(setq domainname "https://her.esy.fun")
+(setq org-publish-project-alist
+ `(("orgfiles"
+ :base-directory ,base-dir
+ :exclude ".*drafts/.*"
+ :base-extension "org"
+
+ :publishing-directory ,publish-dir
+
+ :recursive t
+ :preparation-function org-blog-prepare
+ :publishing-function org-html-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 ".*"
+ :publishing-directory ,publish-assets-dir
+ :publishing-function org-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 ""
- ""
- ""
- ""))
-
- (defun menu (lst)
- "Blog menu"
- (concat
- ""))
-
-
- (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 org-blog-preamble (info)
- "Pre-amble for whole blog."
- (concat
- ""
- (menu '("
↓ bottom ↓"))
- "
"
- (format "%s" (car (plist-get info :title)))
- (when-let ((date (get-from-info info :date)))
- (format " - %s" date))
- "
"
- "
"))
-
- (defun get-from-info (info k)
- (let ((i (car (plist-get info k))))
- (when (and i (stringp i))
- i)))
-
- (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
- ""
- "
"
- (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 "@@html:@@ %s: @@html:@@ [[file:%s][%s]] @@html:@@"
- (format-time-string "%Y-%m-%d"
- (org-publish-find-date entry project))
- entry
- (org-publish-find-title entry project))))
-
- (defun org-blog-sitemap-function (title list)
- "Return sitemap using TITLE and LIST returned by `org-blog-sitemap-format-entry'."
- (concat "#+TITLE: " title "\n"
- "#+AUTHOR: Yann Esposito\n"
- "#+EMAIL: yann.esposito@gmail.com\n"
- "\n#+begin_archive\n"
- (mapconcat (lambda (li)
- (format "@@html:@@ %s @@html:@@" (car li)))
- (seq-filter #'car (cdr list))
- "\n")
- "\n#+end_archive\n"))
-
- (setq base-dir (concat (projectile-project-root) "src"))
- (setq publish-dir (concat (projectile-project-root) "_site"))
- (setq assets-dir (concat base-dir "/assets"))
- (setq publish-assets-dir (concat publish-dir "/assets"))
- (setq rss-dir base-dir)
- (setq publish-rss-dir publish-dir)
- (setq domainname "https://her.esy.fun")
- (setq org-publish-project-alist
- `(("orgfiles"
- :base-directory ,base-dir
- :exclude ".*drafts/.*"
- :base-extension "org"
-
- :publishing-directory ,publish-dir
-
- :recursive t
- :preparation-function org-blog-prepare
- :publishing-function org-html-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 ".*"
- :publishing-directory ,publish-assets-dir
- :publishing-function org-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 "