summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.firebaserc1
-rw-r--r--.gitignore5
-rw-r--r--404.adoc8
-rw-r--r--Rakefile82
-rw-r--r--_config.yml24
-rw-r--r--_includes/footer.html0
-rw-r--r--_includes/head.html12
-rw-r--r--_includes/header.html0
-rw-r--r--_layouts/default.html21
-rw-r--r--_layouts/home.html34
-rw-r--r--_layouts/page.html14
-rw-r--r--_layouts/post.html15
-rw-r--r--_sass/_base.scss203
-rw-r--r--_sass/_layout.scss242
-rw-r--r--_sass/_normalize.scss425
-rw-r--r--_sass/_syntax-highlighting.scss72
-rw-r--r--build/Dockerfile.build.erb3
-rw-r--r--build/Dockerfile.deploy.erb5
-rw-r--r--build/apache.conf21
-rw-r--r--build/templates/Dockerfile.base.erb27
-rw-r--r--build/templates/Dockerfile.cmd.erb3
-rw-r--r--css/main.scss53
-rw-r--r--firebase.json19
-rw-r--r--index.html3
-rw-r--r--public/.gitignore0
25 files changed, 1292 insertions, 0 deletions
diff --git a/.firebaserc b/.firebaserc
new file mode 100644
index 0000000..0967ef4
--- /dev/null
+++ b/.firebaserc
@@ -0,0 +1 @@
+{}
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..6d93572
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+.sass-cache
+/_site/
+/build/Dockerfile.*
+!/build/Dockerfile.*.erb
+node_modules/
diff --git a/404.adoc b/404.adoc
new file mode 100644
index 0000000..99956e4
--- /dev/null
+++ b/404.adoc
@@ -0,0 +1,8 @@
+---
+layout: default
+---
+= 404
+
+*Page not found*
+
+The requested page could not be found.
diff --git a/Rakefile b/Rakefile
new file mode 100644
index 0000000..2164645
--- /dev/null
+++ b/Rakefile
@@ -0,0 +1,82 @@
+require 'erb'
+require 'rake'
+require 'rexml/document'
+
+# ERB processing template.
+class Template
+ def name
+ @name ||= 0
+ @name += 1
+ "name_a#{@name}"
+ end
+
+ def erb(file)
+ ERB.new(File.read(file), nil, '-', name).result(binding)
+ end
+end
+
+GCLOUD_PROJECT = 'responsive-task-141123'
+IMAGE_NAME = 'blog'
+
+SOURCE_FILES = Rake::FileList['**/*.adoc']
+IGNORABLE = Rake::FileList[
+ '_site/Rakefile',
+ '_site/build/**',
+ '_site/node_modules/**',
+ '_site/firebase.json',
+]
+TEMPLATES = Rake::FileList['build/*.erb']
+
+task :s => [:serve]
+task :b => [:build]
+
+task :serve do
+ sh 'jekyll serve'
+end
+
+task :jekyll do
+ sh 'jekyll build'
+end
+
+task :all => [:build]
+
+task :build => [:jekyll] do
+ files = Rake::FileList['_site/**/*.html']
+ files.each do |f|
+ Rake::Task[f.gsub(/\.html$/, '.xhtml')].invoke
+ end
+ rm files
+ rm_r IGNORABLE
+end
+
+task :templates do
+ TEMPLATES.each do |f|
+ fp = File.open(f.sub(/\.erb$/, ''), 'w')
+ fp.print Template.new.erb(f)
+ fp.close
+ end
+end
+
+task :deploy => [:templates] do
+ image = "gcr.io/#{GCLOUD_PROJECT}/#{IMAGE_NAME}"
+ sh "docker build -t #{image} -f build/Dockerfile.deploy ."
+ sh "docker push #{image}"
+ sh "gcloud beta run deploy --project #{GCLOUD_PROJECT} --allow-unauthenticated --region us-central1 --image #{image} #{IMAGE_NAME}"
+ # Note that "npm install --no-package-lock firebase-tools" must have been run.
+ sh "node_modules/.bin/firebase deploy --project #{GCLOUD_PROJECT}"
+ sh "gcloud container images delete #{image}:latest"
+end
+
+task :check => [:build] do
+ Rake::FileList['_site/**/*.html', '_site/**/*.xhtml'].each do |f|
+ begin
+ REXML::Document.new(File.read(f))
+ rescue StandardError => e
+ raise "Failed well-formedness check for #{f}: #{e}"
+ end
+ end
+end
+
+rule '.xhtml' => ['.html'] do |t|
+ cp t.source, t.name
+end
diff --git a/_config.yml b/_config.yml
new file mode 100644
index 0000000..3e90568
--- /dev/null
+++ b/_config.yml
@@ -0,0 +1,24 @@
+# Welcome to Jekyll!
+#
+# This config file is meant for settings that affect your whole blog, values
+# which you are expected to set up once and rarely need to edit after that.
+# For technical reasons, this file is *NOT* reloaded automatically when you use
+# 'jekyll serve'. If you change this file, please restart the server process.
+
+# Site settings
+title: Sidewalk to Nowhere
+email: webmaster@phthalo.io
+description: Thoughts and musings by brian m. carlson
+baseurl: "" # the subpath of your site, e.g. /blog
+url: "https://sidewalk.crustytoothpaste.net" # the base hostname & protocol for your site
+
+# Build settings
+markdown: kramdown
+asciidoc:
+ ext: adoc
+asciidoctor:
+ backend: xhtml5
+ attributes:
+ source-highlighter: rouge
+gems:
+ - jekyll-asciidoc
diff --git a/_includes/footer.html b/_includes/footer.html
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/_includes/footer.html
diff --git a/_includes/head.html b/_includes/head.html
new file mode 100644
index 0000000..f077285
--- /dev/null
+++ b/_includes/head.html
@@ -0,0 +1,12 @@
+<head>
+ <meta charset="utf-8" />
+ <meta http-equiv="X-UA-Compatible" content="IE=edge" />
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
+
+ <title>{% if page.title %}{{ page.title | escape }}{% else %}{{ site.title | escape }}{% endif %}</title>
+ <meta name="description" content="{% if page.excerpt %}{{ page.excerpt | strip_html | strip_newlines | truncate: 160 }}{% else %}{{ site.description }}{% endif %}" />
+
+ <link rel="stylesheet" href="{{ "/css/main.css" | prepend: site.baseurl }}" />
+ <link rel="canonical" href="{{ page.url | replace:'index.html','' | prepend: site.baseurl | prepend: site.url | remove: ".html" }}" />
+ <link rel="alternate" type="application/rss+xml" title="{{ site.title }}" href="{{ "/feed.xml" | prepend: site.baseurl | prepend: site.url }}" />
+</head>
diff --git a/_includes/header.html b/_includes/header.html
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/_includes/header.html
diff --git a/_layouts/default.html b/_layouts/default.html
new file mode 100644
index 0000000..f873e3b
--- /dev/null
+++ b/_layouts/default.html
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml">
+
+ {% include head.html %}
+
+ <body>
+
+ {% include header.html %}
+
+ <div class="page-content">
+ <div class="wrapper">
+ {{ content }}
+ </div>
+ </div>
+
+ {% include footer.html %}
+
+ </body>
+
+</html>
diff --git a/_layouts/home.html b/_layouts/home.html
new file mode 100644
index 0000000..33bc17d
--- /dev/null
+++ b/_layouts/home.html
@@ -0,0 +1,34 @@
+---
+layout: default
+---
+
+<div class="home">
+ {%- if page.title -%}
+ <h1 class="page-heading">{{ page.title }}</h1>
+ {%- endif -%}
+
+ {{ content }}
+
+ {%- if site.posts.size > 0 -%}
+ <h2 class="post-list-heading">{{ page.list_title | default: "Posts" }}</h2>
+ <ul class="post-list">
+ {%- for post in site.posts -%}
+ <li>
+ {%- assign date_format = site.minima.date_format | default: "%b %-d, %Y" -%}
+ <span class="post-meta">{{ post.date | date: date_format }}</span>
+ <h3>
+ <a class="post-link" href="{{ post.url | relative_url | remove: ".html" }}">
+ {{ post.title | escape }}
+ </a>
+ </h3>
+ {%- if site.show_excerpts -%}
+ {{ post.excerpt }}
+ {%- endif -%}
+ </li>
+ {%- endfor -%}
+ </ul>
+
+ <p class="feed-subscribe"><a href="{{ "/feed.xml" | relative_url }}">Subscribe</a></p>
+ {%- endif -%}
+
+</div>
diff --git a/_layouts/page.html b/_layouts/page.html
new file mode 100644
index 0000000..ce233ad
--- /dev/null
+++ b/_layouts/page.html
@@ -0,0 +1,14 @@
+---
+layout: default
+---
+<article class="post">
+
+ <header class="post-header">
+ <h1 class="post-title">{{ page.title }}</h1>
+ </header>
+
+ <div class="post-content">
+ {{ content }}
+ </div>
+
+</article>
diff --git a/_layouts/post.html b/_layouts/post.html
new file mode 100644
index 0000000..883ac22
--- /dev/null
+++ b/_layouts/post.html
@@ -0,0 +1,15 @@
+---
+layout: default
+---
+<article class="post" itemscope="" itemtype="http://schema.org/BlogPosting">
+
+ <header class="post-header">
+ <h1 class="post-title" itemprop="name headline">{{ page.title }}</h1>
+ <p class="post-meta"><time datetime="{{ page.date | date_to_xmlschema }}" itemprop="datePublished">{{ page.date | date: "%b %-d, %Y" }}</time>{% if page.author %} • <span itemprop="author" itemscope itemtype="http://schema.org/Person"><span itemprop="name">{{ page.author }}</span></span>{% endif %}</p>
+ </header>
+
+ <div class="post-content" itemprop="articleBody">
+ {{ content }}
+ </div>
+
+</article>
diff --git a/_sass/_base.scss b/_sass/_base.scss
new file mode 100644
index 0000000..815a2bb
--- /dev/null
+++ b/_sass/_base.scss
@@ -0,0 +1,203 @@
+/**
+ * Reset some basic elements
+ */
+body, h1, h2, h3, h4, h5, h6,
+p, blockquote, pre, hr,
+dl, dd, ol, ul, figure {
+ margin: 0;
+ padding: 0;
+}
+
+
+
+/**
+ * Basic styling
+ */
+body {
+ font: $base-font-weight #{$base-font-size}/#{$base-line-height} $base-font-family;
+ color: $text-color;
+ background-color: $background-color;
+ -webkit-text-size-adjust: 100%;
+ -webkit-font-feature-settings: "kern" 1;
+ -moz-font-feature-settings: "kern" 1;
+ -o-font-feature-settings: "kern" 1;
+ font-feature-settings: "kern" 1;
+ font-kerning: normal;
+}
+
+
+
+/**
+ * Set `margin-bottom` to maintain vertical rhythm
+ */
+h1, h2, h3, h4, h5, h6,
+p, blockquote, pre,
+ul, ol, dl, figure,
+%vertical-rhythm {
+ margin-bottom: $spacing-unit / 2;
+}
+
+
+
+/**
+ * Images
+ */
+img {
+ max-width: 100%;
+ vertical-align: middle;
+}
+
+
+
+/**
+ * Figures
+ */
+figure > img {
+ display: block;
+}
+
+figcaption {
+ font-size: $small-font-size;
+}
+
+
+
+/**
+ * Lists
+ */
+ul, ol {
+ margin-left: $spacing-unit;
+}
+
+li {
+ > ul,
+ > ol {
+ margin-bottom: 0;
+ }
+}
+
+
+
+/**
+ * Headings
+ */
+h1, h2, h3, h4, h5, h6 {
+ font-weight: $base-font-weight;
+}
+
+
+
+/**
+ * Links
+ */
+a {
+ color: $brand-color;
+ text-decoration: none;
+
+ &:visited {
+ color: darken($brand-color, 15%);
+ }
+
+ &:hover {
+ color: $text-color;
+ text-decoration: underline;
+ }
+}
+
+
+
+/**
+ * Blockquotes
+ */
+blockquote {
+ color: $grey-color;
+ border-left: 4px solid $grey-color-light;
+ padding-left: $spacing-unit / 2;
+ font-size: 18px;
+ letter-spacing: -1px;
+ font-style: italic;
+
+ > :last-child {
+ margin-bottom: 0;
+ }
+}
+
+
+
+/**
+ * Code formatting
+ */
+pre,
+code {
+ font-size: 15px;
+}
+
+code {
+ padding: 1px 5px;
+}
+
+pre {
+ padding: 8px 12px;
+ overflow-x: auto;
+
+ > code {
+ border: 0;
+ padding-right: 0;
+ padding-left: 0;
+ }
+}
+
+
+
+/**
+ * Wrapper
+ */
+.wrapper {
+ max-width: -webkit-calc(#{$content-width} - (#{$spacing-unit} * 2));
+ max-width: calc(#{$content-width} - (#{$spacing-unit} * 2));
+ margin-right: auto;
+ margin-left: auto;
+ padding-right: $spacing-unit;
+ padding-left: $spacing-unit;
+ @extend %clearfix;
+
+ @include media-query($on-laptop) {
+ max-width: -webkit-calc(#{$content-width} - (#{$spacing-unit}));
+ max-width: calc(#{$content-width} - (#{$spacing-unit}));
+ padding-right: $spacing-unit / 2;
+ padding-left: $spacing-unit / 2;
+ }
+}
+
+
+
+/**
+ * Clearfix
+ */
+%clearfix {
+
+ &:after {
+ content: "";
+ display: table;
+ clear: both;
+ }
+}
+
+
+
+/**
+ * Icons
+ */
+.icon {
+
+ > svg {
+ display: inline-block;
+ width: 16px;
+ height: 16px;
+ vertical-align: middle;
+
+ path {
+ fill: $grey-color;
+ }
+ }
+}
diff --git a/_sass/_layout.scss b/_sass/_layout.scss
new file mode 100644
index 0000000..9cbfdde
--- /dev/null
+++ b/_sass/_layout.scss
@@ -0,0 +1,242 @@
+/**
+ * Site header
+ */
+.site-header {
+ border-top: 5px solid $grey-color-dark;
+ border-bottom: 1px solid $grey-color-light;
+ min-height: 56px;
+
+ // Positioning context for the mobile navigation icon
+ position: relative;
+}
+
+.site-title {
+ font-size: 26px;
+ font-weight: 300;
+ line-height: 56px;
+ letter-spacing: -1px;
+ margin-bottom: 0;
+ float: left;
+
+ &,
+ &:visited {
+ color: $grey-color-dark;
+ }
+}
+
+.site-nav {
+ float: right;
+ line-height: 56px;
+
+ .menu-icon {
+ display: none;
+ }
+
+ .page-link {
+ color: $text-color;
+ line-height: $base-line-height;
+
+ // Gaps between nav items, but not on the last one
+ &:not(:last-child) {
+ margin-right: 20px;
+ }
+ }
+
+ @include media-query($on-palm) {
+ position: absolute;
+ top: 9px;
+ right: $spacing-unit / 2;
+ background-color: $background-color;
+ border: 1px solid $grey-color-light;
+ border-radius: 5px;
+ text-align: right;
+
+ .menu-icon {
+ display: block;
+ float: right;
+ width: 36px;
+ height: 26px;
+ line-height: 0;
+ padding-top: 10px;
+ text-align: center;
+
+ > svg {
+ width: 18px;
+ height: 15px;
+
+ path {
+ fill: $grey-color-dark;
+ }
+ }
+ }
+
+ .trigger {
+ clear: both;
+ display: none;
+ }
+
+ &:hover .trigger {
+ display: block;
+ padding-bottom: 5px;
+ }
+
+ .page-link {
+ display: block;
+ padding: 5px 10px;
+
+ &:not(:last-child) {
+ margin-right: 0;
+ }
+ margin-left: 20px;
+ }
+ }
+}
+
+
+
+/**
+ * Site footer
+ */
+.site-footer {
+ border-top: 1px solid $grey-color-light;
+ padding: $spacing-unit 0;
+}
+
+.footer-heading {
+ font-size: 18px;
+ margin-bottom: $spacing-unit / 2;
+}
+
+.contact-list,
+.social-media-list {
+ list-style: none;
+ margin-left: 0;
+}
+
+.footer-col-wrapper {
+ font-size: 15px;
+ color: $grey-color;
+ margin-left: -$spacing-unit / 2;
+ @extend %clearfix;
+}
+
+.footer-col {
+ float: left;
+ margin-bottom: $spacing-unit / 2;
+ padding-left: $spacing-unit / 2;
+}
+
+.footer-col-1 {
+ width: -webkit-calc(35% - (#{$spacing-unit} / 2));
+ width: calc(35% - (#{$spacing-unit} / 2));
+}
+
+.footer-col-2 {
+ width: -webkit-calc(20% - (#{$spacing-unit} / 2));
+ width: calc(20% - (#{$spacing-unit} / 2));
+}
+
+.footer-col-3 {
+ width: -webkit-calc(45% - (#{$spacing-unit} / 2));
+ width: calc(45% - (#{$spacing-unit} / 2));
+}
+
+@include media-query($on-laptop) {
+ .footer-col-1,
+ .footer-col-2 {
+ width: -webkit-calc(50% - (#{$spacing-unit} / 2));
+ width: calc(50% - (#{$spacing-unit} / 2));
+ }
+
+ .footer-col-3 {
+ width: -webkit-calc(100% - (#{$spacing-unit} / 2));
+ width: calc(100% - (#{$spacing-unit} / 2));
+ }
+}
+
+@include media-query($on-palm) {
+ .footer-col {
+ float: none;
+ width: -webkit-calc(100% - (#{$spacing-unit} / 2));
+ width: calc(100% - (#{$spacing-unit} / 2));
+ }
+}
+
+
+
+/**
+ * Page content
+ */
+.page-content {
+ padding: $spacing-unit 0;
+}
+
+.page-heading {
+ font-size: 20px;
+}
+
+.post-list {
+ margin-left: 0;
+ list-style: none;
+
+ > li {
+ margin-bottom: $spacing-unit;
+ }
+}
+
+.post-meta {
+ font-size: $small-font-size;
+ color: $grey-color;
+}
+
+.post-link {
+ display: block;
+ font-size: 24px;
+}
+
+
+
+/**
+ * Posts
+ */
+.post-header {
+ margin-bottom: $spacing-unit;
+}
+
+.post-title {
+ font-size: 42px;
+ letter-spacing: -1px;
+ line-height: 1;
+
+ @include media-query($on-laptop) {
+ font-size: 36px;
+ }
+}
+
+.post-content {
+ margin-bottom: $spacing-unit;
+
+ h2 {
+ font-size: 32px;
+
+ @include media-query($on-laptop) {
+ font-size: 28px;
+ }
+ }
+
+ h3 {
+ font-size: 26px;
+
+ @include media-query($on-laptop) {
+ font-size: 22px;
+ }
+ }
+
+ h4 {
+ font-size: 20px;
+
+ @include media-query($on-laptop) {
+ font-size: 18px;
+ }
+ }
+}
diff --git a/_sass/_normalize.scss b/_sass/_normalize.scss
new file mode 100644
index 0000000..08f8950
--- /dev/null
+++ b/_sass/_normalize.scss
@@ -0,0 +1,425 @@
+/*! normalize.css v3.0.1 | MIT License | git.io/normalize */
+
+/**
+ * 1. Set default font family to sans-serif.
+ * 2. Prevent iOS text size adjust after orientation change, without disabling
+ * user zoom.
+ */
+
+html {
+ font-family: sans-serif; /* 1 */
+ -ms-text-size-adjust: 100%; /* 2 */
+ -webkit-text-size-adjust: 100%; /* 2 */
+}
+
+/**
+ * Remove default margin.
+ */
+
+body {
+ margin: 0;
+}
+
+/* HTML5 display definitions
+ ========================================================================== */
+
+/**
+ * Correct `block` display not defined for any HTML5 element in IE 8/9.
+ * Correct `block` display not defined for `details` or `summary` in IE 10/11 and Firefox.
+ * Correct `block` display not defined for `main` in IE 11.
+ */
+
+article,
+aside,
+details,
+figcaption,
+figure,
+footer,
+header,
+hgroup,
+main,
+nav,
+section,
+summary {
+ display: block;
+}
+
+/**
+ * 1. Correct `inline-block` display not defined in IE 8/9.
+ * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.
+ */
+
+audio,
+canvas,
+progress,
+video {
+ display: inline-block; /* 1 */
+ vertical-align: baseline; /* 2 */
+}
+
+/**
+ * Prevent modern browsers from displaying `audio` without controls.
+ * Remove excess height in iOS 5 devices.
+ */
+
+audio:not([controls]) {
+ display: none;
+ height: 0;
+}
+
+/**
+ * Address `[hidden]` styling not present in IE 8/9/10.
+ * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22.
+ */
+
+[hidden],
+template {
+ display: none;
+}
+
+/* Links
+ ========================================================================== */
+
+/**
+ * Remove the gray background color from active links in IE 10.
+ */
+
+a {
+ background: transparent;
+}
+
+/**
+ * Improve readability when focused and also mouse hovered in all browsers.
+ */
+
+a:active,
+a:hover {
+ outline: 0;
+}
+
+/* Text-level semantics
+ ========================================================================== */
+
+/**
+ * Address styling not present in IE 8/9/10/11, Safari, and Chrome.
+ */
+
+abbr[title] {
+ border-bottom: 1px dotted;
+}
+
+/**
+ * Address style set to `bolder` in Firefox 4+, Safari, and Chrome.
+ */
+
+b,
+strong {
+ font-weight: bold;
+}
+
+/**
+ * Address styling not present in Safari and Chrome.
+ */
+
+dfn {
+ font-style: italic;
+}
+
+/**
+ * Address variable `h1` font-size and margin within `section` and `article`
+ * contexts in Firefox 4+, Safari, and Chrome.
+ */
+
+h1 {
+ font-size: 2em;
+ margin: 0.67em 0;
+}
+
+/**
+ * Address styling not present in IE 8/9.
+ */
+
+mark {
+ background: #ff0;
+ color: #000;
+}
+
+/**
+ * Address inconsistent and variable font size in all browsers.
+ */
+
+small {
+ font-size: 80%;
+}
+
+/**
+ * Prevent `sub` and `sup` affecting `line-height` in all browsers.
+ */
+
+sub,
+sup {
+ font-size: 75%;
+ line-height: 0;
+ position: relative;
+ vertical-align: baseline;
+}
+
+sup {
+ top: -0.5em;
+}
+
+sub {
+ bottom: -0.25em;
+}
+
+/* Embedded content
+ ========================================================================== */
+
+/**
+ * Remove border when inside `a` element in IE 8/9/10.
+ */
+
+img {
+ border: 0;
+}
+
+/**
+ * Correct overflow not hidden in IE 9/10/11.
+ */
+
+svg:not(:root) {
+ overflow: hidden;
+}
+
+/* Grouping content
+ ========================================================================== */
+
+/**
+ * Address margin not present in IE 8/9 and Safari.
+ */
+
+figure {
+ margin: 1em 40px;
+}
+
+/**
+ * Address differences between Firefox and other browsers.
+ */
+
+hr {
+ -moz-box-sizing: content-box;
+ box-sizing: content-box;
+ height: 0;
+}
+
+/**
+ * Contain overflow in all browsers.
+ */
+
+pre {
+ overflow: auto;
+}
+
+/**
+ * Address odd `em`-unit font size rendering in all browsers.
+ */
+
+code,
+kbd,
+pre,
+samp {
+ font-family: monospace, monospace;
+ font-size: 1em;
+}
+
+/* Forms
+ ========================================================================== */
+
+/**
+ * Known limitation: by default, Chrome and Safari on OS X allow very limited
+ * styling of `select`, unless a `border` property is set.
+ */
+
+/**
+ * 1. Correct color not being inherited.
+ * Known issue: affects color of disabled elements.
+ * 2. Correct font properties not being inherited.
+ * 3. Address margins set differently in Firefox 4+, Safari, and Chrome.
+ */
+
+button,
+input,
+optgroup,
+select,
+textarea {
+ color: inherit; /* 1 */
+ font: inherit; /* 2 */
+ margin: 0; /* 3 */
+}
+
+/**
+ * Address `overflow` set to `hidden` in IE 8/9/10/11.
+ */
+
+button {
+ overflow: visible;
+}
+
+/**
+ * Address inconsistent `text-transform` inheritance for `button` and `select`.
+ * All other form control elements do not inherit `text-transform` values.
+ * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.
+ * Correct `select` style inheritance in Firefox.
+ */
+
+button,
+select {
+ text-transform: none;
+}
+
+/**
+ * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
+ * and `video` controls.
+ * 2. Correct inability to style clickable `input` types in iOS.
+ * 3. Improve usability and consistency of cursor style between image-type
+ * `input` and others.
+ */
+
+button,
+html input[type="button"], /* 1 */
+input[type="reset"],
+input[type="submit"] {
+ -webkit-appearance: button; /* 2 */
+ cursor: pointer; /* 3 */
+}
+
+/**
+ * Re-set default cursor for disabled elements.
+ */
+
+button[disabled],
+html input[disabled] {
+ cursor: default;
+}
+
+/**
+ * Remove inner padding and border in Firefox 4+.
+ */
+
+button::-moz-focus-inner,
+input::-moz-focus-inner {
+ border: 0;
+ padding: 0;
+}
+
+/**
+ * Address Firefox 4+ setting `line-height` on `input` using `!important` in
+ * the UA stylesheet.
+ */
+
+input {
+ line-height: normal;
+}
+
+/**
+ * It's recommended that you don't attempt to style these elements.
+ * Firefox's implementation doesn't respect box-sizing, padding, or width.
+ *
+ * 1. Address box sizing set to `content-box` in IE 8/9/10.
+ * 2. Remove excess padding in IE 8/9/10.
+ */
+
+input[type="checkbox"],
+input[type="radio"] {
+ box-sizing: border-box; /* 1 */
+ padding: 0; /* 2 */
+}
+
+/**
+ * Fix the cursor style for Chrome's increment/decrement buttons. For certain
+ * `font-size` values of the `input`, it causes the cursor style of the
+ * decrement button to change from `default` to `text`.
+ */
+
+input[type="number"]::-webkit-inner-spin-button,
+input[type="number"]::-webkit-outer-spin-button {
+ height: auto;
+}
+
+/**
+ * 1. Address `appearance` set to `searchfield` in Safari and Chrome.
+ * 2. Address `box-sizing` set to `border-box` in Safari and Chrome
+ * (include `-moz` to future-proof).
+ */
+
+input[type="search"] {
+ -webkit-appearance: textfield; /* 1 */
+ -moz-box-sizing: content-box;
+ -webkit-box-sizing: content-box; /* 2 */
+ box-sizing: content-box;
+}
+
+/**
+ * Remove inner padding and search cancel button in Safari and Chrome on OS X.
+ * Safari (but not Chrome) clips the cancel button when the search input has
+ * padding (and `textfield` appearance).
+ */
+
+input[type="search"]::-webkit-search-cancel-button,
+input[type="search"]::-webkit-search-decoration {
+ -webkit-appearance: none;
+}
+
+/**
+ * Define consistent border, margin, and padding.
+ */
+
+fieldset {
+ border: 1px solid #c0c0c0;
+ margin: 0 2px;
+ padding: 0.35em 0.625em 0.75em;
+}
+
+/**
+ * 1. Correct `color` not being inherited in IE 8/9/10/11.
+ * 2. Remove padding so people aren't caught out if they zero out fieldsets.
+ */
+
+legend {
+ border: 0; /* 1 */
+ padding: 0; /* 2 */
+}
+
+/**
+ * Remove default vertical scrollbar in IE 8/9/10/11.
+ */
+
+textarea {
+ overflow: auto;
+}
+
+/**
+ * Don't inherit the `font-weight` (applied by a rule above).
+ * NOTE: the default cannot safely be changed in Chrome and Safari on OS X.
+ */
+
+optgroup {
+ font-weight: bold;
+}
+
+/* Tables
+ ========================================================================== */
+
+/**
+ * Remove most spacing between table cells.
+ */
+
+table {
+ border-collapse: collapse;
+ border-spacing: 0;
+}
+
+td,
+th {
+ padding: 0;
+}
diff --git a/_sass/_syntax-highlighting.scss b/_sass/_syntax-highlighting.scss
new file mode 100644
index 0000000..264f42a
--- /dev/null
+++ b/_sass/_syntax-highlighting.scss
@@ -0,0 +1,72 @@
+/**
+ * Syntax highlighting styles
+ */
+.highlight {
+ color: #000;
+ background: #fff;
+ @extend %vertical-rhythm;
+
+ .highlighter-rouge & {
+ background: #eef;
+ }
+
+ .c { color: #998; font-style: italic } // Comment
+ .err { color: #a61717; background-color: #e3d2d2 } // Error
+ .k { font-weight: bold } // Keyword
+ .o { font-weight: bold } // Operator
+ .cm { color: #998; font-style: italic } // Comment.Multiline
+ .cp { color: #999; font-weight: bold } // Comment.Preproc
+ .c1 { color: #998; font-style: italic } // Comment.Single
+ .cs { color: #999; font-weight: bold; font-style: italic } // Comment.Special
+ .gd { color: #000; background-color: #fdd } // Generic.Deleted
+ .gd .x { color: #000; background-color: #faa } // Generic.Deleted.Specific
+ .ge { font-style: italic } // Generic.Emph
+ .gr { color: #a00 } // Generic.Error
+ .gh { color: #999 } // Generic.Heading
+ .gi { color: #000; background-color: #dfd } // Generic.Inserted
+ .gi .x { color: #000; background-color: #afa } // Generic.Inserted.Specific
+ .go { color: #888 } // Generic.Output
+ .gp { color: #555 } // Generic.Prompt
+ .gs { font-weight: bold } // Generic.Strong
+ .gu { color: #aaa } // Generic.Subheading
+ .gt { color: #a00 } // Generic.Traceback
+ .kc { font-weight: bold } // Keyword.Constant
+ .kd { font-weight: bold } // Keyword.Declaration
+ .kp { font-weight: bold } // Keyword.Pseudo
+ .kr { font-weight: bold } // Keyword.Reserved
+ .kt { color: #458; font-weight: bold } // Keyword.Type
+ .m { color: #099 } // Literal.Number
+ .s { color: #d14 } // Literal.String
+ .na { color: #008080 } // Name.Attribute
+ .nb { color: #0086B3 } // Name.Builtin
+ .nc { color: #458; font-weight: bold } // Name.Class
+ .no { color: #008080 } // Name.Constant
+ .ni { color: #800080 } // Name.Entity
+ .ne { color: #900; font-weight: bold } // Name.Exception
+ .nf { color: #900; font-weight: bold } // Name.Function
+ .nn { color: #555 } // Name.Namespace
+ .nt { color: #000080 } // Name.Tag
+ .nv { color: #008080 } // Name.Variable
+ .ow { font-weight: bold } // Operator.Word
+ .w { color: #bbb } // Text.Whitespace
+ .mf { color: #099 } // Literal.Number.Float
+ .mh { color: #099 } // Literal.Number.Hex
+ .mi { color: #099 } // Literal.Number.Integer
+ .mo { color: #099 } // Literal.Number.Oct
+ .sb { color: #d14 } // Literal.String.Backtick
+ .sc { color: #d14 } // Literal.String.Char
+ .sd { color: #d14 } // Literal.String.Doc
+ .s2 { color: #d14 } // Literal.String.Double
+ .se { color: #d14 } // Literal.String.Escape
+ .sh { color: #d14 } // Literal.String.Heredoc
+ .si { color: #d14 } // Literal.String.Interpol
+ .sx { color: #d14 } // Literal.String.Other
+ .sr { color: #009926 } // Literal.String.Regex
+ .s1 { color: #d14 } // Literal.String.Single
+ .ss { color: #990073 } // Literal.String.Symbol
+ .bp { color: #999 } // Name.Builtin.Pseudo
+ .vc { color: #008080 } // Name.Variable.Class
+ .vg { color: #008080 } // Name.Variable.Global
+ .vi { color: #008080 } // Name.Variable.Instance
+ .il { color: #099 } // Literal.Number.Integer.Long
+}
diff --git a/build/Dockerfile.build.erb b/build/Dockerfile.build.erb
new file mode 100644
index 0000000..acb15e6
--- /dev/null
+++ b/build/Dockerfile.build.erb
@@ -0,0 +1,3 @@
+<%= erb 'build/templates/Dockerfile.base.erb' -%>
+
+<%= erb 'build/templates/Dockerfile.cmd.erb' -%>
diff --git a/build/Dockerfile.deploy.erb b/build/Dockerfile.deploy.erb
new file mode 100644
index 0000000..ab44111
--- /dev/null
+++ b/build/Dockerfile.deploy.erb
@@ -0,0 +1,5 @@
+<%= erb 'build/templates/Dockerfile.base.erb' -%>
+
+RUN rm -fr /var/lib/gems && apt-get -y purge jekyll rake && apt-get -y autoremove
+
+<%= erb 'build/templates/Dockerfile.cmd.erb' -%>
diff --git a/build/apache.conf b/build/apache.conf
new file mode 100644
index 0000000..b661eaa
--- /dev/null
+++ b/build/apache.conf
@@ -0,0 +1,21 @@
+Listen ${PORT}
+
+<VirtualHost *>
+ ServerName sidewalk.crustytoothpaste.net
+
+ ServerAdmin webmaster@crustytoothpaste.net
+ DocumentRoot /var/www/html
+
+ ErrorLog ${APACHE_LOG_DIR}/error.log
+ CustomLog ${APACHE_LOG_DIR}/access.log combined
+
+ AddType application/xhtml+xml .xhtml
+
+ Header append Cache-Control "public; s-maxage=86400" "expr=%{REQUEST_STATUS} == 200"
+
+ ErrorDocument 404 /404.xhtml
+
+ <Location />
+ Options +MultiViews -Indexes
+ </Location>
+</VirtualHost>
diff --git a/build/templates/Dockerfile.base.erb b/build/templates/Dockerfile.base.erb
new file mode 100644
index 0000000..55aab66
--- /dev/null
+++ b/build/templates/Dockerfile.base.erb
@@ -0,0 +1,27 @@
+FROM debian:buster-slim
+
+ENV DEBIAN_FRONTEND=noninteractive
+ENV PORT 8080
+
+RUN apt-get update && \
+ apt-get -y upgrade && \
+ apt-get -y --no-install-recommends install \
+ apache2 jekyll rake busybox-static mime-support && \
+ rm -fr /var/lib/apt/lists
+
+RUN gem install jekyll-asciidoc -v 2.1.0
+
+RUN a2enmod negotiation headers
+
+RUN mkdir -p /var/run/apache2 && rm -fr /var/www/html/*
+
+COPY . /usr/src/site/
+
+RUN cp /usr/src/site/build/apache.conf /etc/apache2/sites-enabled/000-default.conf
+
+RUN cd /usr/src/site && \
+ rake build && \
+ rake check && \
+ cp -a _site/* /var/www/html
+
+# vim: set ft=dockerfile:
diff --git a/build/templates/Dockerfile.cmd.erb b/build/templates/Dockerfile.cmd.erb
new file mode 100644
index 0000000..7894c99
--- /dev/null
+++ b/build/templates/Dockerfile.cmd.erb
@@ -0,0 +1,3 @@
+CMD ["/bin/sh", "-c", ". /etc/apache2/envvars && /usr/sbin/apache2 -DFOREGROUND"]
+
+# vim: set ft=dockerfile:
diff --git a/css/main.scss b/css/main.scss
new file mode 100644
index 0000000..187c399
--- /dev/null
+++ b/css/main.scss
@@ -0,0 +1,53 @@
+---
+# Only the main Sass file needs front matter (the dashes are enough)
+---
+@charset "utf-8";
+
+
+
+// Our variables
+$base-font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+$base-font-size: 16px;
+$base-font-weight: 400;
+$small-font-size: $base-font-size * 0.875;
+$base-line-height: 1.5;
+
+$spacing-unit: 30px;
+
+$text-color: #eee;
+$background-color: #000f89;
+$brand-color: #4bde97;
+
+$grey-color: #ddd;
+$grey-color-light: lighten($grey-color, 40%);
+$grey-color-dark: darken($grey-color, 25%);
+
+// Width of the content area
+$content-width: 800px;
+
+$on-palm: 600px;
+$on-laptop: 800px;
+
+
+
+// Use media queries like this:
+// @include media-query($on-palm) {
+// .wrapper {
+// padding-right: $spacing-unit / 2;
+// padding-left: $spacing-unit / 2;
+// }
+// }
+@mixin media-query($device) {
+ @media screen and (max-width: $device) {
+ @content;
+ }
+}
+
+
+
+// Import partials from `sass_dir` (defaults to `_sass`)
+@import
+ "base",
+ "layout",
+ "syntax-highlighting"
+;
diff --git a/firebase.json b/firebase.json
new file mode 100644
index 0000000..5453294
--- /dev/null
+++ b/firebase.json
@@ -0,0 +1,19 @@
+{
+ "hosting": {
+ "public": "public",
+ "ignore": [
+ "firebase.json",
+ "**/.*",
+ "**/node_modules/**"
+ ],
+ "rewrites": [
+ {
+ "source": "**",
+ "run": {
+ "serviceId": "blog",
+ "region": "us-central1"
+ }
+ }
+ ]
+ }
+}
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..e4d427d
--- /dev/null
+++ b/index.html
@@ -0,0 +1,3 @@
+---
+layout: home
+---
diff --git a/public/.gitignore b/public/.gitignore
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/public/.gitignore