├── .nojekyll ├── .nvmrc ├── public └── img │ └── .gitkeep ├── vercel.json ├── .gitignore ├── .gitattributes ├── netlify.toml ├── content ├── content.11tydata.js ├── feed │ ├── .virtual │ └── pretty-atom-feed.xsl ├── blog │ ├── blog.11tydata.js │ ├── fourthpost │ │ ├── possum.png │ │ └── fourthpost.md │ ├── fifthpost.md │ ├── secondpost.md │ ├── firstpost.md │ └── thirdpost.md ├── about.md ├── blog.njk ├── tags.njk ├── sitemap.xml.njk ├── tag-pages.njk ├── 404.md └── index.njk ├── .editorconfig ├── _data ├── metadata.js └── eleventyDataSchema.js ├── css ├── message-box.css ├── prism-diff.css └── index.css ├── _includes ├── postslist.njk └── layouts │ ├── home.njk │ ├── post.njk │ └── base.njk ├── LICENSE ├── .github └── workflows │ └── gh-pages.yml.sample ├── _config └── filters.js ├── package.json ├── eleventy.config.js └── README.md /.nojekyll: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | 20 2 | -------------------------------------------------------------------------------- /public/img/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /vercel.json: -------------------------------------------------------------------------------- 1 | { "trailingSlash": true } 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | _site/ 2 | node_modules/ 3 | .cache 4 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | content/feed/pretty-atom-feed.xsl linguist-vendored 2 | -------------------------------------------------------------------------------- /netlify.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | publish = "_site" 3 | command = "npm run build" 4 | -------------------------------------------------------------------------------- /content/content.11tydata.js: -------------------------------------------------------------------------------- 1 | export default { 2 | layout: "layouts/home.njk", 3 | }; 4 | -------------------------------------------------------------------------------- /content/feed/.virtual: -------------------------------------------------------------------------------- 1 | For RSS feed, Atom Feed, and JSON feed templates, see the plugin in eleventy.config.js 2 | -------------------------------------------------------------------------------- /content/blog/blog.11tydata.js: -------------------------------------------------------------------------------- 1 | export default { 2 | tags: [ 3 | "posts" 4 | ], 5 | "layout": "layouts/post.njk", 6 | }; 7 | -------------------------------------------------------------------------------- /content/blog/fourthpost/possum.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/11ty/eleventy-base-blog/main/content/blog/fourthpost/possum.png -------------------------------------------------------------------------------- /content/blog/fifthpost.md: -------------------------------------------------------------------------------- 1 | ---js 2 | const title = "This is a fifth post"; 3 | const date = "2023-01-23"; 4 | const draft = true; 5 | --- 6 | This is a draft post 7 | -------------------------------------------------------------------------------- /content/about.md: -------------------------------------------------------------------------------- 1 | ---js 2 | const eleventyNavigation = { 3 | key: "About", 4 | order: 3 5 | }; 6 | --- 7 | # About 8 | 9 | I am a person that writes stuff. 10 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = tab 5 | indent_size = 2 6 | end_of_line = lf 7 | insert_final_newline = true 8 | trim_trailing_whitespace = true 9 | charset = utf-8 10 | -------------------------------------------------------------------------------- /content/blog.njk: -------------------------------------------------------------------------------- 1 | ---js 2 | const eleventyNavigation = { 3 | key: "Archive", 4 | order: 2 5 | }; 6 | --- 7 |

Archive

8 | 9 | {% set postslist = collections.posts %} 10 | {% include "postslist.njk" %} 11 | -------------------------------------------------------------------------------- /content/tags.njk: -------------------------------------------------------------------------------- 1 |

Tags

