65c17aa7972b lisp

Add the simple pages and photo galleries
[view raw] [browse files]
author Steve Losh <steve@stevelosh.com>
date Sun, 05 Jan 2020 18:21:15 -0500
parents d20bad4b886f
children 14a9e325836e
branches/tags lisp
files .ffignore .lispwords Makefile build.sh content/links.markdown content/photography/iceland/index.markdown content/photography/plants/index.markdown content/photography/scotland/index.markdown content/projects.markdown deploy.sh generate.lisp static/style.css

Changes

--- a/.ffignore	Sat Jan 04 23:39:05 2020 -0500
+++ b/.ffignore	Sun Jan 05 18:21:15 2020 -0500
@@ -1,2 +1,1 @@
-deploy
-public
+build
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.lispwords	Sun Jan 05 18:21:15 2020 -0500
@@ -0,0 +1,1 @@
+(2 render)
--- a/Makefile	Sat Jan 04 23:39:05 2020 -0500
+++ b/Makefile	Sun Jan 05 18:21:15 2020 -0500
@@ -1,43 +1,15 @@
-.PHONY: clean generate serve deploy css
-
-files := $(shell hg files)
-less := $(shell ffind --literal '.less')
-style := $(subst .less,.css,$(less))
-
 photos := $(shell ffind 'static/media/images/photography/photos/.*/.*.jpg' --entire)
 thumbs := $(subst photos,thumbnails,$(photos))
 
 THUMBNAIL_CMD = convert $< -resize "200^>" -gravity center -crop 200x200+0+0 -strip $@
 
-# Main ------------------------------------------------------------------------
-public/index.html: $(files) # $(style)
-	hugo -t stevelosh
-
-generate: public/index.html
-
-clean:
-	rm -rf public
-
-serve:
-	hugo server -t stevelosh -D
-
-deploy: public/index.html
-	rsync -avz ./public/ sl:/var/www/stevelosh.com
-
-# CSS -------------------------------------------------------------------------
-# css: $(style)
-
-# static/media/css/%.css: static/media/css/%.less
-# 	lessc $< > $@
-
-# Image Gallery Hell ----------------------------------------------------------
 thumbnails: $(thumbs)
 
 static/media/images/photography/thumbnails/plants/%.jpg: static/media/images/photography/photos/plants/%.jpg
 	$(THUMBNAIL_CMD)
+
 static/media/images/photography/thumbnails/scotland/%.jpg: static/media/images/photography/photos/scotland/%.jpg
 	$(THUMBNAIL_CMD)
+
 static/media/images/photography/thumbnails/iceland/%.jpg: static/media/images/photography/photos/iceland/%.jpg
 	$(THUMBNAIL_CMD)
-static/media/images/photography/thumbnails/dancing/%.jpg: static/media/images/photography/photos/dancing/%.jpg
-	$(THUMBNAIL_CMD)
--- a/build.sh	Sat Jan 04 23:39:05 2020 -0500
+++ b/build.sh	Sun Jan 05 18:21:15 2020 -0500
@@ -2,6 +2,7 @@
 
 set -euo pipefail
 
+make thumbnails
 mkdir -p build
 sbcl --non-interactive --load generate.lisp --eval '(stevelosh.com:toplevel)'
 rsync -avd static/ build/static
--- a/content/links.markdown	Sat Jan 04 23:39:05 2020 -0500
+++ b/content/links.markdown	Sun Jan 05 18:21:15 2020 -0500
@@ -1,9 +1,6 @@
-+++
-date = "2016-06-20T13:17:43Z"
-draft = false
-title = "Links"
-
-+++
+(:title "Links"
+ :date "2016-06-20T13:17:43Z"
+ :draft nil)
 
 This page is a collection of links to blogs/resources I find interesting.
 
