Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
77 commits
Select commit Hold shift + click to select a range
c78a212
Content for zaphod page
joesb Jan 27, 2026
448e9e6
Merge branch 'main' into feature/thinking-zaphod-beeblebrox
joesb Jan 27, 2026
a1f4a4d
More content, fix content canvas for lists
joesb Jan 27, 2026
d4ac0ee
Small text
joesb Jan 27, 2026
e0cfb15
Small text
joesb Jan 27, 2026
7555d3f
Fix some SEO issues
joesb Jan 28, 2026
c0f7f60
One more SEO issue
joesb Jan 28, 2026
ee061cb
Update IndexNow key
joesb Jan 28, 2026
efe6cff
Merge main into feature/thinking-zaphod-beeblebrox
joesb Jan 30, 2026
3ad6182
Oops, duplicated meta
joesb Feb 2, 2026
9e70b87
Merge branch 'main' into feature/thinking-zaphod-beeblebrox
joesb Feb 5, 2026
1993335
Small fix for figcaption close to window edge
joesb Feb 5, 2026
bd2cf90
Some extra text
joesb Feb 5, 2026
944ab3c
Merge branch 'main' into feature/thinking-zaphod-beeblebrox
joesb Feb 5, 2026
b1694db
More Zaphod text, plus some styles
joesb Feb 5, 2026
773dd6a
Zaphod text
joesb Feb 5, 2026
82194c2
Reading Old Books — first commit
joesb Feb 6, 2026
fbec976
Update the Tinker Tailor content, plus some styles
joesb Feb 6, 2026
3e9d9ae
Smiley Oldman photo
joesb Feb 6, 2026
c951a44
Fix stuff
joesb Feb 6, 2026
d49d810
Catch one thing
joesb Feb 6, 2026
0e60cfd
Metadata display left in lists, right in content
joesb Feb 6, 2026
e2b1a79
Catch some typos
joesb Feb 6, 2026
3d51e5c
Update a date
joesb Feb 6, 2026
322899c
Move Old Books to Dr Baker's Library
joesb Feb 7, 2026
507fca4
Background colour on Dr B's Library index list item
joesb Feb 7, 2026
eb5788f
Promote the library item
joesb Feb 7, 2026
e5c3e66
Move Dr B's Library to top level, add social image
joesb Feb 7, 2026
f30c427
hero image background colour
joesb Feb 7, 2026
cc89a1d
Only darken a surface when it's a faux-block link
joesb Feb 7, 2026
a57febf
A little more text for Tinker Tailor
joesb Feb 7, 2026
b51f4f4
Ooops, supertitle on Dr B's Library page
joesb Feb 7, 2026
948afc7
Paras
joesb Feb 7, 2026
ed68a4a
Reading Old Books — first commit
joesb Feb 6, 2026
fd3b79a
Update the Tinker Tailor content, plus some styles
joesb Feb 6, 2026
6cecc69
Smiley Oldman photo
joesb Feb 6, 2026
5ca82d5
Catch some typos
joesb Feb 6, 2026
cee4734
Update a date
joesb Feb 6, 2026
7ef3b26
Move Old Books to Dr Baker's Library
joesb Feb 7, 2026
8cde2ca
Background colour on Dr B's Library index list item
joesb Feb 7, 2026
0f4f6f1
Promote the library item
joesb Feb 7, 2026
03bc20b
Move Dr B's Library to top level, add social image
joesb Feb 7, 2026
f263023
Update Dr B's Library description
joesb Feb 7, 2026
1961205
Description
joesb Feb 7, 2026
75706dd
Fix library page intro text
joesb Feb 7, 2026
940f02d
Change to Dr B's Library
joesb Feb 7, 2026
c1057bc
Typos
joesb Feb 8, 2026
7f90adb
Put Tinker Tailor on homepage
joesb Feb 8, 2026
2a0c227
Dr B's Library in homepage block, plus don't show description on home…
joesb Feb 8, 2026
cff82d4
Home layout
joesb Feb 8, 2026
d9e1bc6
No need to double promote Dr B's Library
joesb Feb 8, 2026
6478fa0
Dr B's Library lists should be thinner content canvas
joesb Feb 9, 2026
c00d3b2
Reading Old Books — first commit
joesb Feb 6, 2026
4a4601e
Update the Tinker Tailor content, plus some styles
joesb Feb 6, 2026
bb7e5e0
Smiley Oldman photo
joesb Feb 6, 2026
e232ca9
Catch some typos
joesb Feb 6, 2026
4bbfb4a
Update a date
joesb Feb 6, 2026
f74679f
Move Old Books to Dr Baker's Library
joesb Feb 7, 2026
648dd3f
Background colour on Dr B's Library index list item
joesb Feb 7, 2026
b32a193
Promote the library item
joesb Feb 7, 2026
7f691d0
Move Dr B's Library to top level, add social image
joesb Feb 7, 2026
c2b31cb
Fix library page intro text
joesb Feb 7, 2026
7e69fe1
Update photo for the DBL Tinker Tailor
joesb Feb 9, 2026
62f0a2b
A longer description for the Writing landing page
joesb Feb 9, 2026
9c7c5af
Oops, title markdown inline
joesb Feb 9, 2026
2bbd0ea
Typo
joesb Feb 9, 2026
80dbb8a
Update current reading
joesb Feb 10, 2026
b24782e
Donna Tartt, The Secret History first commit
joesb Feb 9, 2026
72893a5
Small extra text
joesb Feb 9, 2026
0b2aeaf
No interrobang in Tinker Tailor
joesb Feb 9, 2026
53ee3ac
Mid-stream commit
joesb Feb 9, 2026
3ffeca3
Alter some external links in TTSS
joesb Feb 9, 2026
5c16999
Phraseology, TTSS
joesb Feb 9, 2026
a77b2a2
Another quote
joesb Feb 9, 2026
b9044c5
Better cascading fade animations in lists
joesb Feb 10, 2026
1f581e9
2nd section of Secret History
joesb Feb 10, 2026
abfa35a
Finish off Secret History text
joesb Feb 10, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
211 changes: 117 additions & 94 deletions eleventy.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import timeToRead from "eleventy-plugin-time-to-read";
import embedEverything from "eleventy-plugin-embed-everything";
import env from "./src/_data/env.js";
import { minify } from "html-minifier-terser";
import slugify from "slugify";

