Blogging with RestructuredText, a Google Domain, and Pelican

Purchase a domain from Google.

Installing and using Pelican is very straightforward. Only pelicanconf.py is needed as a configuration file:

#!/usr/bin/env python
# -*- coding: utf-8 -*- #
from __future__ import unicode_literals

AUTHOR = 'alphaXomega'
SITENAME = 'All Things Phi'
SITEURL = 'http://allthingsphi.com'

TIMEZONE = 'US/Pacific'

DEFAULT_DATE = 'fs'
DEFAULT_LANG = 'en'

PATH = 'content'
PAGE_EXCLUDES = ['assets']
ARTICLE_EXCLUDES = ['assets']
STATIC_PATHS = ['assets']
OUTPUT_PATH = 'gae/www/'

DEFAULT_PAGINATION = False

GOOGLE_ANALYTICS = 'UA-XXXXXXXX-X'

#THEME = 'pelican-chameleon'
#MENUITEMS = [
#    ('Bitbucket', 'https://bitbucket.org/alphaXomega/'),
#    ('Search', 'XXXXXXXXXXXXXXXXXXXXX:XXXXXXXXXXX')
#]
#AUTHORS = {
#    'alphaXomega': 'about.html'
#}

FEED_ALL_ATOM = None
CATEGORY_FEED_ATOM = None
TRANSLATION_FEED_ATOM = None
AUTHOR_FEED_ATOM = None
AUTHOR_FEED_RSS = None

# Blogroll
LINKS = None

# Social widget
SOCIAL = None

# Uncomment following line if you want document-relative URLs when developing
RELATIVE_URLS = False

Changing the default theme consists of cloning the desired repository and setting the THEME variable to the corresponding path. Prefer themes that support Google Custom Search Engine for easier navigation.

Google App Engine

After completing the Before you begin section, add the custom domain and take note of the resource records. Go to the Google Domains site and select the Configure DNS tab. Under Custom resource records, add each of the records. Finally enable SSL by turning on Google-managed security.

Create an app.yaml configuration file in the root directory of the application with the following content:

runtime: python27
api_version: 1
threadsafe: yes

handlers:
#re-direct to index.html if no path is give
- url: /
  static_files: www/index.html
  upload: www/index.html
  secure: always
#access the static resources in the www directory
- url: /
  static_dir: www
  secure: always

The secure: always forces the app to always serve https.

Assuming a project layout consisting of

.
├── content
│   └── assets
├── gae
│   ├── app.yaml
│   └── www
└── pelicanconf.py

the following commands will generate the blog and upload it to GAE:

pelican content
gcloud app deploy gae/app.yaml --stop-previous-version

GAE at the moment does not expose an automatic way of deleting older app versions. Use the following commands to manually remove older versions:

gcloud app versions list
gcloud app versions delete <VERSION from list>...

Log Keeping with Mercurial

In an ideal world, a memex system would serve as a blog. Until that time comes, Mercurial is one of the most pleasant alternatives. When using it locally, create a configuration file ~/.hgrc with the following content:

[ui]
username = your_name <your_email@gmail.com>

ssh = ssh -C

The last line is to enable file compression when using Mercurial with Bitbucket over SSH.

Blogger (i.e. for those who do not own a web domain)

Go to the Configure website tab and select the Create action next to the Blogger platform. The Address field during the creation of the blog should be the purchased domain name. After creating the blog, go to Settings and edit the Blog Address to enable redirection from the non-www domain URL to the www domain URL.

Each post can be compiled and added manually to Blogger via

tail -n+<first_line_to_print> <file> | rst2html.py | xclip -selection clipboard

Notice that tail is needed because Pelican requires each post to have a title, but Blogger has its own mechanism for titles. The output from rst2html.py is the appropriate content to post to Blogger.

The Navbar Configuration layout includes a non-removable Next Blog link, which is quite confusing to the end user. The easiest solution is to remove it, but that requires giving up the search functionality.

The ideal search replacement is Google’s Search Box gadget, powered by CSE. This solution requires submitting an index request via the Google Search Console.

Another solution is to add a HTML/JavaScript gadget that defines such a search box:

<style type="text/css">
  #searchThisBlogForm {
    margin: 4px;
  }

  #searchThisBlogBox {
    border: 2px solid #dadada;
    border-radius: 15px;
    -moz-border-radius: 15px;
    -webkit-border-radius: 15px;
  }

  #searchThisBlogBox:focus {
    border-color: #9ecaed;
    box-shadow: 0px 0px 10px #9ecaed;
    outline: none;
  }
</style>

<form id="searchThisBlogForm" action="/search" method="get">
  <input type="search" id="searchThisBlogBox" name="q" placeholder="Search this blog..." results/>
</form>

Note that the CSS style is purely for aesthetic reasons.