2 | 3 | 9 | -------------------------------------------------------------------------------- /_data/metadata.js: -------------------------------------------------------------------------------- 1 | export default { 2 | title: "Eleventy Base Blog v9", 3 | url: "https://example.com/", 4 | language: "en", 5 | description: "I am writing about my experiences as a naval navel-gazer.", 6 | author: { 7 | name: "Your Name Here", 8 | email: "youremailaddress@example.com", 9 | url: "https://example.com/about-me/" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /css/message-box.css: -------------------------------------------------------------------------------- 1 | /* Message Box */ 2 | .message-box { 3 | --color-message-box: #ffc; 4 | 5 | display: block; 6 | background-color: var(--color-message-box); 7 | color: var(--color-gray-90); 8 | padding: 1em 0.625em; /* 16px 10px /16 */ 9 | } 10 | .message-box ol { 11 | margin-top: 0; 12 | } 13 | 14 | @media (prefers-color-scheme: dark) { 15 | .message-box { 16 | --color-message-box: #082840; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /_includes/postslist.njk: -------------------------------------------------------------------------------- 1 |
    2 | {%- for post in postslist | reverse %} 3 |
  1. 4 | {% if post.data.title %}{{ post.data.title }}{% else %}{{ post.url }}{% endif %} 5 | 6 |
  2. 7 | {%- endfor %} 8 |
9 | -------------------------------------------------------------------------------- /_data/eleventyDataSchema.js: -------------------------------------------------------------------------------- 1 | import { z } from "zod"; 2 | import { fromZodError } from 'zod-validation-error'; 3 | 4 | // Draft content, validate `draft` front matter 5 | export default function() { 6 | return function(data) { 7 | // Note that drafts may be skipped in a preprocessor (see eleventy.config.js) 8 | // when doing a standard build (not --serve or --watch) 9 | let result = z.object({ 10 | draft: z.boolean().or(z.undefined()), 11 | }).safeParse(data); 12 | 13 | if(result.error) { 14 | throw fromZodError(result.error); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /content/sitemap.xml.njk: -------------------------------------------------------------------------------- 1 | --- 2 | permalink: /sitemap.xml 3 | layout: false 4 | eleventyExcludeFromCollections: true 5 | --- 6 | 7 | 8 | {%- for page in collections.all %} 9 | {% if page.data.permalink != false %} 10 | {% set absoluteUrl %}{{ page.url | htmlBaseUrl(metadata.url) }}{% endset %} 11 | 12 | {{ absoluteUrl }} 13 | {{ page.date | htmlDateString }} 14 | 15 | {% endif %} 16 | {%- endfor %} 17 | 18 | -------------------------------------------------------------------------------- /content/tag-pages.njk: -------------------------------------------------------------------------------- 1 | ---js 2 | // 41 | 42 | 43 | 44 | 45 |
46 | {{ metadata.title }} 47 | 48 | {#- Read more about `eleventy-navigation` at https://www.11ty.dev/docs/plugins/navigation/ #} 49 | 57 |
58 | 59 |
60 | 61 | {{ content | safe }} 62 | 63 |
64 | 65 | 70 | 71 | 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /eleventy.config.js: -------------------------------------------------------------------------------- 1 | import { IdAttributePlugin, InputPathToUrlTransformPlugin, HtmlBasePlugin } from "@11ty/eleventy"; 2 | import { feedPlugin } from "@11ty/eleventy-plugin-rss"; 3 | import pluginSyntaxHighlight from "@11ty/eleventy-plugin-syntaxhighlight"; 4 | import pluginNavigation from "@11ty/eleventy-navigation"; 5 | import { eleventyImageTransformPlugin } from "@11ty/eleventy-img"; 6 | 7 | import pluginFilters from "./_config/filters.js"; 8 | 9 | /** @param {import("@11ty/eleventy").UserConfig} eleventyConfig */ 10 | export default async function(eleventyConfig) { 11 | // Drafts, see also _data/eleventyDataSchema.js 12 | eleventyConfig.addPreprocessor("drafts", "*", (data, content) => { 13 | if (data.draft) { 14 | data.title = `${data.title} (draft)`; 15 | } 16 | 17 | if(data.draft && process.env.ELEVENTY_RUN_MODE === "build") { 18 | return false; 19 | } 20 | }); 21 | 22 | // Copy the contents of the `public` folder to the output folder 23 | // For example, `./public/css/` ends up in `_site/css/` 24 | eleventyConfig 25 | .addPassthroughCopy({ 26 | "./public/": "/" 27 | }) 28 | .addPassthroughCopy("./content/feed/pretty-atom-feed.xsl"); 29 | 30 | // Run Eleventy when these files change: 31 | // https://www.11ty.dev/docs/watch-serve/#add-your-own-watch-targets 32 | 33 | // Watch CSS files 34 | eleventyConfig.addWatchTarget("css/**/*.css"); 35 | // Watch images for the image pipeline. 36 | eleventyConfig.addWatchTarget("content/**/*.{svg,webp,png,jpg,jpeg,gif}"); 37 | 38 | // Per-page bundles, see https://github.com/11ty/eleventy-plugin-bundle 39 | // Bundle ` and uncomment `` 116 | 2. Configure the server with the CSP directive `style-src: 'unsafe-inline'` (less secure). 117 | -------------------------------------------------------------------------------- /css/index.css: -------------------------------------------------------------------------------- 1 | /* Defaults */ 2 | :root { 3 | --font-family: -apple-system, system-ui, sans-serif; 4 | --font-family-monospace: Consolas, Menlo, Monaco, Andale Mono WT, Andale Mono, Lucida Console, Lucida Sans Typewriter, DejaVu Sans Mono, Bitstream Vera Sans Mono, Liberation Mono, Nimbus Mono L, Courier New, Courier, monospace; 5 | } 6 | 7 | /* Theme colors */ 8 | :root { 9 | --color-gray-20: #e0e0e0; 10 | --color-gray-50: #C0C0C0; 11 | --color-gray-90: #333; 12 | 13 | --background-color: #fff; 14 | 15 | --text-color: var(--color-gray-90); 16 | --text-color-link: #082840; 17 | --text-color-link-active: #5f2b48; 18 | --text-color-link-visited: #17050F; 19 | 20 | --syntax-tab-size: 2; 21 | } 22 | 23 | @media (prefers-color-scheme: dark) { 24 | :root { 25 | --color-gray-20: #e0e0e0; 26 | --color-gray-50: #C0C0C0; 27 | --color-gray-90: #dad8d8; 28 | 29 | /* --text-color is assigned to --color-gray-_ above */ 30 | --text-color-link: #1493fb; 31 | --text-color-link-active: #6969f7; 32 | --text-color-link-visited: #a6a6f8; 33 | 34 | --background-color: #15202b; 35 | } 36 | } 37 | 38 | 39 | /* Global stylesheet */ 40 | * { 41 | box-sizing: border-box; 42 | } 43 | 44 | @view-transition { 45 | navigation: auto; 46 | } 47 | 48 | html, 49 | body { 50 | padding: 0; 51 | margin: 0 auto; 52 | font-family: var(--font-family); 53 | color: var(--text-color); 54 | background-color: var(--background-color); 55 | } 56 | html { 57 | overflow-y: scroll; 58 | } 59 | body { 60 | max-width: 40em; 61 | } 62 | 63 | /* https://www.a11yproject.com/posts/how-to-hide-content/ */ 64 | .visually-hidden:not(:focus):not(:active) { 65 | clip: rect(0 0 0 0); 66 | clip-path: inset(50%); 67 | height: 1px; 68 | overflow: hidden; 69 | position: absolute; 70 | white-space: nowrap; 71 | width: 1px; 72 | } 73 | 74 | /* Fluid images via https://www.zachleat.com/web/fluid-images/ */ 75 | img{ 76 | max-width: 100%; 77 | } 78 | img[width][height] { 79 | height: auto; 80 | } 81 | img[src$=".svg"] { 82 | width: 100%; 83 | height: auto; 84 | max-width: none; 85 | } 86 | video, 87 | iframe { 88 | width: 100%; 89 | height: auto; 90 | } 91 | iframe { 92 | aspect-ratio: 16/9; 93 | } 94 | 95 | p:last-child { 96 | margin-bottom: 0; 97 | } 98 | p { 99 | line-height: 1.5; 100 | } 101 | 102 | li { 103 | line-height: 1.5; 104 | } 105 | 106 | a[href] { 107 | color: var(--text-color-link); 108 | } 109 | a[href]:visited { 110 | color: var(--text-color-link-visited); 111 | } 112 | a[href]:hover, 113 | a[href]:active { 114 | color: var(--text-color-link-active); 115 | } 116 | 117 | main, 118 | footer { 119 | padding: 1rem; 120 | } 121 | main :first-child { 122 | margin-top: 0; 123 | } 124 | 125 | header { 126 | border-bottom: 1px dashed var(--color-gray-20); 127 | } 128 | 129 | #skip-link { 130 | text-decoration: none; 131 | background: var(--background-color); 132 | color: var(--text-color); 133 | padding: 0.5rem 1rem; 134 | border: 1px solid var(--color-gray-90); 135 | border-radius: 2px; 136 | } 137 | 138 | /* Prevent visually-hidden skip link fom pushing content around when focused */ 139 | #skip-link.visually-hidden:focus { 140 | position: absolute; 141 | top: 1rem; 142 | left: 1rem; 143 | /* Ensure it is positioned on top of everything else when it is shown */ 144 | z-index: 999; 145 | } 146 | 147 | .links-nextprev { 148 | display: flex; 149 | justify-content: space-between; 150 | gap: .5em 1em; 151 | list-style: ""; 152 | border-top: 1px dashed var(--color-gray-20); 153 | padding: 1em 0; 154 | } 155 | .links-nextprev > * { 156 | flex-grow: 1; 157 | } 158 | .links-nextprev-next { 159 | text-align: right; 160 | } 161 | 162 | table { 163 | margin: 1em 0; 164 | } 165 | table td, 166 | table th { 167 | padding-right: 1em; 168 | } 169 | 170 | pre, 171 | code { 172 | font-family: var(--font-family-monospace); 173 | } 174 | pre:not([class*="language-"]) { 175 | margin: .5em 0; 176 | line-height: 1.375; /* 22px /16 */ 177 | -moz-tab-size: var(--syntax-tab-size); 178 | -o-tab-size: var(--syntax-tab-size); 179 | tab-size: var(--syntax-tab-size); 180 | -webkit-hyphens: none; 181 | -ms-hyphens: none; 182 | hyphens: none; 183 | direction: ltr; 184 | text-align: left; 185 | white-space: pre; 186 | word-spacing: normal; 187 | word-break: normal; 188 | overflow-x: auto; 189 | } 190 | code { 191 | word-break: break-all; 192 | } 193 | 194 | /* Header */ 195 | header { 196 | display: flex; 197 | gap: 1em; 198 | flex-wrap: wrap; 199 | justify-content: space-between; 200 | align-items: center; 201 | padding: 1em; 202 | } 203 | .home-link { 204 | flex-grow: 1; 205 | font-size: 1em; /* 16px /16 */ 206 | font-weight: 700; 207 | } 208 | .home-link:link:not(:hover) { 209 | text-decoration: none; 210 | } 211 | 212 | /* Nav */ 213 | .nav { 214 | display: flex; 215 | gap: .5em 1em; 216 | padding: 0; 217 | margin: 0; 218 | list-style: none; 219 | } 220 | .nav-item { 221 | display: inline-block; 222 | } 223 | .nav-item a[href]:not(:hover) { 224 | text-decoration: none; 225 | } 226 | .nav a[href][aria-current="page"] { 227 | text-decoration: underline; 228 | } 229 | 230 | /* Posts list */ 231 | .postlist { 232 | counter-reset: start-from var(--postlist-index); 233 | list-style: none; 234 | padding: 0; 235 | padding-left: 1.5rem; 236 | } 237 | .postlist-item { 238 | display: flex; 239 | flex-wrap: wrap; 240 | align-items: baseline; 241 | counter-increment: start-from -1; 242 | margin-bottom: 1em; 243 | } 244 | .postlist-item:before { 245 | display: inline-block; 246 | pointer-events: none; 247 | content: "" counter(start-from, decimal-leading-zero) ". "; 248 | line-height: 100%; 249 | text-align: right; 250 | margin-left: -1.5rem; 251 | } 252 | .postlist-date, 253 | .postlist-item:before { 254 | font-size: 0.8125em; /* 13px /16 */ 255 | color: var(--color-gray-90); 256 | } 257 | .postlist-date { 258 | word-spacing: -0.5px; 259 | } 260 | .postlist-link { 261 | font-size: 1.1875em; /* 19px /16 */ 262 | font-weight: 700; 263 | flex-basis: calc(100% - 1.5rem); 264 | padding-left: .25em; 265 | padding-right: .5em; 266 | text-underline-position: from-font; 267 | text-underline-offset: 0; 268 | text-decoration-thickness: 1px; 269 | } 270 | .postlist-item-active .postlist-link { 271 | font-weight: bold; 272 | } 273 | 274 | /* Tags */ 275 | .post-tag { 276 | display: inline-flex; 277 | align-items: center; 278 | justify-content: center; 279 | text-transform: capitalize; 280 | font-style: italic; 281 | } 282 | .postlist-item > .post-tag { 283 | align-self: center; 284 | } 285 | 286 | /* Tags list */ 287 | .post-metadata { 288 | display: inline-flex; 289 | flex-wrap: wrap; 290 | gap: .5em; 291 | list-style: none; 292 | padding: 0; 293 | margin: 0; 294 | } 295 | .post-metadata time { 296 | margin-right: 1em; 297 | } 298 | 299 | -------------------------------------------------------------------------------- /content/feed/pretty-atom-feed.xsl: -------------------------------------------------------------------------------- 1 | 2 | 14 | 17 | 18 | 19 | 20 | 21 | <xsl:value-of select="atom:feed/atom:title"/> 22 | 23 | 24 | 25 | 26 | 27 | 35 |
36 |
37 |

38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | Web Feed Preview 57 |

58 |

59 |

60 |

This preview only shows titles, but the actual feed contains the full content.

61 | 62 | 63 | 64 | 65 | Visit Website → 66 | 67 |
68 |

Recent Items

69 | 70 |
71 | 72 | 73 |
74 | 75 |
76 |

77 | 78 | 79 | 80 | 81 | 82 | 83 |

84 | 85 | Published: 86 | 87 |
88 |
89 |
90 | --------------------------------------------------------------------------------