--- a/content/photography/iceland/index.markdown	Sat Jan 04 23:39:05 2020 -0500
+++ b/content/photography/iceland/index.markdown	Sun Jan 05 18:21:15 2020 -0500
@@ -1,149 +1,8 @@
-+++
-date = "2017-07-28T00:00:00Z"
-draft = false
-title = "Iceland"
-lightbox = true
-
-+++
+(:title "Iceland"
+ :date "2017-07-28T00:00:00Z"
+ :draft false
+ :gallery "iceland"
+ :snip "Two years (plus a bit) in Iceland.")
 
 In 2015 I quit my job and moved to Iceland for graduate school.  Two years, one
 Master's degree, and ten thousand photographs later I moved back to the states.
-
-<section data-featherlight-gallery data-featherlight-filter="a">
-{{< gallery-link "iceland/stevelosh.com-_1030948.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1030974.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1030975.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1040016.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1040234.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1040308.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1040348.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1040439.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1040474.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1040508.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1040559.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1040592.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1040735.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1040745.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1040760.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1040858.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1040928.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1050112.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1050121.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1050232.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1050307.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1050323.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1050347.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1050454.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1050480.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1050489.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1050499.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1050656.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1050681.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1050703.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1050752.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1050819.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1050822.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1050833.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1050848.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1060135.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1060138.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1060147.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1060230.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1060233.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1060273.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1060288.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1060300.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1060313.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1060423.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1060458.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1060464.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1060491.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1060806.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1060816.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1070256.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1070264.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1070271.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1070289.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1070305.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1070311.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1070426.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1070444.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1070464.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1070507.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1070589.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1070647.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1070785.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1070886.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1080175.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1080246.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1080255.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1080314.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1080322.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1080339.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1080353.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1080364.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1080382.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1080416.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1080531.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1080725.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1080751.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1080803.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1080828.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1080900.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1090053.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1090092.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_1090229.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_SJL0509.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_SJL0511.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_SJL0550.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_SJL0556.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_SJL0608.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_SJL0883.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_SJL0911.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_SJL1022.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_SJL1199.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_SJL1528.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_SJL1585.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_SJL1597.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_SJL1803.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_SJL1810.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_SJL1859.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_SJL1866.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_SJL1981.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_SJL2051.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_SJL2146.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_SJL2294.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_SJL2334.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_SJL2500.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_SJL2523.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_SJL2538.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_SJL2652.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_SJL2732.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_SJL2753.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_SJL2772.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_SJL2783.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_SJL2809.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_SJL2900.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_SJL2970.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_SJL3007.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_SJL3150.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_SJL3197.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_SJL3270.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_SJL3300.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_SJL3382.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_SJL3442.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_SJL3525.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_SJL3640.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_SJL3745.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_SJL3760.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_SJL3780.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_SJL3852.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_SJL3875.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_SJL3952.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_SJL3972.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_SJL3992.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_SJL4020.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_SJL4083.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_SJL4124.jpg" >}}
-{{< gallery-link "iceland/stevelosh.com-_SJL4155.jpg" >}}
-</section>
--- a/content/photography/plants/index.markdown	Sat Jan 04 23:39:05 2020 -0500
+++ b/content/photography/plants/index.markdown	Sun Jan 05 18:21:15 2020 -0500
@@ -1,112 +1,13 @@
-+++
-date = "2017-07-28T00:00:00Z"
-draft = false
-title = "Plants"
-lightbox = true
-
-+++
+(:title "Plants"
+ :date "2017-07-28T00:00:00Z"
+ :draft false
+ :gallery "plants"
+ :snip "Photographs of plants, inspired by Blossfeldt.")
 
-
-
-This project started as a joke.
-
-I posted a few photographs of plants on Instagram alongside my other photos.
-Purely by accident I posted one plant every three images, and because Instagram
-shows thumbnails in three columns it ended up forming a nice line of sepia-toned
-thumbnails on my profile.
+This project started as a joke.  I posted a few photographs of plants on
+Instagram alongside my other photos.  Purely by accident I posted one plant
+every three images, and because Instagram shows thumbnails in three columns it
+ended up forming a nice line of sepia-toned thumbnails on my profile.
 
 I decided to keep up the rhythm for a while because it looked nice, and two
 years later I'm still making plant photos.
