personal-website/blog/switching-to-nikola/index.html

294 lines
19 KiB
HTML

<!DOCTYPE html>
<html prefix="og: http://ogp.me/ns# article: http://ogp.me/ns/article# " lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Switching to Nikola! | VICKY STEEVES</title>
<link href="../../assets/css/all-nocdn.css" rel="stylesheet" type="text/css">
<meta content="#5670d4" name="theme-color">
<link rel="alternate" type="application/rss+xml" title="RSS" href="../../rss.xml">
<link rel="canonical" href="http://vickysteeves.com/blog/switching-to-nikola/">
<link rel="favicon" href="../../favicon.ico" sizes="16x16">
<link rel="favicon1" href="icon_128x128.png" sizes="128x128">
<!--[if lt IE 9]><script src="../../assets/js/html5.js"></script><![endif]--><meta name="author" content="Vicky Steeves">
<link rel="prev" href="../share-week/" title="SHARE Week" type="text/html">
<link rel="next" href="../cern-visit/" title="Visiting CERN" type="text/html">
<meta property="og:site_name" content="VICKY STEEVES">
<meta property="og:title" content="Switching to Nikola!">
<meta property="og:url" content="http://vickysteeves.com/blog/switching-to-nikola/">
<meta property="og:description" content="This might be a shock to many of you (except my boyfriend and his roommate, who have been giving me sh*t about this forever), but before today I actually hard-coded my website. This meant that every t">
<meta property="og:type" content="article">
<meta property="article:published_time" content="2016-08-17T17:10:00-04:00">
<meta property="article:tag" content="development">
<meta property="article:tag" content="metapost">
</head>
<body>
<a href="#content" class="sr-only sr-only-focusable">Skip to main content</a>
<div class="container" id="content" role="main">
<!-- Menubar -->
<nav class="navbar navbar-inverse"><div class="container-fluid">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-2">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="http://vickysteeves.com/">
<span id="blog-title" style="padding: 19px 0px;">VICKY STEEVES</span>
</a>
</div>
<!-- /.navbar-header -->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-2">
<ul class="nav navbar-nav">
<li>
<a href="../../">Home</a>
</li>
<li>
<a href="../../resume">Resume</a>
</li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Blog <b class="caret"></b></a>
<ul class="dropdown-menu">
<li>
<a href="../../blog">Posts</a>
</li>
<li>
<a href="../../archive.html">Archives</a>
</li>
</ul>
</li>
</ul>
<ul class="nav navbar-nav navbar-right">
<!--dropdown--><li><a href="https://impactstory.org/u/0000-0003-4298-168X">ImpactStory</a></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Data<span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="https://osf.io/7mj2q/">Open Science Framework</a></li>
<li><a href="https://github.com/VickySteeves">GitHub</a></li>
</ul>
</li>
<!--end dropdown-->
<!--dropdown-->
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Social Media<span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="https://twitter.com/VickySteeves">Twitter</a></li>
<li><a href="https://www.instagram.com/vickysteeves/">Instagram</a></li>
<li><a href="https://www.linkedin.com/in/victoriaisteeves">LinkedIn</a></li>
</ul>
</li>
<!--end dropdown-->
</ul>
</div>
<!-- /.navbar-collapse -->
</div>
<!-- /.container -->
</nav><!-- End of Menubar --><div class="body-content">
<!--Body content-->
<div class="row">
<article class="post-text h-entry hentry postpage" itemscope="itemscope" itemtype="http://schema.org/Article"><header><a href="https://github.com/VickySteeves/personal-website/blob/master/posts/2016-aug17.rst" id="sourcelink"><img src="../../images/github.png" height="5%" width="5%" style="float:right;"></a>
<h1 class="p-name entry-title" itemprop="headline name"><a href="." class="u-url">Switching to Nikola!</a></h1>
<div class="metadata">
<p class="byline author vcard"><span class="byline-name fn">
<a href="../../resume">Vicky Steeves</a>
</span></p>
<p class="dateline"><a href="." rel="bookmark"><time class="published dt-published" datetime="2016-08-17T17:10:00-04:00" itemprop="datePublished" title="08-17-2016">08-17-2016</time></a></p>
<p class="commentline">
<a href="#disqus_thread" data-disqus-identifier="cache/posts/2016-aug17.html">Comments</a>
</p>
</div>
</header><div class="e-content entry-content" itemprop="articleBody text">
<div>
<p>This might be a shock to many of you (except my boyfriend and his roommate, who have been giving me sh*t about this forever), but before today I actually hard-coded my website. This meant that every time I updated a post, changed my resume, etc., I had to hard code the changes and the ripple effects.</p>
<p>What was I thinking. Honestly. You can look at how painful it was <a class="reference external" href="https://github.com/VickySteeves/personal-website/tree/OLD/static">here</a> on GitHub. I kept it as a reminder and in case I severely messed up this whole Nikola thing, which I'm going to explain in the bulk of this post.</p>
<!-- TEASER_END -->
<p>I actually made a lot of changes, starting with dumping my old website host, Bluehost. I had decided to register my domain names on Google Domains, which was not only half the cost of Bluehost -- $50/year on Bluehost for 2 domains, and $24/year on Google Domains for the same -- but it provided an easier interface to fix settings, play with email stuff (you can get at me via <a class="reference external" href="mailto:vicky@vickysteeves.com">vicky[AT]vickysteeves[DOT]com</a>! so cool!!), and have domains connected to a Google account, which is just convenient. It's all around really great. If Google retires this, I will honestly throw a fit.</p>
<p>So after I had made the change from Bluehost to Google Domains, I made the switch from Bluehost's servers to GitHub. I exported my site (which was still just hard-coded, even back then) and uploaded to a private GitHub repository. I wanted to make it look pretty before I made it public, as I was pretty embarrassed that I <strong>still</strong> hard-coded my site, especially given I have a C.S. degree... <em>shame</em>.</p>
<p>So I also knew that I couldn't hard-code forever. It was such a hassle to update everything manually every time I wanted to write a post. Rémi pointed me towards static site generators, which I had never really heard of before. <a class="reference external" href="https://davidwalsh.name/introduction-static-site-generators">This introduction to SSGs</a> was really helpful to me as I decided to go with this option. Some of the most obvious advantages are:</p>
<ul class="simple">
<li><dl class="first docutils">
<dt>Completely open-source development</dt>
<dd><ul class="first last">
<li>The static site generators I considered are fully open source, which lets people not only develop great themes and plugins, but support each other in building/using/customizing the generator.</li>
<li>Anyone can file an issue on my site or blog posts (or help me do development -- shoutout to <a class="reference external" href="http://bf.vickysteeves.com">Rémi</a> for that already) when something is wrong or to add a correction with a pull request.</li>
</ul></dd>
</dl></li>
<li>Easy version control and integration with GitHub, which I had already chosen to host my website.</li>
<li>Speed: static generators are usually much faster than a full-blown content mangement system (CMS) like WordPress or the like, because it doesn't rely on a database and server configuration.</li>
<li>Ease of Use: I don't have to deal with a server, which I don't really need. I just need to serve up my HTML pages! And if need be, I can migrate the site to something else -- as a data management librarian, I always have to have an exit strategy ;)</li>
</ul>
<p>I eventually opened up an <a class="reference external" href="https://github.com/VickySteeves/personal-website/issues/3">issue</a> in my GitHub repo that put pressure on me to make this change happen. <a class="reference external" href="https://www.staticgen.com/">Static Gen</a> was an invaluable resource to me as I narrowed my choices down to eventually include Nikola. Nikola is actually #26 on this list, which ranks SSGs by the number of stars it has on GitHub, but it was a really obvious choice for me. I had a few requirements for a site generator:</p>
<ul class="simple">
<li>Support <a class="reference external" href="http://getbootstrap.com/">Bootstrap</a> themes/JS, which I love and already had been using.</li>
<li>Simple blogging framework</li>
<li>Preferably python based</li>
</ul>
<p>I narrowed it down to <a class="reference external" href="http://blog.getpelican.com/">Pelican</a>, <a class="reference external" href="https://www.staticgen.com/hugo">Hugo</a>, <a class="reference external" href="https://www.staticgen.com/lektor">Lektor</a>, and <a class="reference external" href="https://www.staticgen.com/nikola">Nikola</a>. Each had their obvious advantages: Pelican is really simple to build, Hugo is really fast and allows users to define their own metadata, Lektor has built-in dependency tracking, but Nikola stood out to me for a few reasons: built-in Boostrap &amp; <a class="reference external" href="https://bootswatch.com/">Bootswatch</a> support, amazing plugins (including one to <a class="reference external" href="https://plugins.getnikola.com/#iarchiver">send your posts to the Internet Archive</a>!), a really active user and development community, translatable (like French for my boyfriend's parents, who like to Google me :P), python 2 and 3 compatiable, and beyond easy to build.</p>
<p>The next step was to actually take the plunge and develop it. Because Nikola was developed with a "blog first" mentality, I had to do some interesting things with the configuration file to make sure I could my homepage and resume page, and THEN my blog on it's own separate page. Nikola's developers have a <a class="reference external" href="https://getnikola.com/creating-a-site-not-a-blog-with-nikola.html">good guide</a> for doing this. The default setup for pages and posts in Nikola's conf.py file is::</p>
<pre class="literal-block">
POSTS = (
("posts/*.rst", "posts", "post.tmpl"),
("posts/*.txt", "posts", "post.tmpl"),
("posts/*.html", "posts", "post.tmpl"),
)
PAGES = (
("stories/*.rst", "stories", "story.tmpl"),
("stories/*.txt", "stories", "story.tmpl"),
("stories/*.html", "stories", "story.tmpl"),
)
</pre>
<p>We have to modify this to look like::</p>
<pre class="literal-block">
POSTS = ()
PAGES = (
("stories/*.rst", "", "story.tmpl"),
("stories/*.txt", "", "story.tmpl"),
("stories/*.html", "", "story.tmpl"),
)
INDEX_PATH = "blog"
</pre>
<p>And then add the pages in the folder called "stories" which is basically Nikola-speak for just regular web pages. After I was done adding the pages I wanted (basically a home page and a resume page, basically copy-pasting what I had on my original site), I reviewed the POSTS to look like this::</p>
<pre class="literal-block">
POSTS = (
("posts/*.rst", "blog", "post.tmpl"),
("posts/*.txt", "blog", "post.tmpl"),
("posts/*.html", "blog", "post.tmpl"),
)
</pre>
<p>And all the posts would be indexed on a new page called "Blog" which I then added to my navigation, along with my recently added pages.</p>
<p>After getting the navigation and blog configured the way I wanted, the most labour-intensive part of the process began: porting over all my blog posts. Another amazing thing about Nikola, and another reason I chose it, is because users can write blog posts in whatever they want. This is my list from my conf.py file::</p>
<pre class="literal-block">
COMPILERS = {
"rest": ('.rst', '.txt'), #reStructured Text
"markdown": ('.md', '.mdown', '.markdown'),
"textile": ('.textile',),
"txt2tags": ('.t2t',),
"bbcode": ('.bb',),
"wiki": ('.wiki',),
"ipynb": ('.ipynb',), #iPython notebooks
"html": ('.html', '.htm'),
)
</pre>
<p>This worked out <em>excellently</em> for me because all my previous posts were written in HTML (again, I was being a n00b and hard-coding these all myself). I could literally copy and paste the body of the post, and clean up what needed to be cleaned. This included: fixing links to images and other parts of my website, and adding in the metadata that Nikola required. I had to fix my posts to follow this structure, which was super easy::</p>
<pre class="literal-block">
&lt;!--
.. title: Title of the Post!
.. slug: pretty-url-slug
.. date: 20XX-XX-XX
.. tags:
.. category:
.. link: https://github.com/VickySteeves/personal-website/blob/master/posts/{POST FILE NAME}
.. description:
.. type: text
--&gt;
&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;
&lt;body&gt;
&lt;!--POST BODY--&gt;
&lt;/body&gt;
&lt;/html&gt;`
</pre>
<p>After the posts were all successfully modified to the Nikola schema, it was a simple matter of cleaning up the aesthetics. This was done by copy-pasting the templates from Nikola into my site's directory, and then editing them -- the same as creating a child-theme in WordPress. By doing this, I could modify the way my site rendered dynamically. My favourite modification I made (and again, thanks to Rémi for the suggestion) was adding the GitHub source link on each of my blog posts. Each of my posts has this cute little GitHub image</p>
<img alt="../../images/github.png" src="../../images/github.png"><p>at the far-right to the title, that, if clicked, brings the user to the source hosted on GitHub.</p>
<p>This allows my readers to go directly to the source of my post to make corrections, pull requests, etc. I did this by editing the post_header.tmpl file. I copied it into a folder in my site's directory called "templates" which has a long file path: personal-website/themes/custom/templates. Before editing, it just asked the post for it's metadata after displaying the title::</p>
<pre class="literal-block">
&lt;%def name="html_post_header()"&gt;
&lt;header&gt;
${html_title()}
&lt;div class="metadata"&gt;
</pre>
<p>After editing, the image was added to the right of the title. The code looks like this::</p>
<pre class="literal-block">
&lt;%def name="html_post_header()"&gt;
&lt;header&gt;
{* GITHUB IMAGE WITH SOURCE LINK *}
&lt;a href="${post.meta('link')}" id="sourcelink"&gt;&lt;img src="../../images/github.png" height="5%" width="5%" style="float:right;"&gt;&lt;/a&gt;
${html_title()}
&lt;div class="metadata"&gt;
</pre>
<p>This works by querying the post's metadata (which you saw above in the HTML template snippet) for the "link," which goes back to the GitHub source. I added some inline CSS (the style="") which isn't the cleanest, but hey -- it works, and if you want to fix it, make a pull request ;)</p>
<p>After adding this feature and cleaning up the aesthetics, Rémi made the excellent point that I should use <a class="reference external" href="https://travis-ci.org/">Travis CI</a> to make sure my site updated every time a commit was made, either through Git or on GitHub natively (PR or in-browser editing). He actually ended up writing my build file because engineers and he's super smart and did it in 2 seconds when it would have taken me a day.</p>
<p>This is my first post written and published using pure Nikola. I wrote it in reStructured Text format, which honestly seems like the biggest challenge in switching. After writing HTML for so long, it's an easy habit to get into. This is much nicer because it doesn't require tags for literally everything.</p>
<p>I hope this helps anyone else looking to make the switch into static site generators!</p>
</div>
</div>
<aside class="postpromonav"><nav><ul itemprop="keywords" class="tags">
<li><a class="tag p-category" href="../../categories/development/" rel="tag">development</a></li>
<li><a class="tag p-category" href="../../categories/metapost/" rel="tag">metapost</a></li>
</ul>
<ul class="pager hidden-print">
<li class="previous">
<a href="../share-week/" rel="prev" title="SHARE Week">Previous post</a>
</li>
<li class="next">
<a href="../cern-visit/" rel="next" title="Visiting CERN">Next post</a>
</li>
</ul></nav></aside><section class="comments hidden-print"><h2>Comments</h2>
<div id="disqus_thread"></div>
<script>
var disqus_shortname ="vicky-steeves",
disqus_url="http://vickysteeves.com/blog/switching-to-nikola/",
disqus_title="Switching to Nikola!",
disqus_identifier="cache/posts/2016-aug17.html",
disqus_config = function () {
this.language = "en";
};
(function() {
var dsq = document.createElement('script'); dsq.async = true;
dsq.src = 'https://' + 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="https://disqus.com/?ref_noscript" rel="nofollow">comments powered by Disqus.</a>
</noscript>
<a href="https://disqus.com" class="dsq-brlink" rel="nofollow">Comments powered by <span class="logo-disqus">Disqus</span></a>
</section></article><script>var disqus_shortname="vicky-steeves";(function(){var a=document.createElement("script");a.async=true;a.src="https://"+disqus_shortname+".disqus.com/count.js";(document.getElementsByTagName("head")[0]||document.getElementsByTagName("body")[0]).appendChild(a)}());</script>
</div>
<!--End of body content-->
<footer id="footer"><div align="center">
<span xmlns:dct="http://purl.org/dc/terms/" property="dct:title">Data, Science, &amp; Librarians, Oh My!</span> by <a xmlns:cc="http://creativecommons.org/ns#" href="http://vickysteeves.com/blog.html" property="cc:attributionName" rel="cc:attributionURL">Vicky Steeves</a> is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License</a>
</div>
<br></footer>
</div>
</div>
<script src="../../assets/js/all-nocdn.js"></script><script>$('a.image-reference:not(.islink) img:not(.islink)').parent().colorbox({rel:"gal",maxWidth:"100%",maxHeight:"100%",scalePhotos:true});</script><!-- fancy dates --><script>
moment.locale("en");
fancydates(1, "MM-DD-YYYY");
</script><!-- end fancy dates --><script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-86255717-1', 'auto');
ga('send', 'pageview');
</script>
</body>
</html>