import path from 'path';

Expand All @@ -35,16 +36,16 @@ export default async function(eleventyConfig) {
eleventyConfig.addFilter("debug", (content) => `<pre>${inspect(content)}</pre>`);
eleventyConfig.addPlugin(eleventyImageOnRequestDuringServePlugin);
eleventyConfig.addPlugin(EleventyHtmlBasePlugin, {
// The base URL: defaults to Path Prefix
// baseHref: eleventyConfig.pathPrefix,
// The base URL: defaults to Path Prefix
// baseHref: eleventyConfig.pathPrefix,

// But you could use a full URL here too:
// baseHref: env.baseUrl,
// But you could use a full URL here too:
// baseHref: env.baseUrl,

// Comma separated list of output file extensions to apply
// our transform to. Use `false` to opt-out of the transform.
extensions: "html",
});
// Comma separated list of output file extensions to apply
// our transform to. Use `false` to opt-out of the transform.
extensions: "html",
});

// Return active path attributes
eleventyConfig.addShortcode('activepath', function (itemUrl, currentUrl) {
Expand All @@ -58,40 +59,40 @@ export default async function(eleventyConfig) {
});

eleventyConfig.addPlugin(eleventyImageTransformPlugin, {
// which file extensions to process
extensions: "html",
// which file extensions to process
extensions: "html",

// Add any other Image utility options here:
// Add any other Image utility options here:

// optional, output image formats
formats: ["webp", "jpeg"],
// formats: ["auto"],
// optional, output image formats
formats: ["webp", "jpeg"],
// formats: ["auto"],

// optional, output image widths
widths: [800, 500, 300],
// optional, output image widths
widths: [1980, 1200, 800, 500, 300],

urlPath: "/static/img/",
outputDir: "./_site/static/img/",

// optional, attributes assigned on <img> override these values.
defaultAttributes: {
loading: "lazy",
decoding: "async",
sizes: "auto",
},
// optional, attributes assigned on <img> override these values.
defaultAttributes: {
loading: "lazy",
decoding: "async",
sizes: "auto",
},

filenameFormat: (id, src, width, format) => {
const { name } = path.parse(src);
return `${name}-${width}w.${format}`;
},
});
});

// Return responsive images
eleventyConfig.addShortcode("image", async function(src, alt, cls = [], pictureCls = "", sizes = "auto", widths = [300, 600, 1000, 1980]) {
if(alt === undefined) {
// You bet we throw an error on missing alt (alt="" works okay)
throw new Error(`Missing \`alt\` on responsiveimage from: ${src}`);
}
if(alt === undefined) {
// You bet we throw an error on missing alt (alt="" works okay)
throw new Error(`Missing \`alt\` on responsiveimage from: ${src}`);
}

let imgClass = cls.length ? cls.map(s => `.${s}`).join(' ') : '';

Expand All @@ -100,7 +101,7 @@ export default async function(eleventyConfig) {
content = markdownLibrary.renderInline(content);

return content;
});
});

