diff --git a/Makefile b/Makefile
index 2735444..e4c6ee9 100644
--- a/Makefile
+++ b/Makefile
@@ -1,17 +1,57 @@
-PELICAN=pelican
+PELICANOPTS=
-html:
- $(PELICAN) -s pelican.conf.py content
+BASEDIR=$(CURDIR)
+INPUTDIR=$(BASEDIR)/content
+OUTPUTDIR=$(BASEDIR)/output
+CONFFILE=$(BASEDIR)/pelicanconf.py
+PUBLISHCONF=$(BASEDIR)/publishconf.py
-upload: html
- rsync -P -rvz --delete output/* artichaut:/home/www/blog.notmyidea.org
+VENV := $(shell echo $${VIRTUAL_ENV-$(shell pwd)/.venv})
+VIRTUALENV = virtualenv -p /usr/bin/python3.6
+INSTALL_STAMP = $(VENV)/.install.stamp
-serve: html
- cd output && python -m pelican.server 8000&
+PYTHON=$(VENV)/bin/python
+PELICAN=$(VENV)/bin/pelican
+PIP=$(VENV)/bin/pip
-regenerate: serve
- $(PELICAN) -r -s pelican.conf.py content
+DEBUG ?= 0
+ifeq ($(DEBUG), 1)
+ PELICANOPTS += -D
+endif
-github: html
- ghp-import -n $(OUTPUTDIR)
- @git push -fq https://${GH_TOKEN}@github.com/$(TRAVIS_REPO_SLUG).git gh-pages > /dev/null
+install: $(INSTALL_STAMP)
+$(INSTALL_STAMP): $(PYTHON) requirements.txt
+ $(VENV)/bin/pip install -r requirements.txt
+ touch $(INSTALL_STAMP)
+
+virtualenv: $(PYTHON)
+$(PYTHON):
+ $(VIRTUALENV) $(VENV)
+
+html: install
+ $(PELICAN) $(INPUTDIR) -o $(OUTPUTDIR) -s $(CONFFILE) $(PELICANOPTS)
+
+clean:
+ [ ! -d $(OUTPUTDIR) ] || rm -rf $(OUTPUTDIR)
+ rm -rf $(VENV)
+
+serve: install
+ifdef PORT
+ cd $(OUTPUTDIR) && $(PYTHON) -m pelican.server $(PORT)
+else
+ cd $(OUTPUTDIR) && $(PYTHON) -m pelican.server 8000
+endif
+
+regenerate:
+ cd $(OUTPUTDIR) && $(PYTHON) -m pelican.server &
+ $(PELICAN) -r $(INPUTDIR) -o $(OUTPUTDIR) -s $(CONFFILE) $(PELICANOPTS)
+
+publish: install
+ $(PELICAN) $(INPUTDIR) -o $(OUTPUTDIR) -s $(PUBLISHCONF) $(PELICANOPTS)
+ echo "blog.notmyidea.org" > $(OUTPUTDIR)/CNAME
+
+github: publish
+ ghp-import -n $(OUTPUTDIR)
+ @git push -fq https://${GH_TOKEN}@github.com/$(TRAVIS_REPO_SLUG).git gh-pages > /dev/null
+
+.PHONY: html clean serve devserver publish
diff --git a/pelican.conf.py b/pelicanconf.py
similarity index 100%
rename from pelican.conf.py
rename to pelicanconf.py
diff --git a/publishconf.py b/publishconf.py
new file mode 100644
index 0000000..95de51b
--- /dev/null
+++ b/publishconf.py
@@ -0,0 +1,19 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*- #
+from __future__ import unicode_literals
+
+# This file is only used if you use `make publish` or
+# explicitly specify it as your config file.
+
+import os
+import sys
+sys.path.append(os.curdir)
+from pelicanconf import * # NoQA
+
+SITEURL = 'https://blog.notmyidea.org'
+RELATIVE_URLS = False
+
+FEED_ALL_ATOM = 'feeds/all.atom.xml'
+CATEGORY_FEED_ATOM = 'feeds/%s.atom.xml'
+
+DELETE_OUTPUT_DIRECTORY = True
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..fa95caf
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1 @@
+pelican
diff --git a/theme/templates/base.html b/theme/templates/base.html
index d2af2a1..781090e 100644
--- a/theme/templates/base.html
+++ b/theme/templates/base.html
@@ -22,9 +22,6 @@
{% if FEED_RSS %}
{% endif %}
- {% if CATEGORY_FEED_ATOM and category %}
-
- {% endif %}
{% if CATEGORY_FEED_RSS and category %}
{% endif %}