-
-<section data-featherlight-gallery data-featherlight-filter="a">
-{{< gallery-link "plants/stevelosh.com-_1030180.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1030230.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1030233.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1030236.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1030243.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1030308.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1030327.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1030328.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1030397.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1030719.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1030754.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1030793.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1030798.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1030800.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1030812.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1030836.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1030845.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1030852.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1040671.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1040685.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1040888.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1040915.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1040929.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1040950.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1050019.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1050043.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1050048.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1050087.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1050236.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1050243.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1050333.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1050438.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1050570.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1050632.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1050637.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1050642.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1050644.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1050653.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1050708.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1050722.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1050744.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1050748.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1050840.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1050959.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1050974.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1050993.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1050998.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1060015.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1060025.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1060033.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1060066.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1060076.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1060078.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1060087.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1060490.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1060576.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1060587.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1060588.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1060595.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1060599.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1060621.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1060625.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1060652.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1060945.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1070333.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1070373.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1070511.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1070524.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1070905.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1070927.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1070953.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1070960.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1070977.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1070981.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1080002.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1080018.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1080043.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1080064.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1080085.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1080113.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1080128.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1080145.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1080164.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1080199.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1080200.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1080214.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1080235.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1080241.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1090014.jpg" >}}
-{{< gallery-link "plants/stevelosh.com-_1090038.jpg" >}}
-</section>
--- a/content/photography/scotland/index.markdown	Sat Jan 04 23:39:05 2020 -0500
+++ b/content/photography/scotland/index.markdown	Sun Jan 05 18:21:15 2020 -0500
@@ -1,60 +1,8 @@
-+++
-date = "2017-07-28T00:00:00Z"
-draft = false
-title = "Scotland"
-lightbox = true
-
-+++
+(:title "Scotland"
+ :date "2017-07-28T00:00:00Z"
+ :draft false
+ :gallery "scotland"
+ :snip "Two weeks in Scotland.")
 
 In 2014 I spent two weeks in Scotland for my birthday.  I rented a car and
 traveled around, photographing as much as I could.