// // Collection of items promotoed
// eleventyConfig.addCollection('promotedContent', (collection) => {
Expand Down Expand Up @@ -166,19 +167,19 @@ export default async function(eleventyConfig) {

// Minify HTML
eleventyConfig.addTransform("htmlmin", function (content) {
if ((this.page.outputPath || "").endsWith(".html")) {
let minified = minify(content, {
useShortDoctype: true,
removeComments: true,
collapseWhitespace: true,
});

return minified;
}
if ((this.page.outputPath || "").endsWith(".html")) {
let minified = minify(content, {
useShortDoctype: true,
removeComments: true,
collapseWhitespace: true,
});

return minified;
}

// If not an HTML output, return content as-is
return content;
});
// If not an HTML output, return content as-is
return content;
});

// Check a string starts with a character.
eleventyConfig.addFilter('starts_with', function(str, prefix, not = false) {
Expand All @@ -202,30 +203,46 @@ export default async function(eleventyConfig) {
return typeof obj == 'string'
});

eleventyConfig.addFilter("isTag", (str, tag) => {
return str === tag;
});

eleventyConfig.addFilter("readableDate", (dateObj, format, zone) => {
// Formatting tokens for Luxon: https://moment.github.io/luxon/#/formatting?id=table-of-tokens
return DateTime.fromJSDate(dateObj, { zone: zone || "utc" }).toFormat(format || "dd LLLL yyyy");
});

eleventyConfig.addFilter('htmlDateString', (dateObj) => {
// dateObj input: https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-date-string
return DateTime.fromJSDate(dateObj, {zone: 'utc'}).toFormat('yyyy-LL-dd');
});

// Return all the tags used in a collection
eleventyConfig.addFilter("getAllTags", collection => {
let tagSet = new Set();
for(let item of collection) {
(item.data.tags || []).forEach(tag => tagSet.add(tag));
}
let tsArray = Array.from(tagSet);
// Formatting tokens for Luxon: https://moment.github.io/luxon/#/formatting?id=table-of-tokens
return DateTime.fromJSDate(dateObj, { zone: zone || "utc" }).toFormat(format || "dd LLLL yyyy");
});

eleventyConfig.addFilter('htmlDateString', (dateObj) => {
// dateObj input: https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-date-string
return DateTime.fromJSDate(dateObj, {zone: 'utc'}).toFormat('yyyy-LL-dd');
});

// Return all the tags used in a collection
eleventyConfig.addFilter("getAllTags", collection => {
let tagSet = new Set();
for(let item of collection) {
(item.data.tags || []).forEach(tag => tagSet.add(tag));
}
let tsArray = Array.from(tagSet);
return tsArray.sort();
});
});

eleventyConfig.addFilter("filterTagList", function filterTagList(tags) {
return (tags || []).filter(tag => ['all', 'nav', 'rss', '#reading', '#writing', '#thinking', 'Reading', 'Thinking', 'promotedContent', 'footerNav', 'footerSecondaryNav', 'mainNav', 'allContent', 'reading', 'writing', 'thinking'].indexOf(tag) === -1);
});
eleventyConfig.addFilter("filterTagList", function filterTagList(tags) {
return (tags || []).filter(tag => ['all', 'nav', 'rss', '#reading', '#writing', '#thinking', '#reading-library', 'Reading', 'Thinking', 'promotedContent', 'footerNav', 'footerSecondaryNav', 'mainNav', 'allContent', 'reading', 'writing', 'thinking'].indexOf(tag) === -1);
});