-
-<section data-featherlight-gallery data-featherlight-filter="a">
-{{< gallery-link "scotland/stevelosh.com-SJL_5468.jpg" >}}
-{{< gallery-link "scotland/stevelosh.com-SJL_5492.jpg" >}}
-{{< gallery-link "scotland/stevelosh.com-SJL_5509.jpg" >}}
-{{< gallery-link "scotland/stevelosh.com-SJL_5513.jpg" >}}
-{{< gallery-link "scotland/stevelosh.com-SJL_5563.jpg" >}}
-{{< gallery-link "scotland/stevelosh.com-SJL_5584.jpg" >}}
-{{< gallery-link "scotland/stevelosh.com-SJL_5599.jpg" >}}
-{{< gallery-link "scotland/stevelosh.com-SJL_5602.jpg" >}}
-{{< gallery-link "scotland/stevelosh.com-SJL_5710.jpg" >}}
-{{< gallery-link "scotland/stevelosh.com-SJL_5743.jpg" >}}
-{{< gallery-link "scotland/stevelosh.com-SJL_5746.jpg" >}}
-{{< gallery-link "scotland/stevelosh.com-SJL_5748.jpg" >}}
-{{< gallery-link "scotland/stevelosh.com-SJL_5759.jpg" >}}
-{{< gallery-link "scotland/stevelosh.com-SJL_5786.jpg" >}}
-{{< gallery-link "scotland/stevelosh.com-SJL_5788.jpg" >}}
-{{< gallery-link "scotland/stevelosh.com-SJL_5855.jpg" >}}
-{{< gallery-link "scotland/stevelosh.com-SJL_5948.jpg" >}}
-{{< gallery-link "scotland/stevelosh.com-SJL_5971.jpg" >}}
-{{< gallery-link "scotland/stevelosh.com-SJL_6006.jpg" >}}
-{{< gallery-link "scotland/stevelosh.com-SJL_6134.jpg" >}}
-{{< gallery-link "scotland/stevelosh.com-SJL_6243.jpg" >}}
-{{< gallery-link "scotland/stevelosh.com-SJL_6378.jpg" >}}
-{{< gallery-link "scotland/stevelosh.com-SJL_6600.jpg" >}}
-{{< gallery-link "scotland/stevelosh.com-SJL_6611.jpg" >}}
-{{< gallery-link "scotland/stevelosh.com-SJL_6722.jpg" >}}
-{{< gallery-link "scotland/stevelosh.com-SJL_6781.jpg" >}}
-{{< gallery-link "scotland/stevelosh.com-SJL_6785.jpg" >}}
-{{< gallery-link "scotland/stevelosh.com-SJL_6818.jpg" >}}
-{{< gallery-link "scotland/stevelosh.com-SJL_6903.jpg" >}}
-{{< gallery-link "scotland/stevelosh.com-SJL_6953.jpg" >}}
-{{< gallery-link "scotland/stevelosh.com-SJL_7027.jpg" >}}
-{{< gallery-link "scotland/stevelosh.com-SJL_7099.jpg" >}}
-{{< gallery-link "scotland/stevelosh.com-SJL_7167.jpg" >}}
-{{< gallery-link "scotland/stevelosh.com-SJL_7236.jpg" >}}
-{{< gallery-link "scotland/stevelosh.com-SJL_7246.jpg" >}}
-{{< gallery-link "scotland/stevelosh.com-SJL_7411.jpg" >}}
-{{< gallery-link "scotland/stevelosh.com-SJL_7435.jpg" >}}
-{{< gallery-link "scotland/stevelosh.com-SJL_7490.jpg" >}}
-{{< gallery-link "scotland/stevelosh.com-SJL_7582.jpg" >}}
-{{< gallery-link "scotland/stevelosh.com-SJL_7604.jpg" >}}
-{{< gallery-link "scotland/stevelosh.com-SJL_7644.jpg" >}}
-{{< gallery-link "scotland/stevelosh.com-SJL_7711.jpg" >}}
-{{< gallery-link "scotland/stevelosh.com-SJL_7717.jpg" >}}
-{{< gallery-link "scotland/stevelosh.com-SJL_7789.jpg" >}}
-{{< gallery-link "scotland/stevelosh.com-SJL_7965.jpg" >}}
-{{< gallery-link "scotland/stevelosh.com-SJL_7985.jpg" >}}
-{{< gallery-link "scotland/stevelosh.com-SJL_8086.jpg" >}}
-</section>
--- a/content/projects.markdown	Sat Jan 04 23:39:05 2020 -0500
+++ b/content/projects.markdown	Sun Jan 05 18:21:15 2020 -0500
@@ -1,9 +1,6 @@
-+++
-date = "2016-12-28T17:50:11Z"
-draft = false
-title = "Projects"
-
-+++
+(:title "Projects"
+ :date "2016-12-28T17:50:11Z"
+ :draft nil)
 
 The following is a list of projects I've created.  They're grouped by
 maintenance status:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/deploy.sh	Sun Jan 05 18:21:15 2020 -0500
@@ -0,0 +1,7 @@
+#!/usr/bin/env bash
+
+set -euo pipefail
+
+./build.sh
+rsync -avz ./build/ sl:/var/www/stevelosh.com
+heading smslant 'Deployed'
--- a/generate.lisp	Sat Jan 04 23:39:05 2020 -0500
+++ b/generate.lisp	Sun Jan 05 18:21:15 2020 -0500
@@ -1,5 +1,7 @@
-(ql:quickload (list :alexandria :iterate :losh :local-time
-                    :cl-who :3bmd :3bmd-ext-code-blocks))
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (ql:quickload (list :alexandria :iterate :losh :local-time
+                      :cl-who :3bmd :3bmd-ext-code-blocks)
+                :silent t))
 
 (defpackage :stevelosh.com
   (:use :cl :iterate :losh)
@@ -24,6 +26,64 @@
 (defmacro who (&body body)
   `(with-html-output (*standard-output*) ,@body))
 
+(defmacro delay (&body body)
+  `(let (result done)
+     (lambda ()
+       (if done
+         result
+         (setf done t result (progn ,@body))))))
+
+(defun force (delay)
+  (funcall delay))
+
+(defun cat (&rest strings)
+  (apply #'concatenate 'string strings))
+
+
+;;;; Content ------------------------------------------------------------------
+(defclass* content ()
+  (input-path output-path date modified-timestamp body
+   url title draft gallery snip
+   (mathjax :initform nil)))
+
+(defun parse-markdown (path)
+  (with-open-file (stream path :direction :input)
+    (read stream) ; discard metadata this time
+    (with-output-to-string (string)
+      (3bmd:parse-string-and-print-to-stream
+        (alexandria:read-stream-content-into-string stream)
+        string))))
+
+(defun read-content (path)
+  (with-open-file (s path :direction :input)
+    (let ((metadata (if (string= #\left_parenthesis (peek-char nil s))
+                      (read s)
+                      (return-from read-content nil))))
+      (callf (getf metadata :date) #'local-time:parse-rfc3339-timestring)
+      (apply
+        #'make-instance 'content
+        :input-path path
+        :output-path (ppcre:regex-replace "content/(.*)\\.markdown" path "build/\\1/index.html")
+        :url (ppcre:regex-replace "content/(.*)\\.markdown" path "/\\1/")
+        :modified-timestamp (file-write-date path)
+        :body (delay (parse-markdown path))
+        metadata))))
+
+(defun walk (path)
+  (-<> (sh (list "find" path "-name" "*.markdown") :result-type 'list)
+    (mapcar #'read-content <>)
+    (remove nil <>)
+    (sort <> #'local-time:timestamp> :key #'date)))
+
+(defun gallery-photos (gallery)
+  (let* ((slug (gallery gallery))
+         (photo-path (cat "static/images/photography/photos/" slug))
+         (thumb-path (cat "static/images/photography/thumbnails/" slug))
+         (files (sh (list "ls" "-1" photo-path) :result-type 'list)))
+    (loop :for file :in files
+          :collect (cons (cat "/" photo-path "/" file)
+                         (cat "/" thumb-path "/" file)))))
+
 
 ;;;; Base Templates -----------------------------------------------------------
 (defun t/header ()
@@ -73,28 +133,62 @@
   (who (str "<script type=\"text/javascript\" async
                      src=\"https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js?config=TeX-AMS-MML_HTMLorMML\"></script>")))
 
-(defun t/blog/index/item (entry)
+
+(defun t/index-item (item)
   (who
-    (:li
-     (:a :href (getf entry :url) (str (getf entry :title)))
-     (:p :class "entry-date" (str (human-date (getf entry :date))))
-     (:p :class "snippet" (str (getf entry :snip))))))
+    (:li :class "item"
+     (:a :href (url item) (str (title item)))
+     (:p :class "date" (str (human-date (date item))))
+     (:p :class "snippet" (str (snip item))))))
+
+(defun t/index (items)
+  (who (:ol :class "index" (map nil #'t/index-item items))))
+
 
 (defun t/blog/index (entries)
   (with-base ("blog-index" "Blog")
-    (who
-      (:ul (map nil #'t/blog/index/item entries)))))
+    (t/index entries)))
 
 (defun t/blog/entry (entry)
-  (with-base ("blog-entry" (getf entry :title))
+  (with-base ("blog-entry" (title entry))
     (who
       (:article
-       (when (getf entry :mathjax) (t/mathjax))
-       (:h1 (:a :href (str (getf entry :url))
-             (str (getf entry :title))))
-       (:p :class "entry-date"
-        "Posted on " (str (human-date (getf entry :date))) ".")
-       (str (getf entry :body))))))
+       (when (mathjax entry) (t/mathjax))
+       (:h1 (:a :href (url entry) (str (title entry))))
+       (:p :class "date"
+        "Posted on " (str (human-date (date entry))) ".")
+       (str (force (body entry)))))))
+
+
+(defun t/photography/index (galleries)
+  (with-base ("photography-index" "Photography")
+    (t/index galleries)))
+
+
+(defun t/photography/gallery/photo (photo)
+  (destructuring-bind (photo . thumb) photo
+    (who (:li (:a :href photo (:img :src thumb))))))
+
+(defun t/photography/gallery (gallery)
+  (with-base ("photography-gallery" (title gallery))
+    (who
+      (:article
+       (:h1 (:a :href (url gallery) (str (title gallery))))
+       (:p :class "date"
+        "Last updated on " (str (human-date (date gallery))) ".")
+       (str (force (body gallery)))
+       (:ul
+        (map nil #'t/photography/gallery/photo (gallery-photos gallery)))))))
+
+
+(defun t/simple (content)
+  (with-base ("simple" (title content))
+    (who
+      (:article
+       (:h1 (:a :href (url content) (str (title content))))
+       (:p :class "date"
+        "Last updated on " (str (human-date (date content))) ".")
+       (str (force (body content)))))))
 
 (defun t/home ()
   (with-base ("home")
@@ -108,67 +202,73 @@
        " is best."))))
 
 
-;;;; Markdown -----------------------------------------------------------------
-(defun parse-markdown-stream (stream)
-  (with-output-to-string (s)
-    (3bmd:parse-string-and-print-to-stream
-     (alexandria:read-stream-content-into-string stream)
-     s)))
+;;;; Generation ---------------------------------------------------------------
+(defparameter *generate-timestamp* (file-write-date "generate.lisp"))
+
+(defun needs-render-p (path times)
+  (or (null (probe-file path))
+      (let ((prev (file-write-date path)))
+        (or (> *generate-timestamp* prev)
+            (some (lambda (time) (> time prev))
+                  (alexandria:ensure-list times))))))
 
-(defun read-markdown-file (path)
-  (with-open-file (s path :direction :input)
-    (let ((metadata (if (string= #\left_parenthesis (peek-char nil s))
-                      (read s)
-                      (return-from read-markdown-file nil)))
-          (body (parse-markdown-stream s)))
-      (append
-        (list :body body
-              :input-path path
-              :date (when-let ((d (getf metadata :date)))
-                      (local-time:parse-rfc3339-timestring d))
-              :output-path (ppcre:regex-replace "content/(.*)\\.markdown" path "build/\\1/index.html")
-              :url (ppcre:regex-replace "content/(.*)\\.markdown" path "/\\1/"))
-        metadata))))
-
+(defun render% (path times thunk)
+  (if (needs-render-p path times)
+    (progn
+      (format t "Rendering ~S~%" path)
+      (ensure-directories-exist path)
+      (with-open-file (*standard-output* path
+                                         :direction :output
+                                         :if-exists :supersede)
+        (with-html-output (*standard-output* nil :prologue t)
+          (funcall thunk))))
+    #+no (format t "Skipping ~S, file is up to date.~%" path)))
 
-;;;; Data ---------------------------------------------------------------------
-(defun walk (path)
-  (-<> (sh (list "find" path "-name" "*.markdown") :result-type 'list)
-    (sort <> #'string>)
-    (mapcar #'read-markdown-file <>)
-    (remove nil <>)))
-
-
-;;;; Generation ---------------------------------------------------------------
-(defmacro render (path &body body)
-  `(progn
-     (ensure-directories-exist ,path)
-     (with-open-file (*standard-output* ,path
-                                        :direction :output
-                                        :if-exists :supersede)
-       (with-html-output (*standard-output* nil :prologue t)
-         ,@body))))
+(defmacro render (path &optional times &body body)
+  `(render% ,path ,times (lambda () ,@body)))
 
 (defun page/home ()
-  (render "build/index.html" (t/home)))
+  (render "build/index.html" nil
+    (t/home)))
 
-(defparameter *blog-entries*
-  (walk "content/blog"))
+(defun page/blog/index (entries)
+  (render "build/blog/index.html" (mapcar #'modified-timestamp entries)
+    (t/blog/index entries)))
+
+(defun page/photography/index (galleries)
+  (render "build/photography/index.html" (mapcar #'modified-timestamp galleries)
+    (t/photography/index galleries)))
 
-(defun page/blog/index ()
-  (render "build/blog/index.html" (t/blog/index *blog-entries*)))
+(defun page/blog/entries (entries)
+  (dolist (entry entries)
+    (render (output-path entry) (modified-timestamp entry)
+      (t/blog/entry entry))))
 
-(defun page/blog/entries ()
-  (dolist (entry *blog-entries*)
-    (render (getf entry :output-path) (t/blog/entry entry))))
+(defun page/photography/galleries (galleries)
+  (dolist (gallery galleries)
+    (render (output-path gallery) (modified-timestamp gallery)
+      (t/photography/gallery gallery))))
+
+(defun page/simple (content)
+  (render (output-path content) (modified-timestamp content)
+    (t/simple content)))
 
 
 ;;;; Toplevel -----------------------------------------------------------------
 (defun toplevel ()
-  (page/home)
-  (page/blog/index)
-  (page/blog/entries)
-  )
+  (let ((blog-entries (walk "content/blog"))
+        (photo-galleries (walk "content/photography"))
+        (links (read-content "content/links.markdown"))
+        (projects (read-content "content/projects.markdown")))
+    (page/home)
+    (page/blog/index blog-entries)
+    (page/blog/entries blog-entries)
+    (page/photography/index photo-galleries)
+    (page/photography/galleries photo-galleries)
+    (page/simple links)
+    (page/simple projects)))
 
 
 #; Scratch --------------------------------------------------------------------
+(defparameter *blog-entries*
+  (walk "content/blog"))
--- a/static/style.css	Sat Jan 04 23:39:05 2020 -0500
+++ b/static/style.css	Sun Jan 05 18:21:15 2020 -0500
@@ -124,24 +124,27 @@
 a#logo { color: #000000; }
 a#logo:hover { color: #e50053; }
 
-/* Individual Pages -------------------------------------------------------- */
-main#page-blog-index ul {
+/* Index Pages ------------------------------------------------------------- */
+ol.index {
     list-style-type: none;
     padding: 0px;
 }
-main#page-blog-index ul li {
+ol.index li.item {
     margin-bottom: 24px;
 }
-main#page-blog-index p.snippet {
+ol.index p.snippet {
     font-style: italic;
 }
-main#page-blog-index p.entry-date {
+ol.index p.date {
     margin: 0px;
     color: #666;
     float: right;
 }
 
-main#page-blog-entry p.entry-date {
+/* Individual Pages -------------------------------------------------------- */
+main#page-blog-entry p.date,
+main#page-photography-gallery p.date,
+main#page-simple p.date {
     margin: -20px 0px 24px;
     color: #666;
 }
@@ -165,3 +168,22 @@
 main#page-blog-entry div.threejs {
     margin: 0px 0px 24px;
 }
+
+main#page-photography-gallery ul {
+    margin: 0px 0px 24px 0px;
+    padding: 0;
+}
+
+main#page-photography-gallery li {
+    display: inline-block;
+    margin: 0;
+}
+
+main#page-photography-gallery img {
+    display: inline-block;
+    margin: 0px 12px 12px 0px;
+    border: 1px solid black;
+    width: 160px;
+    height: 160px;
+}
+