// Custom slug filter
eleventyConfig.addFilter("slug", (str) => {
if (!str) {
return;
}

return slugify(str, {
lower: true,
strict: true,
remove: /[']/g,
});
});

// Sort footer menu items by 'order' field
eleventyConfig.addCollection('footerNav', (collection) => {
Expand Down Expand Up @@ -278,6 +295,12 @@ export default async function(eleventyConfig) {
return sortByDate(nav).reverse();
});

// Sort reading old books pieces by 'order' field
eleventyConfig.addCollection('readingLibrary', (collection) => {
var nav = collection.getFilteredByTag('#reading-library');
return sortByDate(nav).reverse();
});

// Sort thinking pieces by 'order' field
eleventyConfig.addCollection('thinking', (collection) => {
var nav = collection.getFilteredByTag('#thinking');
Expand Down Expand Up @@ -319,50 +342,50 @@ export default async function(eleventyConfig) {
}

async function getPictureMarkup(src, alt, cls, pictureCls = "", sizes = "(min-width: 30em) 50vw, 100vw", widths = [300, 600, 1000, 1980]) {
if(alt === undefined) {
// You bet we throw an error on missing alt (alt="" works okay)
throw new Error(`Missing \`alt\` on responsiveimage from: ${src}`);
}

let metadata = await Image(src, {
widths: widths,
formats: ['webp', 'jpeg'],
if(alt === undefined) {
// You bet we throw an error on missing alt (alt="" works okay)
throw new Error(`Missing \`alt\` on responsiveimage from: ${src}`);
}

let metadata = await Image(src, {
widths: widths,
formats: ['webp', 'jpeg'],
urlPath: "/static/img/",
outputDir: "./_site/static/img/"
});

let lowsrc = metadata.jpeg[0];
let highsrc = metadata.jpeg[metadata.jpeg.length - 1];

return `<picture class="${pictureCls}">
${Object.values(metadata).map(imageFormat => {
return ` <source type="${imageFormat[0].sourceType}" srcset="${imageFormat.map(entry => entry.srcset).join(", ")}" sizes="${sizes}">`;
}).join("\n")}
<img
src="${lowsrc.url}"
width="${highsrc.width}"
height="${highsrc.height}"
});

let lowsrc = metadata.jpeg[0];
let highsrc = metadata.jpeg[metadata.jpeg.length - 1];

return `<picture class="${pictureCls}">
${Object.values(metadata).map(imageFormat => {
return ` <source type="${imageFormat[0].sourceType}" srcset="${imageFormat.map(entry => entry.srcset).join(", ")}" sizes="${sizes}">`;
}).join("\n")}
<img
src="${lowsrc.url}"
width="${highsrc.width}"
height="${highsrc.height}"
class="${cls}"
alt="${alt}"
loading="lazy"
decoding="async">
</picture>`;
};
alt="${alt}"
loading="lazy"
decoding="async">
</picture>`;
};

async function getPictureData(src, widths = [300, 600, 1000, 1980]) {
let metadata = await Image('./pages' + src, {
returnType: 'object',
returnType: 'object',
widths: widths,
formats: ['jpeg'],
formats: ['jpeg'],
urlPath: "/static/img/",
outputDir: "./_site/static/img/"
});
});
return metadata;
};

eleventyConfig.addPairedShortcode("ImgFigure", function(content, caption = false, classes, md = true) {
eleventyConfig.addPairedShortcode("ImgFigure", function(content, caption = false, classes = [], md = true) {
if (caption) {
caption = '<figcaption>' + caption + '</figcaption>';
caption = '<figcaption>' + (md ? markdownLibrary.renderInline(caption) : caption) + '</figcaption>';
}
return '<figure' + (classes.length ? ' class="' + (classes instanceof Array ? classes.join(" ") : classes) + '"' : '') + '>' + (md ? markdownLibrary.renderInline(content) : content) + (caption ? caption : '') +'</figure>';
});
Expand All @@ -379,12 +402,12 @@ export default async function(eleventyConfig) {
symbol: "#",
level: [1,2,3,4],
}),
slugify: eleventyConfig.getFilter("slug")
slugify: eleventyConfig.getFilter("slugify")
}).use(markdownItAttrs).use(markdownItSmall);
eleventyConfig.setLibrary("md", markdownLibrary);

eleventyConfig.addFilter("markdown", (content) => {
return markdownLibrary.render(content);
eleventyConfig.addFilter("markdown", (content, ril = false) => {
return ril ? markdownLibrary.renderInline(content) : markdownLibrary.render(content);
});

eleventyConfig.addPairedShortcode("Markdown", function(content, ril = false) {
Expand Down
11 changes: 10 additions & 1 deletion pages/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: Joe Baker
description: My writer's journal, for my writing projects, as well as the reading and thinking that support them.
pageTitle: Writer
date: 2026-01-25T12:34:21Z
date: 2026-02-08T13:20:21Z
eleventyNavigation:
key: Home
layout: home.njk
Expand All @@ -17,3 +17,12 @@ pagination:
---

My writer's journal, for my [writing](/writing){.light} projects, as well as the [reading](/reading){.light} and [thinking](/thinking){.light} that support them.

---{.margin-block-start-vlg}

**And also …**{.bold} Yeah, sure, there’s plenty of new books, but do you ever read old books?
{.margin-block-start-vlg}

Welcome to [Dr B's Library](/library/){.light .single-meta-forward .bold}

Let's pick one off the shelf.
27 changes: 27 additions & 0 deletions pages/library/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
---
title: Dr B's Library
description: |
Yeah, sure, there’s plenty of new books, but do you ever read old books?

Let's pick one off the shelf.
date: 2026-02-06T11:39:24Z
layout: list-library.njk
hideDescriptions: true
promoted: false
eleventyNavigation:
key: Dr B's Library
order: 4
pagination:
data: collections.readingLibrary
size: 11
alias: items
pageClass: "site-content--surface-dark site-content--surface-rose"
indexListClass: "site-content--surface-dark site-content--surface-rose"
tags:
'#reading'
order: -10
image:
social: /static/images/oldbooks/pexels-tima-miroshnichenko-9572619.jpg
redirectFrom:
- /reading/old-books/
---
Loading