├── .gitattributes ├── .gitignore ├── .nvmrc ├── .prettierignore ├── .prettierrc.json ├── README.md ├── eleventy.config.js ├── etc ├── collections │ └── index.js ├── filters │ ├── filters.js │ └── index.js └── transforms │ └── index.js ├── lib └── markdown.js ├── package-lock.json ├── package.json ├── postcss.config.js └── src ├── _data ├── config.js └── helpers.js ├── _includes ├── layouts │ ├── base.njk │ ├── error.njk │ ├── index.njk │ ├── list.njk │ ├── page.njk │ ├── post.njk │ └── tag-results.njk └── partials │ ├── base-head.njk │ ├── card-list-index.njk │ ├── site-footer.njk │ ├── site-header.njk │ ├── site-pagination.njk │ └── site-post-list.njk ├── _styles ├── _components │ ├── _card-list.css │ ├── _footnotes.css │ ├── _site-footer.css │ ├── _site-header.css │ └── _site-pagination.css ├── _config │ ├── _import.css │ └── _media.css ├── _layout │ ├── _content.css │ ├── _layout-grid.css │ └── _wrapper.css ├── _types.css ├── _utilities.css ├── _variables.css └── _vendor │ └── _prism.css ├── content ├── 404.md ├── index.md ├── posts.md ├── posts │ ├── 2011-06-02-leviathan-wakes.md │ ├── 2012-06-26-calibans-war.md │ ├── 2013-07-04-abaddons-gate.md │ ├── 2014-06-05-cibola-burn.md │ ├── 2015-06-02-nemesis-games.md │ ├── 2016-12-06-babylons-ashes.md │ ├── 2017-12-05-persepolis-rising.md │ ├── 2019-03-26-tiamats-wrath.md │ ├── 2021-11-30-leviathan-falls.md │ └── posts.json ├── tags.md └── using-this-template.md ├── feed.njk ├── media ├── aldebaran-s-qtRF_RxCAo0-unsplash.jpg ├── andy-holmes-rCbdp8VCYhQ-unsplash.jpg ├── jeremy-thomas-E0AHdsENmDg-unsplash.jpg └── john-fowler-7Ym9rpYtSdA-unsplash.jpg ├── site.css ├── static ├── favicons │ ├── apple-touch-icon.jpg │ ├── favicon.jpg │ ├── icon-192.jpg │ ├── icon-512.jpg │ └── icon.svg ├── fonts │ └── .gitkeep └── og-default.jpg └── webmanifest.njk /.gitattributes: -------------------------------------------------------------------------------- 1 | https://github.com/alexkaratarakis/gitattributes 2 | ## GITATTRIBUTES FOR WEB PROJECTS 3 | # 4 | # These settings are for any web project. 5 | # 6 | # Details per file setting: 7 | # text These files should be normalized (i.e. convert CRLF to LF). 8 | # binary These files are binary and should be left untouched. 9 | # 10 | # Note that binary is a macro for -text -diff. 11 | ###################################################################### 12 | # Auto detect 13 | ## Handle line endings automatically for files detected as 14 | ## text and leave all files detected as binary untouched. 15 | ## This will handle all files NOT defined below. 16 | * text=auto 17 | # Source code 18 | *.bash text eol=lf 19 | *.bat text eol=crlf 20 | *.cmd text eol=crlf 21 | *.coffee text 22 | *.css text 23 | *.htm text diff=html 24 | *.html text diff=html 25 | *.inc text 26 | *.ini text 27 | *.js text 28 | *.json text 29 | *.jsx text 30 | *.less text 31 | *.ls text 32 | *.map text -diff 33 | *.od text 34 | *.onlydata text 35 | *.php text diff=php 36 | *.pl text 37 | *.ps1 text eol=crlf 38 | *.py text diff=python 39 | *.rb text diff=ruby 40 | *.sass text 41 | *.scm text 42 | *.scss text diff=css 43 | *.sh text eol=lf 44 | *.sql text 45 | *.styl text 46 | *.tag text 47 | *.ts text 48 | *.tsx text 49 | *.xml text 50 | *.xhtml text diff=html 51 | # Docker 52 | Dockerfile text 53 | # Documentation 54 | *.ipynb text 55 | *.markdown text 56 | *.md text 57 | *.mdwn text 58 | *.mdown text 59 | *.mkd text 60 | *.mkdn text 61 | *.mdtxt text 62 | *.mdtext text 63 | *.txt text 64 | AUTHORS text 65 | CHANGELOG text 66 | CHANGES text 67 | CONTRIBUTING text 68 | COPYING text 69 | copyright text 70 | *COPYRIGHT* text 71 | INSTALL text 72 | license text 73 | LICENSE text 74 | NEWS text 75 | readme text 76 | *README* text 77 | TODO text 78 | # Templates 79 | *.dot text 80 | *.ejs text 81 | *.haml text 82 | *.handlebars text 83 | *.hbs text 84 | *.hbt text 85 | *.jade text 86 | *.latte text 87 | *.mustache text 88 | *.njk text 89 | *.phtml text 90 | *.tmpl text 91 | *.tpl text 92 | *.twig text 93 | *.vue text 94 | # Configs 95 | *.cnf text 96 | *.conf text 97 | *.config text 98 | .editorconfig text 99 | .env text 100 | .gitattributes text 101 | .gitconfig text 102 | .htaccess text 103 | *.lock text -diff 104 | package-lock.json text -diff 105 | *.toml text 106 | *.yaml text 107 | *.yml text 108 | browserslist text 109 | Makefile text 110 | makefile text 111 | # Heroku 112 | Procfile text 113 | # Graphics 114 | *.ai binary 115 | *.bmp binary 116 | *.eps binary 117 | *.gif binary 118 | *.gifv binary 119 | *.ico binary 120 | *.jng binary 121 | *.jp2 binary 122 | *.jpg binary 123 | *.jpeg binary 124 | *.jpx binary 125 | *.jxr binary 126 | *.pdf binary 127 | *.png binary 128 | *.psb binary 129 | *.psd binary 130 | # SVG treated as an asset (binary) by default. 131 | *.svg text 132 | # If you want to treat it as binary, 133 | # use the following line instead. 134 | # *.svg binary 135 | *.svgz binary 136 | *.tif binary 137 | *.tiff binary 138 | *.wbmp binary 139 | *.webp binary 140 | # Audio 141 | *.kar binary 142 | *.m4a binary 143 | *.mid binary 144 | *.midi binary 145 | *.mp3 binary 146 | *.ogg binary 147 | *.ra binary 148 | # Video 149 | *.3gpp binary 150 | *.3gp binary 151 | *.as binary 152 | *.asf binary 153 | *.asx binary 154 | *.fla binary 155 | *.flv binary 156 | *.m4v binary 157 | *.mng binary 158 | *.mov binary 159 | *.mp4 binary 160 | *.mpeg binary 161 | *.mpg binary 162 | *.ogv binary 163 | *.swc binary 164 | *.swf binary 165 | *.webm binary 166 | # Archives 167 | *.7z binary 168 | *.gz binary 169 | *.jar binary 170 | *.rar binary 171 | *.tar binary 172 | *.zip binary 173 | # Fonts 174 | *.ttf binary 175 | *.eot binary 176 | *.otf binary 177 | *.woff binary 178 | *.woff2 binary 179 | # Executables 180 | *.exe binary 181 | *.pyc binary 182 | # RC files (like .babelrc or .eslintrc) 183 | *.*rc text 184 | # Ignore files (like .npmignore or .gitignore) 185 | *.*ignore text 186 | # Files/directories actively tracked for this project 187 | *.jpg filter=lfs diff=lfs merge=lfs 188 | *.png filter=lfs diff=lfs merge=lfs 189 | *.gif filter=lfs diff=lfs merge=lfs 190 | *.mp4 filter=lfs diff=lfs merge=lfs 191 | *.webm filter=lfs diff=lfs merge=lfs 192 | *.woff filter=lfs diff=lfs merge=lfs -binary 193 | *.woff2 filter=lfs diff=lfs merge=lfs -binary 194 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .env 3 | node_modules/ 4 | dist -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | v21.7.3 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | *.md -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 100, 3 | "useTabs": true, 4 | "tabWidth": 2, 5 | "bracketSpacing": true, 6 | "bracketSameLine": true, 7 | "arrowParens": "avoid" 8 | } 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 11ty Get going 2 | Get Going is an 11ty starter project for simple blogs, small sites and prototypes. 3 | 4 | _Now upgraded to use ES6 modules and 11ty v3.0_ 🎉 5 | 6 | **[View a demo](https://mellow-crepe-c98c31.netlify.app)** 7 | 8 | The following starting points and integrations come included: 9 | 10 | - [11ty Pagination](https://www.11ty.dev/docs/pagination/) 11 | - [11ty Navigation](https://www.11ty.dev/docs/plugins/navigation/) 12 | - [11ty Image](https://www.11ty.dev/docs/plugins/image/) 13 | - [11ty RSS](https://www.11ty.dev/docs/plugins/rss/) 14 | - [11ty Syntax Highlighting](https://www.11ty.dev/docs/plugins/syntaxhighlight/) 15 | - [Eleventy Plugin: Lightning CSS](https://www.npmjs.com/package/@11tyrocks/eleventy-plugin-lightningcss) 16 | - [Markdown-it](https://www.npmjs.com/package/markdown-it) 17 | - [Markdown-it Footnote](https://www.npmjs.com/package/markdown-it-footnote) 18 | - [Markdown-it Definition Lists](https://www.npmjs.com/package/markdown-it-deflist) 19 | - [Markdown-it Sub](https://www.npmjs.com/package/markdown-it-sub) 20 | - [Markdown-it Sup](https://www.npmjs.com/package/markdown-it-sup) 21 | - [Markdown-it-eleventy-img](https://www.npmjs.com/package/markdown-it-eleventy-img) 22 | 23 | ## Requirements 24 | [Node version manager](https://github.com/nvm-sh/nvm) is recommended then simply `nvm use` and it will pull the version from the `.nvmrc` file in this repo. Any Node LTS version should suffice for this template. 25 | 26 | ### Running the project 27 | To run a version yourself, [clone the repo](https://github.com/kevh-c/11ty-get-going), `npm install` and then `npm run serve` to view the demo project locally. 28 | 29 | If you're intending to use Git LFS remember to `git lfs install` to enable it. 30 | 31 | --- 32 | 33 | ## Getting started 34 | There's a little bit of housekeeping to do in order to make this template your own. 35 | 36 | ### Update global configs for this template 37 | This project uses a single file to capture project-wide metadata, basically to populate all the stuff in a `` tag on your pages. This can be found under `src/data/config.js`. These of course can be overridden in your content frontmatter thanks to Eleventys [data cascade](https://www.11ty.dev/docs/data-cascade/). 38 | 39 | ```js 40 | // Required. The name of your project. 41 | projectName: "11ty Get Going", 42 | 43 | // Required. A brief description of your project. 44 | description: "Just another 11ty starter kit", 45 | 46 | // Required. A short name used exclusively in webmanifest.njk. Keep it under 12 characters to minimize the possibility of truncation. Can be safely deleted if you delete webmanifest.njk. 47 | shortName: "11ty GG", 48 | 49 | // Required. Update development and production urls to your project requirements. 50 | domain: process.env.ELEVENTY_RUN_MODE == "serve" ? "http://localhost:8080" : "https://example.com", 51 | 52 | // Required. SEO indexing behaviour. 53 | robots: "index, follow", 54 | 55 | // Required. Used exclusively in webmanifest.njk. This sometimes affects how an OS displays your site. Can be safely deleted if you delete webmanifest.njk. 56 | themeColor: "#FFFFFF", 57 | 58 | // Required. Used exclusively in webmanifest.njk. Recommend using the same value as body background color in your CSS. Can be safely deleted if you delete webmanifest.njk. 59 | backgroundColor: "#FFFFFF", 60 | 61 | // Optional. Delete block if not used. Author values for project. 62 | author: { 63 | name: "Author Name", 64 | email: "author@email.com", 65 | }, 66 | 67 | // Optional. Delete block if you don't require link tags related to your idenity. Duplicate as many objects as you need! 68 | identity: [ 69 | { 70 | rel: "me", 71 | url: "URL-GOES-HERE", 72 | }, 73 | ], 74 | 75 | // Optional. Delete block if you don't require Opengraph. 76 | og: { 77 | locale: "en_GB", 78 | type: "website", 79 | image: { 80 | rel: "/og-default.jpg", 81 | alt: "Default OG image displayed here", 82 | }, 83 | } 84 | ``` 85 | 86 | ### Favicons and Opengraph 87 | 88 | #### Favicons 89 | Favicons are stored under `src/static/favicons` and are automatically passed through to their relevant directories on build. All you need to do is create the images for your project. 90 | 91 | #### Opengraph 92 | A default Opengraph image can be found under `src/static` and is named `og-default.jpg`. Much like the favicons all you need to do is create a relevant default image to be used. 93 | 94 | If you decide to delete this file (for example if you don't require Opengraph in your project), then you must update `eleventy.config.js` and remove this line: 95 | 96 | ```js 97 | eleventyConfig.addPassthroughCopy({ "src/static/og-default.jpg": "/og-default.jpg" }); 98 | ``` 99 | 100 | ### RSS logic 101 | By default this template collects all posts under `src/content/posts` to populate the RSS feed. You would most likely want something different for your project. If you visit `etc/collections/index.js` and edit the following to fit your needs: 102 | 103 | ```js 104 | export const feed = i => i.getFilteredByGlob("./src/content/posts/*.md").reverse(); 105 | ``` 106 | 107 | ### Responsive images 108 | Images are stored in their original format under `src/media`, although you can organise images in any way in this project. 109 | 110 | This project adheres to Markdown syntax as much as possible and uses [Markdown-it-eleventy-img](https://www.npmjs.com/package/markdown-it-eleventy-img) in order to leverage the magic of [Eleventy Image](https://www.11ty.dev/docs/plugins/image/) to generate responsive images based on your needs (so you can do something like this `![The depths of space showing an immense variety of colour across millions of stars.](./src/media/jeremy-thomas-E0AHdsENmDg-unsplash.jpg "Space by Jeremy Thomas")` and get all the responsive benefits without much effort). 111 | 112 | For images imported using Markdown syntax, this project wraps images in a `
` by default and a `
` is rendered if a `title` attribute is applied to your image (e.g. `![Alt text](..link/to/image.jpg "Title text")`). 113 | 114 | Finally, if a gif is imported it is assumed this is animated, so relevant logic is set to make that possible. 115 | 116 | You will most likely want to adapt widths, sizes and formats to suit your projects needs. You will want to edit the Markdown-it library located in `lib/markdown.js` and find these object keys: 117 | 118 | ```js 119 | const eleventyImageOptions = { 120 | imgOptions: { 121 | widths: [300, 600, 1200, 1800, 2150], 122 | urlPath: "/img/", 123 | outputDir: "./dist/img/", 124 | formats: ["avif", "jpeg"], 125 | }, 126 | globalAttributes: { 127 | decoding: "async", 128 | loading: "lazy", 129 | sizes: "(max-width: 72rem) 100vw, 75vw", 130 | }, 131 | ... 132 | .. 133 | . 134 | ``` 135 | 136 | --- 137 | 138 | **With that all said and done you should be ready to get on with your project. Good going!** -------------------------------------------------------------------------------- /eleventy.config.js: -------------------------------------------------------------------------------- 1 | // Enable type definitions: https://www.11ty.dev/docs/config/#type-definitions 2 | /** @param {import("@11ty/eleventy/src/UserConfig")} eleventyConfig */ 3 | 4 | import pluginNavigation from "@11ty/eleventy-navigation"; 5 | import pluginRss from "@11ty/eleventy-plugin-rss"; 6 | import pluginSyntax from "@11ty/eleventy-plugin-syntaxhighlight"; 7 | import lightningcss from "@11tyrocks/eleventy-plugin-lightningcss"; 8 | 9 | import { markdownParser } from "./lib/markdown.js"; 10 | import * as collections from "./etc/collections/index.js"; 11 | import * as filters from "./etc/filters/index.js"; 12 | import * as transforms from "./etc/transforms/index.js"; 13 | 14 | export default function (eleventyConfig) { 15 | // Plugins 16 | eleventyConfig.addPlugin(pluginNavigation); 17 | eleventyConfig.addPlugin(pluginRss); 18 | eleventyConfig.addPlugin(pluginSyntax); 19 | eleventyConfig.addPlugin(lightningcss); 20 | 21 | // Libraries 22 | eleventyConfig.setLibrary("md", markdownParser()); 23 | 24 | // Collections 25 | eleventyConfig.addCollection("posts", collections.posts); 26 | eleventyConfig.addCollection("feed", collections.feed); 27 | eleventyConfig.addCollection("curated", collections.curated); 28 | 29 | // Filters 30 | eleventyConfig.addFilter("dateToDMY", filters.dateToDMY); 31 | eleventyConfig.addFilter("dateToTime", filters.dateToTime); 32 | eleventyConfig.addFilter("dateToYear", filters.dateToYear); 33 | eleventyConfig.addFilter("dateToMonth", filters.dateToMonth); 34 | eleventyConfig.addFilter("dateToUNIX", filters.dateToUNIX); 35 | 36 | // Transforms 37 | eleventyConfig.addTransform("htmlmin", transforms.htmlmin); 38 | 39 | // Passthrough copies 40 | eleventyConfig.addPassthroughCopy({ "src/static/fonts": "/fonts" }); 41 | eleventyConfig.addPassthroughCopy({ "src/static/favicons/*": "/" }); 42 | eleventyConfig.addPassthroughCopy({ 43 | "src/static/og-default.jpg": "/og-default.jpg", 44 | }); 45 | 46 | // Watch targets 47 | eleventyConfig.addWatchTarget("./src/_styles/**/*.css"); 48 | 49 | return { 50 | dir: { 51 | input: "src", 52 | output: "dist", 53 | data: "_data", 54 | }, 55 | templateFormats: ["css", "html", "md", "njk", "11ty.js"], 56 | markdownTemplateEngine: "njk", 57 | htmlTemplateEngine: "njk", 58 | }; 59 | } 60 | -------------------------------------------------------------------------------- /etc/collections/index.js: -------------------------------------------------------------------------------- 1 | export const posts = i => i.getFilteredByGlob("./src/content/posts/*.md").reverse(); 2 | export const feed = i => i.getFilteredByGlob("./src/content/posts/*.md").reverse(); 3 | export const curated = i => 4 | i 5 | .getAllSorted() 6 | .filter(post => post.data.curated) 7 | .reverse(); 8 | -------------------------------------------------------------------------------- /etc/filters/filters.js: -------------------------------------------------------------------------------- 1 | import { DateTime } from "luxon"; 2 | 3 | // Add ordinal suffix to day 4 | const addSuffix = i => { 5 | const s = ["th", "st", "nd", "rd"]; 6 | const v = i % 100; 7 | return i + (s[(v - 20) % 10] || s[v] || s[0]); 8 | }; 9 | 10 | // Return day/month/year (with suffix) 11 | export const dateToDMY = i => { 12 | const getDay = DateTime.fromJSDate(i).toFormat("d").toString(); 13 | const getDayWithSuffix = addSuffix(getDay); 14 | const getMonth = DateTime.fromJSDate(i).toFormat("LLLL").toString(); 15 | const getYear = DateTime.fromJSDate(i).toFormat("y").toString(); 16 | return `${getDayWithSuffix} ${getMonth} ${getYear}`; 17 | }; 18 | 19 | // Return time 20 | export const dateToTime = i => { 21 | return DateTime.fromJSDate(i).toFormat("HH':'mm").toString(); 22 | }; 23 | 24 | // Return just year 25 | export const dateToYear = i => { 26 | return DateTime.fromJSDate(i).toFormat("y").toString(); 27 | }; 28 | 29 | // Return just month 30 | export const dateToMonth = i => { 31 | return DateTime.fromJSDate(i).toFormat("LL").toString(); 32 | }; 33 | 34 | // Return UNIX 35 | export const dateToUNIX = i => { 36 | return DateTime.fromJSDate(i).toFormat("x").toString(); 37 | }; 38 | -------------------------------------------------------------------------------- /etc/filters/index.js: -------------------------------------------------------------------------------- 1 | import { DateTime } from "luxon"; 2 | 3 | // Add ordinal suffix to day 4 | const addSuffix = i => { 5 | const s = ["th", "st", "nd", "rd"]; 6 | const v = i % 100; 7 | return i + (s[(v - 20) % 10] || s[v] || s[0]); 8 | }; 9 | 10 | // Return day/month/year (with suffix) 11 | export const dateToDMY = i => { 12 | const getDay = DateTime.fromJSDate(i).toFormat("d").toString(); 13 | const getDayWithSuffix = addSuffix(getDay); 14 | const getMonth = DateTime.fromJSDate(i).toFormat("LLLL").toString(); 15 | const getYear = DateTime.fromJSDate(i).toFormat("y").toString(); 16 | return `${getDayWithSuffix} ${getMonth} ${getYear}`; 17 | }; 18 | 19 | // Return time 20 | export const dateToTime = i => { 21 | return DateTime.fromJSDate(i).toFormat("HH':'mm").toString(); 22 | }; 23 | 24 | // Return just year 25 | export const dateToYear = i => { 26 | return DateTime.fromJSDate(i).toFormat("y").toString(); 27 | }; 28 | 29 | // Return just month 30 | export const dateToMonth = i => { 31 | return DateTime.fromJSDate(i).toFormat("LL").toString(); 32 | }; 33 | 34 | // Return UNIX 35 | export const dateToUNIX = i => { 36 | return DateTime.fromJSDate(i).toFormat("x").toString(); 37 | }; 38 | -------------------------------------------------------------------------------- /etc/transforms/index.js: -------------------------------------------------------------------------------- 1 | import { minify } from "html-minifier"; 2 | 3 | export const htmlmin = function (content) { 4 | if ((this.page.outputPath || "").endsWith(".html")) { 5 | let minified = minify(content, { 6 | minifyJS: true, 7 | minifyCSS: true, 8 | removeComments: true, 9 | preserveLineBreaks: true, 10 | collapseWhitespace: true, 11 | removeEmptyElements: true, 12 | }); 13 | return minified; 14 | } 15 | return content; 16 | }; 17 | -------------------------------------------------------------------------------- /lib/markdown.js: -------------------------------------------------------------------------------- 1 | import markdown from "markdown-it"; 2 | import markdownItAttrs from "markdown-it-attrs"; 3 | import markdownItSub from "markdown-it-sub"; 4 | import markdownItSup from "markdown-it-sup"; 5 | import markdownItDefList from "markdown-it-deflist"; 6 | import markdownItFootnote from "markdown-it-footnote"; 7 | import markdownItEleventyImage from "markdown-it-eleventy-img"; 8 | 9 | export const markdownParser = () => { 10 | const parserOptions = { 11 | html: true, 12 | linkify: true, 13 | }; 14 | 15 | const linkifyOptions = { 16 | fuzzyEmail: false, 17 | }; 18 | 19 | const eleventyImageOptions = { 20 | imgOptions: { 21 | widths: [300, 600, 1200, 1800, 2150], 22 | urlPath: "/img/", 23 | outputDir: "./dist/img/", 24 | formats: ["avif", "jpeg"], 25 | }, 26 | globalAttributes: { 27 | decoding: "async", 28 | loading: "lazy", 29 | sizes: "(max-width: 72rem) 100vw, 75vw", 30 | }, 31 | renderImage(image, attributes) { 32 | const [Image, options] = image; 33 | const [src, attrs] = attributes; 34 | 35 | if (src.substring(src.lastIndexOf(".") + 1, src.length) == "gif") { 36 | options.formats = ["webp", "gif"]; 37 | options.sharpOptions = { 38 | animated: true, 39 | }; 40 | } 41 | 42 | Image(src, options); 43 | 44 | const metadata = Image.statsSync(src, options); 45 | const imageMarkup = Image.generateHTML(metadata, attrs, { 46 | whitespaceMode: "inline", 47 | }); 48 | 49 | return `
${imageMarkup}${ 50 | attrs.title ? `
${attrs.title}
` : "" 51 | }
`; 52 | }, 53 | }; 54 | 55 | const parser = markdown(parserOptions); 56 | 57 | parser.linkify.set(linkifyOptions); 58 | 59 | parser 60 | .use(markdownItAttrs) 61 | .use(markdownItSub) 62 | .use(markdownItSup) 63 | .use(markdownItDefList) 64 | .use(markdownItFootnote) 65 | .use(markdownItEleventyImage, eleventyImageOptions); 66 | 67 | parser.renderer.rules.footnote_block_open = () => { 68 | return `
\n

Footnotes

\n
    \n`; 69 | }; 70 | 71 | parser.renderer.rules.footnote_block_close = () => { 72 | return "
\n
\n"; 73 | }; 74 | 75 | return parser; 76 | }; 77 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "11ty-get-going", 3 | "version": "2.0.0", 4 | "description": "Just another 11ty starter kit.", 5 | "keywords": [ 6 | "eleventy", 7 | "eleventy template", 8 | "starter" 9 | ], 10 | "author": { 11 | "name": "Kevin Healy-Clarke" 12 | }, 13 | "engines": { 14 | "node": "^20.0.0" 15 | }, 16 | "type": "module", 17 | "scripts": { 18 | "clean": "rm -rf dist", 19 | "build:files": "npx @11ty/eleventy", 20 | "build": "run-p build:*", 21 | "serve:files": "npx @11ty/eleventy --quiet --incremental --serve", 22 | "serve": "run-p serve:*" 23 | }, 24 | "dependencies": { 25 | "@11ty/eleventy": "3.0.0-alpha.6", 26 | "@11ty/eleventy-img": "^3.1.0", 27 | "@11ty/eleventy-navigation": "^0.3.5", 28 | "@11ty/eleventy-plugin-rss": "^1.2.0", 29 | "@11ty/eleventy-plugin-syntaxhighlight": "^5.0.0", 30 | "@11tyrocks/eleventy-plugin-lightningcss": "^1.4.0", 31 | "html-minifier": "^4.0.0", 32 | "markdown-it": "^13.0.1", 33 | "markdown-it-attrs": "^4.1.6", 34 | "markdown-it-deflist": "^2.1.0", 35 | "markdown-it-eleventy-img": "^0.10.2", 36 | "markdown-it-footnote": "^3.0.3", 37 | "markdown-it-sub": "^1.0.0", 38 | "markdown-it-sup": "^1.0.0", 39 | "npm-run-all": "^4.1.5" 40 | }, 41 | "devDependencies": { 42 | "prettier": "^2.8.0" 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | import { default as easyImport } from "postcss-easy-import"; 2 | import { default as customSelectors } from "postcss-custom-selectors"; 3 | import { default as extendRule } from "postcss-extend-rule"; 4 | import { default as customMedia } from "postcss-custom-media"; 5 | import { default as nano } from "cssnano"; 6 | 7 | export default { 8 | plugins: [easyImport, customSelectors, extendRule, customMedia, nano({ preset: "default" })], 9 | }; 10 | -------------------------------------------------------------------------------- /src/_data/config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | projectName: "11ty Get Going", 3 | description: "Just another 11ty starter kit", 4 | shortName: "11ty GG", 5 | domain: 6 | process.env.ELEVENTY_RUN_MODE == "serve" ? "http://localhost:8080" : "https://example.com", 7 | robots: "index, follow", 8 | themeColor: "#FFFFFF", 9 | backgroundColor: "#FFFFFF", 10 | author: { 11 | name: "Author Name", 12 | email: "author@email.com", 13 | }, 14 | identity: [ 15 | { 16 | rel: "me", 17 | url: "URL-GOES-HERE", 18 | }, 19 | ], 20 | og: { 21 | locale: "en_GB", 22 | type: "website", 23 | image: { 24 | rel: "/og-default.jpg", 25 | alt: "Default OG image displayed here", 26 | }, 27 | }, 28 | }; 29 | -------------------------------------------------------------------------------- /src/_data/helpers.js: -------------------------------------------------------------------------------- 1 | const dateNow = new Date(); 2 | 3 | export default { 4 | dateNow, 5 | }; 6 | -------------------------------------------------------------------------------- /src/_includes/layouts/base.njk: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {% include "partials/base-head.njk" %} 5 | 6 | 7 | 8 | {% include "partials/site-header.njk" %} 9 |
10 | {% block content %}{% endblock %} 11 |
12 | {% include "partials/site-footer.njk" %} 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/_includes/layouts/error.njk: -------------------------------------------------------------------------------- 1 | {% extends "layouts/base.njk" %} 2 | 3 | {% block content %} 4 |
5 |
6 |

{{ title }}

7 | {{ content | safe }} 8 |
9 |
10 | {% endblock %} -------------------------------------------------------------------------------- /src/_includes/layouts/index.njk: -------------------------------------------------------------------------------- 1 | {% extends "layouts/base.njk" %} 2 | 3 | {% set title = config.projectName %} 4 | 5 | {% block content %} 6 |
7 |

{{ title }}

8 |
9 | {{ content | safe }} 10 |
11 |
12 | 21 |
22 |
23 | {% endblock %} -------------------------------------------------------------------------------- /src/_includes/layouts/list.njk: -------------------------------------------------------------------------------- 1 | {% extends "layouts/base.njk" %} 2 | 3 | {% block content %} 4 |
5 |

{{ title }}

6 |
7 |
    8 | {% for item in pagination.items %} 9 | {% include "partials/site-post-list.njk" %} 10 | {% endfor %} 11 |
12 |
13 | {% if pagination.href.next or pagination.href.previous %} 14 |
15 | {% include "partials/site-pagination.njk" %} 16 |
17 | {% endif %} 18 | 19 |
20 | {% endblock %} -------------------------------------------------------------------------------- /src/_includes/layouts/page.njk: -------------------------------------------------------------------------------- 1 | {% extends "layouts/base.njk" %} 2 | 3 | {% block content %} 4 |
5 |

{{ title }}

6 |
7 | {{ content | safe }} 8 |
9 |
10 | {% endblock %} -------------------------------------------------------------------------------- /src/_includes/layouts/post.njk: -------------------------------------------------------------------------------- 1 | {% extends "layouts/base.njk" %} 2 | 3 | {% block content %} 4 |
5 |

{{ title }}

6 |
7 | {% if tags %} 8 |

Tags

9 |
    10 | {% for item in tags %} 11 |
  • {{ item }}
  • 12 | {% endfor %} 13 |
14 | {% endif %} 15 | {{ content | safe }} 16 |
17 |
18 | {% endblock %} -------------------------------------------------------------------------------- /src/_includes/layouts/tag-results.njk: -------------------------------------------------------------------------------- 1 | {% extends "layouts/base.njk" %} 2 | 3 | {% block content %} 4 |
5 |

Tagged “{{ tag }}”

6 |
7 |
    8 | {% for item in collections[tag] | reverse %} 9 | {% include "partials/site-post-list.njk" %} 10 | {% endfor %} 11 |
12 |
13 |
14 | {% endblock %} -------------------------------------------------------------------------------- /src/_includes/partials/base-head.njk: -------------------------------------------------------------------------------- 1 | {# - Head order thanks to https://github.com/rviscomi/capo.js #} 2 | 3 | {# Page title format #} 4 | {% set pageTitle = title + ': ' + config.projectName %} 5 | {# Remove any title duplication #} 6 | {% if title === config.projectName %} {% set pageTitle = title %} {% endif %} 7 | 8 | {# URL formats #} 9 | {% set thisUrl = config.domain + page.url %} 10 | 11 | 12 | 13 | 14 | {{ pageTitle }} 15 | 16 | 17 | 18 | {# ------------ Prefetches? Place here ------------ #} 19 | 20 | 21 | 22 | 23 | 24 | 25 | {% if config.og %} 26 | 27 | 28 | 29 | {% if config.og.locale %} 30 | 31 | {% endif %} 32 | {% if config.og.type %} 33 | 34 | {% endif %} 35 | {% if config.og.image %} 36 | 37 | 38 | {% endif %} 39 | {% endif %} 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | {# Identity loop #} 48 | {% if config.identity %} 49 | {% for item in config.identity %} 50 | 51 | {% endfor %} 52 | {% endif %} 53 | 54 | {# - Minimal favicons thanks to https://evilmartians.com/chronicles/how-to-favicon-in-2021-six-files-that-fit-most-needs #} 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /src/_includes/partials/card-list-index.njk: -------------------------------------------------------------------------------- 1 |
2 | 16 |
-------------------------------------------------------------------------------- /src/_includes/partials/site-footer.njk: -------------------------------------------------------------------------------- 1 |
2 |
3 |

Last update on {{ helpers.dateNow | dateToDMY }} at {{ helpers.dateNow | dateToTime }}

4 |
5 |
-------------------------------------------------------------------------------- /src/_includes/partials/site-header.njk: -------------------------------------------------------------------------------- 1 | {# Skip to main content https://design-system.service.gov.uk/components/skip-link/ #} 2 | {# We'll render home "/" manually to avoid any navigation headaches for rendering active class #} 3 | {# We loop through eleventyNavigation and check if item.url e.g. /posts/ is in page.url and set active class. Stuck with this method for the moment until a relationship between Eleventy Navigation and Eleventy Pagination is figured out #} 4 | {# Recommend using aria-current="page" instead of active class if your project is surfacing all navigation items #} 5 | 6 | 7 |
8 | 24 |
-------------------------------------------------------------------------------- /src/_includes/partials/site-pagination.njk: -------------------------------------------------------------------------------- 1 | {# Uses Nunjucks special variable loop.index0 to target the current iteration of a loop #} 2 | 3 | -------------------------------------------------------------------------------- /src/_includes/partials/site-post-list.njk: -------------------------------------------------------------------------------- 1 |
  • {{ item.data.title }}: {{ item.date | dateToDMY }}
  • -------------------------------------------------------------------------------- /src/_styles/_components/_card-list.css: -------------------------------------------------------------------------------- 1 | .card-list ul { 2 | display: grid; 3 | grid-template-columns: auto; 4 | column-gap: var(--space-xs-s); 5 | margin: 0; 6 | padding: 0; 7 | list-style: none; 8 | } 9 | 10 | .card-list ul li { 11 | margin-block-start: 0; 12 | padding: var(--space-xs-s) 0; 13 | border-bottom: 2px solid var(--color-border-default); 14 | } 15 | 16 | .card-list ul li:first-of-type { 17 | border-top: 2px solid var(--color-border-default); 18 | } 19 | 20 | @media (--from-medium-viewport) { 21 | .card-list ul { 22 | grid-template-columns: auto auto; 23 | column-gap: var(--space-m-l); 24 | } 25 | .card-list ul li:nth-child(2) { 26 | border-top: 2px solid var(--color-border-default); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/_styles/_components/_footnotes.css: -------------------------------------------------------------------------------- 1 | .footnotes { 2 | margin-block-start: var(--space-l-xl); 3 | } 4 | 5 | .footnotes a { 6 | word-wrap: break-word; 7 | } 8 | -------------------------------------------------------------------------------- /src/_styles/_components/_site-footer.css: -------------------------------------------------------------------------------- 1 | .site-footer { 2 | margin-block-start: var(--space-l-xl); 3 | padding-bottom: var(--space-2xl-3xl); 4 | } 5 | -------------------------------------------------------------------------------- /src/_styles/_components/_site-header.css: -------------------------------------------------------------------------------- 1 | .skip-link { 2 | font-family: var(--font-family-sans); 3 | font-weight: 500; 4 | display: block; 5 | width: 100%; 6 | padding: var(--space-xs); 7 | background-color: var(--color-surface-secondary); 8 | } 9 | 10 | .main-nav { 11 | padding: var(--space-s-m) 0; 12 | margin-block-end: var(--space-xl-2xl); 13 | } 14 | 15 | .main-nav ul { 16 | margin: 0; 17 | padding: 0; 18 | list-style: none; 19 | } 20 | 21 | .main-nav-item--active { 22 | color: var(--color-text-default); 23 | text-decoration: none; 24 | } 25 | 26 | @media (--from-medium-viewport) { 27 | .main-nav ul { 28 | display: flex; 29 | } 30 | 31 | .main-nav ul li { 32 | margin-inline-end: var(--space-xs-s); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/_styles/_components/_site-pagination.css: -------------------------------------------------------------------------------- 1 | .site-pagination { 2 | margin-block-start: var(--space-m-l); 3 | } 4 | 5 | .site-pagination ul { 6 | margin: 0; 7 | padding: 0; 8 | list-style: none; 9 | display: flex; 10 | } 11 | 12 | .site-pagination ul li { 13 | margin-inline-end: var(--space-xs-s); 14 | } 15 | 16 | .site-pagination a[aria-current="page"] { 17 | color: var(--color-text-default); 18 | text-decoration: none; 19 | } 20 | -------------------------------------------------------------------------------- /src/_styles/_config/_import.css: -------------------------------------------------------------------------------- 1 | /* @font-face rules */ 2 | -------------------------------------------------------------------------------- /src/_styles/_config/_media.css: -------------------------------------------------------------------------------- 1 | /* Smallest viewport: 320px */ 2 | @custom-media --upto-smallest-viewport (max-width: 20em); 3 | @custom-media --from-smallest-viewport (min-width: 20em); 4 | 5 | /* Small viewport: 480px */ 6 | @custom-media --upto-small-viewport (max-width: 30em); 7 | @custom-media --from-small-viewport (min-width: 30em); 8 | 9 | /* Medium viewport: 768px */ 10 | @custom-media --upto-medium-viewport (max-width: 48em); 11 | @custom-media --from-medium-viewport (min-width: 48em); 12 | 13 | /* Large viewport: 1100px */ 14 | @custom-media --upto-large-viewport (max-width: 68.75em); 15 | @custom-media --from-large-viewport (min-width: 68.75em); 16 | 17 | /* Largest viewport: 1480px */ 18 | @custom-media --upto-largest-viewport (max-width: 92.5em); 19 | @custom-media --from-largest-viewport (min-width: 92.5em); 20 | -------------------------------------------------------------------------------- /src/_styles/_layout/_content.css: -------------------------------------------------------------------------------- 1 | .content-main { 2 | --flow-space: var(--space-2xs-xs); 3 | margin-block-start: var(--space-s-m); 4 | } 5 | 6 | .content-main 7 | :is( 8 | * + h2, 9 | * + figure, 10 | * + .card-list, 11 | * + pre[class*="language-"], 12 | pre[class*="language-"] + *, 13 | * + hr, 14 | hr + * 15 | ) { 16 | --flow-space: var(--space-l-xl); 17 | } 18 | 19 | .content-main :is(* + h3) { 20 | --flow-space: var(--space-m-l); 21 | } 22 | 23 | .content-main :is(* + h4) { 24 | --flow-space: var(--space-s-m); 25 | } 26 | 27 | .content-aside { 28 | --flow-space: var(--space-xs-s); 29 | margin-block-start: var(--space-l); 30 | padding: var(--space-l); 31 | border-radius: var(--border-radius-small); 32 | background-color: var(--color-surface-secondary); 33 | } 34 | -------------------------------------------------------------------------------- /src/_styles/_layout/_layout-grid.css: -------------------------------------------------------------------------------- 1 | .layout-grid { 2 | display: grid; 3 | grid-template-columns: [main-start] 5fr [main-end] var(--space-s-m) [aside-start] 2fr [aside-end]; 4 | column-gap: var(--space-s-m); 5 | } 6 | 7 | .layout-span { 8 | grid-column: main-start / aside-end; 9 | } 10 | 11 | @media (--from-large-viewport) { 12 | .layout-span--main { 13 | grid-column: main-start / main-end; 14 | } 15 | 16 | .layout-span--aside { 17 | grid-column: aside-start / aside-end; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/_styles/_layout/_wrapper.css: -------------------------------------------------------------------------------- 1 | .wrapper { 2 | margin-inline-start: var(--space-m-l); 3 | margin-inline-end: var(--space-m-l); 4 | max-width: var(--wrapper-max); 5 | } 6 | 7 | @media (--from-large-viewport) { 8 | .wrapper { 9 | margin-inline-start: auto; 10 | margin-inline-end: auto; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/_styles/_types.css: -------------------------------------------------------------------------------- 1 | *, 2 | *::before, 3 | *::after { 4 | box-sizing: border-box; 5 | } 6 | 7 | *::selection { 8 | background-color: var(--color-highlight); 9 | } 10 | 11 | /* Ref: https://andy-bell.co.uk/a-modern-css-reset/ */ 12 | @media (prefers-reduced-motion: reduce) { 13 | *, 14 | *::before, 15 | *::after { 16 | animation-duration: 0.01ms !important; 17 | animation-iteration-count: 1 !important; 18 | transition-duration: 0.01ms !important; 19 | scroll-behavior: auto !important; 20 | } 21 | } 22 | 23 | html { 24 | -webkit-font-smoothing: antialiased; 25 | -webkit-text-size-adjust: 100%; 26 | font-feature-settings: normal; 27 | font-variant-ligatures: common-ligatures; 28 | text-rendering: optimizeSpeed; 29 | font-variation-settings: "slnt" 0; /* Variable font Safari fix */ 30 | } 31 | 32 | html:focus-within { 33 | scroll-behavior: smooth; 34 | } 35 | 36 | /* Edits: ins, del */ 37 | 38 | /* Embedded content: img, iframe, embed, object, param, video, audio, source, track, canvas, map, area */ 39 | 40 | img, 41 | video { 42 | max-width: 100%; 43 | height: auto; 44 | display: block; 45 | } 46 | 47 | /* Forms: form, fieldset, legend, label, input, button, select, datalist, optgroup, option, textarea, keygen, output, progress, meter */ 48 | 49 | input, 50 | button, 51 | optgroup, 52 | textarea, 53 | select { 54 | font-family: inherit; 55 | margin: 0; 56 | } 57 | 58 | /* Grouping content: p, hr, br, pre, blockquote, ol, ul, li, dl, dt, dd, figure, figcaption, div */ 59 | 60 | p, 61 | ul, 62 | ol, 63 | li, 64 | figure, 65 | figcaption, 66 | blockquote, 67 | pre, 68 | hr { 69 | margin: 0; 70 | } 71 | 72 | ul, 73 | ol { 74 | list-style-position: outside; 75 | } 76 | 77 | ul { 78 | margin-inline-start: -1.5em; 79 | } 80 | 81 | ol { 82 | margin-inline-start: -0.5em; 83 | } 84 | 85 | p, 86 | li, 87 | figcaption { 88 | font-family: var(--font-family-sans); 89 | font-weight: 400; 90 | color: var(--color-text-default); 91 | font-size: var(--step-0); 92 | line-height: var(--leading-default); 93 | } 94 | 95 | li { 96 | margin-block-start: 0.5em; 97 | } 98 | 99 | figure { 100 | margin: 0; 101 | padding: 0; 102 | } 103 | 104 | figure:has(figcaption) { 105 | border-bottom: 1px solid var(--color-border-default); 106 | } 107 | 108 | figcaption { 109 | padding: var(--space-xs-s) 0; 110 | max-width: var(--measure-default); 111 | } 112 | 113 | p, 114 | li { 115 | max-width: var(--measure-default); 116 | } 117 | 118 | hr { 119 | border: none; 120 | background-color: var(--color-border-default); 121 | height: 1px; 122 | } 123 | 124 | /* Interactive elements: details, summary, command, menu */ 125 | 126 | /* Sections: body, section, nav, article, aside, h1, h2, h3, h4, h5, h6, hgroup, header, footer, address */ 127 | 128 | body { 129 | min-height: 100vh; 130 | margin: 0; 131 | background: var(--color-surface-default); 132 | } 133 | 134 | h1, 135 | h2, 136 | h3, 137 | h4, 138 | h5, 139 | h6, 140 | hgroup { 141 | max-width: var(--measure-tight); 142 | margin: 0; 143 | } 144 | 145 | h1, 146 | h2, 147 | h3, 148 | h4, 149 | h5, 150 | h6 { 151 | font-family: var(--font-family-sans); 152 | color: var(--color-text-default); 153 | } 154 | 155 | h1 { 156 | font-weight: 900; 157 | font-size: var(--step-4); 158 | line-height: var(--leading-tight); 159 | } 160 | 161 | h2 { 162 | font-weight: 800; 163 | font-size: var(--step-2); 164 | line-height: var(--leading-tight); 165 | } 166 | 167 | h3 { 168 | font-weight: 600; 169 | font-size: var(--step-1); 170 | line-height: var(--leading-default); 171 | } 172 | 173 | h4, 174 | h5, 175 | h6 { 176 | font-weight: 600; 177 | font-size: var(--step-1); 178 | line-height: var(--leading-default); 179 | } 180 | 181 | /* Tables: table, caption, colgroup, col, tbody, thead, tfoot, tr, td, th */ 182 | 183 | table, 184 | fieldset { 185 | margin: 0; 186 | } 187 | 188 | /* Text-level semantics: a, em, strong, small, s, cite, q, dfn, abbr, time, code, var, samp, kbd, sub, sup, i, b, u, mark, ruby, rt, rp, bdi, bdo, span */ 189 | 190 | a { 191 | font-weight: 500; 192 | color: var(--color-interactive-default); 193 | } 194 | 195 | a:hover { 196 | color: var(--color-interactive-hover); 197 | } 198 | 199 | a:active { 200 | color: var(--color-interactive-default); 201 | } 202 | a:focus { 203 | outline: 1px solid var(--color-interactive-focus-ring); 204 | outline-offset: 2px; 205 | } 206 | 207 | a:focus-visible { 208 | outline: 2px solid var(--color-interactive-focus-ring); 209 | outline-offset: 2px; 210 | } 211 | 212 | a:not([class]) { 213 | text-decoration-skip-ink: auto; 214 | text-decoration-line: underline; 215 | text-decoration-color: var(--color-interactive-default); 216 | text-decoration-thickness: 2px; 217 | text-underline-offset: 3px; 218 | } 219 | 220 | code { 221 | font-family: var(--font-family-code); 222 | font-size: 95%; 223 | color: var(--color-text-code-default); 224 | } 225 | 226 | b, 227 | strong { 228 | font-weight: 800; 229 | color: var(--color-grey-80); 230 | } 231 | 232 | sub { 233 | line-height: 0; 234 | vertical-align: -0.35em; 235 | } 236 | 237 | sup { 238 | line-height: 0; 239 | vertical-align: 0.35em; 240 | } 241 | -------------------------------------------------------------------------------- /src/_styles/_utilities.css: -------------------------------------------------------------------------------- 1 | .flow > * + * { 2 | margin-block-start: var(--flow-space, 1em); 3 | } 4 | 5 | /* https://css-tricks.com/inclusively-hidden/ */ 6 | .visually-hidden:not(:focus) { 7 | clip: rect(0 0 0 0); 8 | clip-path: inset(50%); 9 | border: 0; 10 | block-size: 1px; 11 | inline-size: 1px; 12 | padding: 0; 13 | overflow: hidden; 14 | position: absolute; 15 | white-space: nowrap; 16 | } 17 | -------------------------------------------------------------------------------- /src/_styles/_variables.css: -------------------------------------------------------------------------------- 1 | :root { 2 | /* Colour */ 3 | --color-surface-default: hsl(33, 15%, 88%); 4 | --color-surface-secondary: hsl(33, 13%, 94%); 5 | --color-highlight: hsl(216, 100%, 88%); 6 | --color-text-default: hsl(105, 4%, 22%); 7 | --color-text-code-default: hsl(105, 10%, 42%); 8 | --color-text-code-attr: hsl(358, 85%, 38%); 9 | --color-text-code-function: hsl(24, 85%, 31%); 10 | --color-text-code-class: hsl(39, 92%, 35%); 11 | --color-text-code-selector: hsl(299, 54%, 40%); 12 | --color-text-code-variable: hsl(143, 59%, 34%); 13 | --color-text-code-url: hsl(179, 50%, 30%); 14 | --color-interactive-default: hsl(216, 100%, 56%); 15 | --color-interactive-hover: hsl(216, 100%, 26%); 16 | --color-interactive-focus: hsl(216, 100%, 26%); 17 | --color-interactive-focus-ring: hsl(216, 100%, 76%); 18 | --color-border-default: hsl(83, 4%, 68%); 19 | 20 | /* Font */ 21 | --font-family-sans: system-ui, -apple-system, sans-serif; 22 | --font-family-code: ui-monospace, "Cascadia Code", "Source Code Pro", Menlo, Consolas, 23 | "DejaVu Sans Mono", monospace; 24 | 25 | /* Fluid type and space, thanks to https://utopia.fyi/ */ 26 | /* Font size */ 27 | --step-0: clamp(1rem, calc(1rem + 0.12vw), 1.15rem); 28 | --step-1: clamp(1.2rem, calc(1.16rem + 0.19vw), 1.33rem); 29 | --step-2: clamp(1.44rem, calc(1.34rem + 0.48vw), 1.78rem); 30 | --step-3: clamp(1.73rem, calc(1.55rem + 0.92vw), 2.37rem); 31 | --step-4: clamp(2.07rem, calc(1.76rem + 1.55vw), 3.16rem); 32 | --step-5: clamp(2.49rem, calc(2rem + 2.46vw), 4.21rem); 33 | 34 | /* Leading */ 35 | --leading-tight: 1.1; 36 | --leading-default: 1.4; 37 | --leading-loose: 1.6; 38 | 39 | /* Measure */ 40 | --measure-default: 70ch; 41 | --measure-tight: 48ch; 42 | 43 | /* Spacing */ 44 | --space-3xs: clamp(0.25rem, calc(0.25rem + 0vw), 0.25rem); 45 | --space-2xs: clamp(0.5rem, calc(0.5rem + 0vw), 0.5rem); 46 | --space-xs: clamp(0.75rem, calc(0.75rem + 0vw), 0.75rem); 47 | --space-s: clamp(1rem, calc(1rem + 0vw), 1rem); 48 | --space-m: clamp(1.5rem, calc(1.5rem + 0vw), 1.5rem); 49 | --space-l: clamp(2rem, calc(2rem + 0vw), 2rem); 50 | --space-xl: clamp(3rem, calc(3rem + 0vw), 3rem); 51 | --space-2xl: clamp(4rem, calc(4rem + 0vw), 4rem); 52 | --space-3xl: clamp(6rem, calc(6rem + 0vw), 6rem); 53 | /* One-up pairs */ 54 | --space-3xs-2xs: clamp(0.25rem, calc(0.18rem + 0.36vw), 0.5rem); 55 | --space-2xs-xs: clamp(0.5rem, calc(0.43rem + 0.36vw), 0.75rem); 56 | --space-xs-s: clamp(0.75rem, calc(0.68rem + 0.36vw), 1rem); 57 | --space-s-m: clamp(1rem, calc(0.86rem + 0.71vw), 1.5rem); 58 | --space-m-l: clamp(1.5rem, calc(1.36rem + 0.71vw), 2rem); 59 | --space-l-xl: clamp(2rem, calc(1.71rem + 1.43vw), 3rem); 60 | --space-xl-2xl: clamp(3rem, calc(2.71rem + 1.43vw), 4rem); 61 | --space-2xl-3xl: clamp(4rem, calc(3.43rem + 2.86vw), 6rem); 62 | /* Custom pairs */ 63 | --space-s-l: clamp(1rem, calc(0.71rem + 1.43vw), 2rem); 64 | 65 | /* Border radius */ 66 | --border-radius-small: 1rem; 67 | 68 | /* Max width */ 69 | --wrapper-max: 64rem; 70 | } 71 | 72 | /* Dark mode preferences */ 73 | @media (prefers-color-scheme: dark) { 74 | :root { 75 | --color-surface-default: hsl(105, 4%, 8%); 76 | --color-surface-secondary: hsl(105, 4%, 4%); 77 | --color-highlight: hsl(216, 100%, 18%); 78 | --color-text-default: hsl(33, 15%, 88%); 79 | --color-text-code-default: hsl(33, 15%, 68%); 80 | --color-text-code-attr: hsl(358, 65%, 68%); 81 | --color-text-code-function: hsl(24, 85%, 61%); 82 | --color-text-code-class: hsl(41, 92%, 65%); 83 | --color-text-code-selector: hsl(299, 34%, 70%); 84 | --color-text-code-variable: hsl(143, 39%, 64%); 85 | --color-text-code-url: hsl(179, 50%, 60%); 86 | --color-interactive-hover: hsl(216, 100%, 86%); 87 | --color-interactive-focus: hsl(216, 100%, 86%); 88 | --color-border-default: hsl(83, 4%, 28%); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/_styles/_vendor/_prism.css: -------------------------------------------------------------------------------- 1 | /* PrismJS 1.29.0 2 | https://prismjs.com/download.html#themes=prism-tomorrow&languages=markup+css+clike+javascript+handlebars+markdown+markup-templating */ 3 | code[class*="language-"], 4 | pre[class*="language-"] { 5 | color: var(--color-text-code-default); 6 | background: 0 0; 7 | font-size: 1em; 8 | text-align: left; 9 | white-space: pre-wrap; 10 | word-spacing: normal; 11 | word-break: normal; 12 | word-wrap: normal; 13 | line-height: 1.5; 14 | -moz-tab-size: 4; 15 | -o-tab-size: 4; 16 | tab-size: 4; 17 | -webkit-hyphens: none; 18 | -moz-hyphens: none; 19 | -ms-hyphens: none; 20 | hyphens: none; 21 | } 22 | pre[class*="language-"] { 23 | margin-block-start: var(--space-l); 24 | padding: var(--space-l); 25 | border-radius: var(--border-radius-small); 26 | overflow: auto; 27 | } 28 | :not(pre) > code[class*="language-"], 29 | pre[class*="language-"] { 30 | background-color: var(--color-surface-secondary); 31 | } 32 | :not(pre) > code[class*="language-"] { 33 | padding: 0.1em; 34 | border-radius: 0.3em; 35 | white-space: normal; 36 | } 37 | .token.block-comment, 38 | .token.cdata, 39 | .token.comment, 40 | .token.doctype, 41 | .token.prolog { 42 | color: var(--color-text-code-default); 43 | } 44 | .token.punctuation { 45 | color: var(--color-text-code-default); 46 | } 47 | .token.attr-name, 48 | .token.deleted, 49 | .token.namespace, 50 | .token.tag { 51 | color: var(--color-text-code-attr); 52 | } 53 | .token.function-name, 54 | .token.boolean, 55 | .token.function, 56 | .token.number { 57 | color: var(--color-text-code-function); 58 | } 59 | .token.class-name, 60 | .token.constant, 61 | .token.property, 62 | .token.symbol { 63 | color: var(--color-text-code-class); 64 | } 65 | .token.atrule, 66 | .token.builtin, 67 | .token.important, 68 | .token.keyword, 69 | .token.selector { 70 | color: var(--color-text-code-selector); 71 | } 72 | .token.attr-value, 73 | .token.char, 74 | .token.regex, 75 | .token.string, 76 | .token.variable { 77 | color: var(--color-text-code-variable); 78 | } 79 | .token.entity, 80 | .token.operator, 81 | .token.url { 82 | color: var(--color-text-code-url); 83 | } 84 | .token.bold, 85 | .token.important { 86 | font-weight: 700; 87 | } 88 | .token.italic { 89 | font-style: italic; 90 | } 91 | .token.entity { 92 | cursor: help; 93 | } 94 | .token.inserted { 95 | color: green; 96 | } 97 | -------------------------------------------------------------------------------- /src/content/404.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: "layouts/error" 3 | title: "Page not found" 4 | permalink: "/404.html" 5 | --- 6 | 7 | It looks like this link has moved somewhere else or doesn't exist. Head [home](/) instead. 8 | -------------------------------------------------------------------------------- /src/content/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: "layouts/index" 3 | permalink: "/index.html" 4 | --- 5 | 6 | It works! 7 | 8 | Get Going is an 11ty starter project for simple blogs, small sites and prototypes. 9 | 10 | _Now upgraded to use ES6 modules and 11ty v3.0_ 🎉 11 | 12 | The following starting points and integrations come included: 13 | 14 | {% include "partials/card-list-index.njk" %} 15 | 16 | ## Requirements 17 | 18 | [Node version manager](https://github.com/nvm-sh/nvm) is recommended then simply `nvm use` and it will pull the version from the `.nvmrc` file in this repo. Any Node LTS version should suffice for this template. 19 | 20 | ### Running the project 21 | 22 | To run a version yourself, [clone the repo](https://github.com/kevh-c/11ty-get-going), `npm install` and then `npm run serve` to view the demo project locally. 23 | 24 | If you're intending to use Git LFS remember to `git lfs install` to enable it. -------------------------------------------------------------------------------- /src/content/posts.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: "layouts/list" 3 | eleventyNavigation: 4 | key: posts 5 | title: Example posts 6 | order: 2 7 | pagination: 8 | data: "collections.posts" 9 | size: 5 10 | permalink: "/posts{% if pagination.pageNumber > 0 %}/{{ pagination.pageNumber + 1 }}{% endif %}/index.html" 11 | title: "Posts" 12 | --- 13 | -------------------------------------------------------------------------------- /src/content/posts/2011-06-02-leviathan-wakes.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Leviathan Wakes" 3 | tags: 4 | - "book" 5 | - "tv series" 6 | --- 7 | ![The depths of space showing an immense variety of colour across millions of stars.](./src/media/jeremy-thomas-E0AHdsENmDg-unsplash.jpg "Space by Jeremy Thomas") 8 | 9 | ## Setting 10 | 11 | Humanity has colonized the solar system—Mars, the Moon, the Asteroid Belt and beyond—but the stars are still out of our reach. 12 | 13 | Jim Holden is XO of an ice miner making runs from the rings of Saturn to the mining stations of the Belt. When he and his crew stumble upon a derelict ship, the Scopuli, they find themselves in possession of a secret they never wanted. A secret that someone is willing to kill for—and kill on a scale unfathomable to Jim and his crew. War is brewing in the system unless he can find out who left the ship and why. 14 | 15 | Detective Miller is looking for a girl. One girl in a system of billions, but her parents have money and money talks. When the trail leads him to the Scopuli and rebel sympathizer Holden, he realizes that this girl may be the key to everything. 16 | 17 | Holden and Miller must thread the needle between the Earth government, the Outer Planet revolutionaries, and secretive corporations—and the odds are against them. But out in the Belt, the rules are different, and one small ship can change the fate of the universe.[^1] 18 | 19 | [^1]: Source: https://www.goodreads.com/book/show/8855321-leviathan-wakes -------------------------------------------------------------------------------- /src/content/posts/2012-06-26-calibans-war.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Caliban's War" 3 | curated: true 4 | tags: 5 | - "book" 6 | - "tv series" 7 | figureTest: 8 | caption: "This is a caption for the figure" 9 | --- 10 | 11 | ## Setting 12 | 13 | We are not alone. On Ganymede, breadbasket of the outer planets, a Martian marine watches as her platoon is slaughtered by a monstrous supersoldier. On Earth, a high-level politician struggles to prevent interplanetary war from reigniting. And on Venus, an alien protomolecule has overrun the planet, wreaking massive, mysterious changes and threatening to spread out into the solar system. 14 | 15 | In the vast wilderness of space, James Holden and the crew of the Rocinante have been keeping the peace for the Outer Planets Alliance. When they agree to help a scientist search war-torn Ganymede for a missing child, the future of humanity rests on whether a single ship can prevent an alien invasion that may have already begun ...[^1] 16 | 17 | ![The depths of space showing an immense variety of colour across millions of stars.](./src/media/andy-holmes-rCbdp8VCYhQ-unsplash.jpg "Andy Holmes") 18 | 19 | [^1]: Source: https://www.goodreads.com/book/show/12591698-caliban-s-war -------------------------------------------------------------------------------- /src/content/posts/2013-07-04-abaddons-gate.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Abaddon's Gate" 3 | tags: 4 | - "book" 5 | - "tv series" 6 | figureTest: 7 | caption: "This is a caption for the figure" 8 | --- 9 | 10 | ## Setting 11 | 12 | For generations, the solar system - Mars, the Moon, the Asteroid Belt - was humanity's great frontier. Until now. The alien artefact working through its program under the clouds of Venus has emerged to build a massive structure outside the orbit of Uranus: a gate that leads into a starless dark. 13 | 14 | Jim Holden and the crew of the Rocinante are part of a vast flotilla of scientific and military ships going out to examine the artefact. But behind the scenes, a complex plot is unfolding, with the destruction of Holden at its core. As the emissaries of the human race try to find whether the gate is an opportunity or a threat, the greatest danger is the one they brought with them.[^1] 15 | 16 | ![The depths of space showing an immense variety of colour across millions of stars.](./src/media/john-fowler-7Ym9rpYtSdA-unsplash.jpg "John Fowler") 17 | 18 | [^1]: Source: https://www.goodreads.com/book/show/16131032-abaddon-s-gate -------------------------------------------------------------------------------- /src/content/posts/2014-06-05-cibola-burn.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Cibola Burn" 3 | curated: true 4 | tags: 5 | - "book" 6 | - "tv series" 7 | figureTest: 8 | caption: "This is a caption for the figure" 9 | --- 10 | 11 | ## Setting 12 | 13 | The gates have opened the way to thousands of habitable planets, and the land rush has begun. Settlers stream out from humanity's home planets in a vast, poorly controlled flood, landing on a new world. Among them, the Rocinante, haunted by the vast, posthuman network of the protomolecule as they investigate what destroyed the great intergalactic society that built the gates and the protomolecule. 14 | 15 | But Holden and his crew must also contend with the growing tensions between the settlers and the company which owns the official claim to the planet. Both sides will stop at nothing to defend what's theirs, but soon a terrible disease strikes and only Holden - with help from the ghostly Detective Miller - can find the cure.[^1] 16 | 17 | ![The depths of space showing an immense variety of colour across millions of stars.](./src/media/jeremy-thomas-E0AHdsENmDg-unsplash.jpg "Space by Jeremy Thomas") 18 | 19 | [^1]: Source: https://www.goodreads.com/book/show/18656030-cibola-burn -------------------------------------------------------------------------------- /src/content/posts/2015-06-02-nemesis-games.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Nemesis Games" 3 | tags: 4 | - "book" 5 | - "tv series" 6 | figureTest: 7 | caption: "This is a caption for the figure" 8 | --- 9 | 10 | ## Setting 11 | 12 | A thousand worlds have opened, and the greatest land rush in human history has begun. As wave after wave of colonists leave, the power structures of the old solar system begin to buckle. 13 | 14 | Ships are disappearing without a trace. Private armies are being secretly formed. The sole remaining protomolecule sample is stolen. Terrorist attacks previously considered impossible bring the inner planets to their knees. The sins of the past are returning to exact a terrible price. 15 | 16 | And as a new human order is struggling to be born in blood and fire, James Holden and the crew of the Rocinante must struggle to survive and get back to the only home they have left.[^1] 17 | 18 | ![The depths of space showing an immense variety of colour across millions of stars.](./src/media/andy-holmes-rCbdp8VCYhQ-unsplash.jpg "Andy Holmes") 19 | 20 | [^1]: Source: https://www.goodreads.com/book/show/22886612-nemesis-games -------------------------------------------------------------------------------- /src/content/posts/2016-12-06-babylons-ashes.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Babylon's Ashes" 3 | curated: true 4 | tags: 5 | - "book" 6 | - "tv series" 7 | figureTest: 8 | caption: "This is a caption for the figure" 9 | --- 10 | 11 | ## Setting 12 | 13 | A revolution brewing for generations has begun in fire. It will end in blood. 14 | 15 | The Free Navy - a violent group of Belters in black-market military ships - has crippled the Earth and begun a campaign of piracy and violence among the outer planets. The colony ships heading for the thousand new worlds on the far side of the alien ring gates are easy prey, and no single navy remains strong enough to protect them. 16 | 17 | James Holden and his crew know the strengths and weaknesses of this new force better than anyone. Outnumbered and outgunned, the embattled remnants of the old political powers call on the Rocinante for a desperate mission to reach Medina Station at the heart of the gate network. 18 | 19 | But the new alliances are as flawed as the old, and the struggle for power has only just begun. As the chaos grows, an alien mystery deepens. Pirate fleets, mutiny and betrayal may be the least of the Rocinante's problems. And in the uncanny spaces past the ring gates, the choices of a few damaged and desperate people may determine the fate of more than just humanity.[^1] 20 | 21 | ![The depths of space showing an immense variety of colour across millions of stars.](./src/media/jeremy-thomas-E0AHdsENmDg-unsplash.jpg "Space by Jeremy Thomas") 22 | 23 | [^1]: Source: https://www.goodreads.com/book/show/25877663-babylon-s-ashes -------------------------------------------------------------------------------- /src/content/posts/2017-12-05-persepolis-rising.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Persepolis Rising" 3 | tags: 4 | - "book" 5 | figureTest: 6 | caption: "This is a caption for the figure" 7 | --- 8 | 9 | ## Setting 10 | 11 | In the thousand-sun network of humanity's expansion, new colony worlds are struggling to find their way. Every new planet lives on a knife edge between collapse and wonder, and the crew of the aging gunship Rocinante have their hands more than full keeping the fragile peace. 12 | 13 | In the vast space between Earth and Jupiter, the inner planets and belt have formed a tentative and uncertain alliance still haunted by a history of wars and prejudices. On the lost colony world of Laconia, a hidden enemy has a new vision for all of humanity and the power to enforce it. 14 | 15 | New technologies clash with old as the history of human conflict returns to its ancient patterns of war and subjugation. But human nature is not the only enemy, and the forces being unleashed have their own price. A price that will change the shape of humanity -- and of the Rocinante -- unexpectedly and forever ...[^1] 16 | 17 | ![The depths of space showing an immense variety of colour across millions of stars.](./src/media/john-fowler-7Ym9rpYtSdA-unsplash.jpg "John Fowler") 18 | 19 | [^1]: Source: https://www.goodreads.com/book/show/28335696-persepolis-rising -------------------------------------------------------------------------------- /src/content/posts/2019-03-26-tiamats-wrath.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Tiamat's Wrath" 3 | tags: 4 | - "book" 5 | figureTest: 6 | caption: "This is a caption for the figure" 7 | --- 8 | 9 | ## Setting 10 | 11 | Thirteen hundred gates have opened to solar systems around the galaxy. But as humanity builds its interstellar empire in the alien ruins, the mysteries and threats grow deeper. 12 | 13 | In the dead systems where gates lead to stranger things than alien planets, Elvi Okoye begins a desperate search to discover the nature of a genocide that happened before the first human beings existed, and to find weapons to fight a war against forces at the edge of the imaginable. But the price of that knowledge may be higher than she can pay. 14 | 15 | At the heart of the empire, Teresa Duarte prepares to take on the burden of her father's godlike ambition. The sociopathic scientist Paolo Cortázar and the Mephistophelian prisoner James Holden are only two of the dangers in a palace thick with intrigue, but Teresa has a mind of her own and secrets even her father the emperor doesn't guess. 16 | 17 | And throughout the wide human empire, the scattered crew of the Rocinante fights a brave rear-guard action against Duarte's authoritarian regime. Memory of the old order falls away, and a future under Laconia's eternal rule -- and with it, a battle that humanity can only lose - seems more and more certain. Because against the terrors that lie between worlds, courage and ambition will not be enough ...[^1] 18 | 19 | ![The depths of space showing an immense variety of colour across millions of stars.](./src/media/andy-holmes-rCbdp8VCYhQ-unsplash.jpg "Andy Holmes") 20 | 21 | [^1]: Source: https://www.goodreads.com/book/show/28335698-tiamat-s-wrath -------------------------------------------------------------------------------- /src/content/posts/2021-11-30-leviathan-falls.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Leviathan Falls" 3 | tags: 4 | - "book" 5 | figureTest: 6 | caption: "This is a caption for the figure" 7 | --- 8 | 9 | ## Setting 10 | 11 | The Laconian Empire has fallen, setting the thirteen hundred solar systems free from the rule of Winston Duarte. But the ancient enemy that killed the gate builders is awake, and the war against our universe has begun again. 12 | 13 | In the dead system of Adro, Elvi Okoye leads a desperate scientific mission to understand what the gate builders were and what destroyed them, even if it means compromising herself and the half-alien children who bear the weight of her investigation. Through the wide-flung systems of humanity, Colonel Aliana Tanaka hunts for Duarte’s missing daughter ... and the shattered emperor himself. And on the Rocinante, James Holden and his crew struggle to build a future for humanity out of the shards and ruins of all that has come before. 14 | 15 | As nearly unimaginable forces prepare to annihilate all human life, Holden and a group of unlikely allies discover a last, desperate chance to unite all of humanity, with the promise of a vast galactic civilization free from wars, factions, lies, and secrets if they win.[^1] 16 | 17 | ![The depths of space showing an immense variety of colour across millions of stars.](./src/media/jeremy-thomas-E0AHdsENmDg-unsplash.jpg "Space by Jeremy Thomas") 18 | 19 | [^1]: Source: https://www.goodreads.com/book/show/28335699-leviathan-falls -------------------------------------------------------------------------------- /src/content/posts/posts.json: -------------------------------------------------------------------------------- 1 | { 2 | "layout": "layouts/post", 3 | "permalink": "/posts/{{ page.fileSlug }}/index.html", 4 | "eleventyNavigation": { 5 | "parent": "posts" 6 | }, 7 | "og": { 8 | "type": "article" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/content/tags.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: "layouts/tag-results" 3 | title: "Tags" 4 | pagination: 5 | data: "collections" 6 | size: 1 7 | alias: "tag" 8 | filter: 9 | - "all" 10 | - "posts" 11 | - "curated" 12 | permalink: "/tag/{{ tag | slug }}/" 13 | --- 14 | -------------------------------------------------------------------------------- /src/content/using-this-template.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: "layouts/page" 3 | eleventyNavigation: 4 | key: usage 5 | title: Using Get Going 6 | order: 1 7 | title: "Using Get Going" 8 | permalink: "/using-this-template/index.html" 9 | --- 10 | 11 | There's a little bit of housekeeping to do in order to make this template your own. 12 | 13 | ### Update global configs for this template 14 | This project uses a single file to capture project-wide metadata, basically to populate all the stuff in a `` tag on your pages. This can be found under `src/data/config.js`. These of course can be overridden in your content frontmatter thanks to Eleventys [data cascade](https://www.11ty.dev/docs/data-cascade/). 15 | 16 | ```js 17 | // Required. The name of your project. 18 | projectName: "11ty Get Going", 19 | 20 | // Required. A brief description of your project. 21 | description: "Just another 11ty starter kit", 22 | 23 | // Required. A short name used exclusively in webmanifest.njk. Keep it under 12 characters to minimize the possibility of truncation. Can be safely deleted if you delete webmanifest.njk. 24 | shortName: "11ty GG", 25 | 26 | // Required. Update development and production urls to your project requirements. 27 | domain: process.env.ELEVENTY_RUN_MODE == "serve" ? "http://localhost:8080" : "https://example.com", 28 | 29 | // Required. SEO indexing behaviour. 30 | robots: "index, follow", 31 | 32 | // Required. Used exclusively in webmanifest.njk. This sometimes affects how an OS displays your site. Can be safely deleted if you delete webmanifest.njk. 33 | themeColor: "#FFFFFF", 34 | 35 | // Required. Used exclusively in webmanifest.njk. Recommend using the same value as body background color in your CSS. Can be safely deleted if you delete webmanifest.njk. 36 | backgroundColor: "#FFFFFF", 37 | 38 | // Optional. Delete block if not used. Author values for project. 39 | author: { 40 | name: "Author Name", 41 | email: "author@email.com", 42 | }, 43 | 44 | // Optional. Delete block if you don't require link tags related to your idenity. Duplicate as many objects as you need! 45 | identity: [ 46 | { 47 | rel: "me", 48 | url: "URL-GOES-HERE", 49 | }, 50 | ], 51 | 52 | // Optional. Delete block if you don't require Opengraph. 53 | og: { 54 | locale: "en_GB", 55 | type: "website", 56 | image: { 57 | rel: "/og-default.jpg", 58 | alt: "Default OG image displayed here", 59 | }, 60 | } 61 | ``` 62 | 63 | ### Favicons and Opengraph 64 | 65 | #### Favicons 66 | Favicons are stored under `src/static/favicons` and are automatically passed through to their relevant directories on build. All you need to do is create the images for your project. 67 | 68 | #### Opengraph 69 | A default Opengraph image can be found under `src/static` and is named `og-default.jpg`. Much like the favicons all you need to do is create a relevant default image to be used. 70 | 71 | If you decide to delete this file (for example if you don't require Opengraph in your project), then you must update `eleventy.config.js` and remove this line: 72 | 73 | ```js 74 | eleventyConfig.addPassthroughCopy({ "src/static/og-default.jpg": "/og-default.jpg" }); 75 | ``` 76 | 77 | ### RSS logic 78 | By default this template collects all posts under `src/content/posts` to populate the RSS feed. You would most likely want something different for your project. If you visit `etc/collections/index.js` and edit the following to fit your needs: 79 | 80 | ```js 81 | export const feed = i => i.getFilteredByGlob("./src/content/posts/*.md").reverse(); 82 | ``` 83 | 84 | ### Responsive images 85 | Images are stored in their original format under `src/media`, although you can organise images in any way in this project. 86 | 87 | This project adheres to Markdown syntax as much as possible and uses [Markdown-it-eleventy-img](https://www.npmjs.com/package/markdown-it-eleventy-img) in order to leverage the magic of [Eleventy Image](https://www.11ty.dev/docs/plugins/image/) to generate responsive images based on your needs (so you can do something like this `![The depths of space showing an immense variety of colour across millions of stars.](./src/media/jeremy-thomas-E0AHdsENmDg-unsplash.jpg "Space by Jeremy Thomas")` and get all the responsive benefits without much effort). 88 | 89 | For images imported using Markdown syntax, this project wraps images in a `
    ` by default and a `
    ` is rendered if a `title` attribute is applied to your image (e.g. `![Alt text](..link/to/image.jpg "Title text")`). 90 | 91 | Finally, if a gif is imported it is assumed this is animated, so relevant logic is set to make that possible. 92 | 93 | You will most likely want to adapt widths, sizes and formats to suit your projects needs. You will want to edit the Markdown-it library located in `lib/markdown.js` and find these object keys: 94 | 95 | ```js 96 | const eleventyImageOptions = { 97 | imgOptions: { 98 | widths: [300, 600, 1200, 1800, 2150], 99 | urlPath: "/img/", 100 | outputDir: "./dist/img/", 101 | formats: ["avif", "jpeg"], 102 | }, 103 | globalAttributes: { 104 | decoding: "async", 105 | loading: "lazy", 106 | sizes: "(max-width: 72rem) 100vw, 75vw", 107 | }, 108 | ... 109 | .. 110 | . 111 | ``` 112 | 113 | --- 114 | 115 | **With that all said and done you should be ready to get on with your project. Good going!** -------------------------------------------------------------------------------- /src/feed.njk: -------------------------------------------------------------------------------- 1 | --- 2 | permalink: /feed.xml 3 | eleventyExcludeFromCollections: true 4 | icon: /icon-512.jpg 5 | --- 6 | 7 | 8 | 9 | 10 | {{ config.projectName }} 11 | {{ config.domain | absoluteUrl(config.domain) }} 12 | {{ collections.feed | getNewestCollectionItemDate | dateToRfc3339 }} 13 | 14 | 15 | 16 | {{ config.author.name }} 17 | {{ config.author.email }} 18 | 19 | {{ icon | absoluteUrl(config.domain) }} 20 | 21 | {% for item in collections.feed %} 22 | {% set absolutePostUrl = item.url | absoluteUrl(config.domain) %} 23 | 24 | {{ item.data.title }} 25 | {% if item.data.summary %}{{ item.data.summary }}{% endif %} 26 | {{ absolutePostUrl }} 27 | 28 | {{ item.date | dateToRfc3339 }} 29 | {% if item.data.updated %} {{item.data.updated[0] | dateToRfc3339}} {%- else -%} {{ item.date | dateToRfc3339 }} {% endif %} 30 | {% if item.data.tags %} 31 | {% for tag in item.data.tags %} 32 | {{ tag }} 33 | {% endfor %} 34 | {% endif %} 35 | {{ item.templateContent | htmlToAbsoluteUrls(absolutePostUrl) }} 36 | 37 | {% endfor %} 38 | 39 | -------------------------------------------------------------------------------- /src/media/aldebaran-s-qtRF_RxCAo0-unsplash.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:9f530c6e1faf5c023db000bd49073d4585ff231883cf73729b12334856a0db91 3 | size 3820558 4 | -------------------------------------------------------------------------------- /src/media/andy-holmes-rCbdp8VCYhQ-unsplash.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:b2e14b65a5eec51c0a1bd72838d3862ed7c81879a89ea46245a77de0ee4ac4f3 3 | size 7343627 4 | -------------------------------------------------------------------------------- /src/media/jeremy-thomas-E0AHdsENmDg-unsplash.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:437663c224a6518490420f7aa7270b5dfbb2f8086c34c405c0dbf526d9042f20 3 | size 4178775 4 | -------------------------------------------------------------------------------- /src/media/john-fowler-7Ym9rpYtSdA-unsplash.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:2ee9445b90b8b4e1f297f77fadfb765e1bd78956684c50fef6524e0c69ec4552 3 | size 7373945 4 | -------------------------------------------------------------------------------- /src/site.css: -------------------------------------------------------------------------------- 1 | /* Configuration */ 2 | @import url("./_styles/_config/_media.css"); 3 | @import url("./_styles/_config/_import.css"); 4 | 5 | /* Variables */ 6 | @import url("./_styles/_variables.css"); 7 | 8 | /* Utilities */ 9 | @import url("./_styles/_utilities.css"); 10 | 11 | /* Types and universal selectors */ 12 | @import url("./_styles/_types.css"); 13 | 14 | /* Layout */ 15 | @import url("./_styles/_layout/_layout-grid.css"); 16 | @import url("./_styles/_layout/_content.css"); 17 | @import url("./_styles/_layout/_wrapper.css"); 18 | 19 | /* Components */ 20 | @import url("./_styles/_components/_site-header.css"); 21 | @import url("./_styles/_components/_site-footer.css"); 22 | @import url("./_styles/_components/_site-pagination.css"); 23 | @import url("./_styles/_components/_card-list.css"); 24 | @import url("./_styles/_components/_footnotes.css"); 25 | 26 | /* Vendor */ 27 | @import url("./_styles/_vendor/_prism.css"); 28 | -------------------------------------------------------------------------------- /src/static/favicons/apple-touch-icon.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:2203af95e930492802d46f59e03c0374927ae780f38880b824d7444ea01332c2 3 | size 1553 4 | -------------------------------------------------------------------------------- /src/static/favicons/favicon.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:60fba73f0745f352bdcce743b9c37848a5a22b436e2ae95cf2da201cec32f67e 3 | size 655 4 | -------------------------------------------------------------------------------- /src/static/favicons/icon-192.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:eee4447478c21bd9d415a22d5c31773767bff98417f52e9b902fa993151e5d59 3 | size 1635 4 | -------------------------------------------------------------------------------- /src/static/favicons/icon-512.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:dfdc154d1997b54b6fc6c5f63922401c8bb3140695a74c953c19357a465314a7 3 | size 7795 4 | -------------------------------------------------------------------------------- /src/static/favicons/icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/static/fonts/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevh-c/11ty-get-going/7f353329c11e6f6c0fc60ecf84a07df87ba2370b/src/static/fonts/.gitkeep -------------------------------------------------------------------------------- /src/static/og-default.jpg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:b961dec5aff548a498ceff04acd5c8d873e3dab5d8056d7b7f91a30486221ed6 3 | size 21365 4 | -------------------------------------------------------------------------------- /src/webmanifest.njk: -------------------------------------------------------------------------------- 1 | --- 2 | eleventyExcludeFromCollections: true 3 | permalink: /manifest.webmanifest 4 | --- 5 | { 6 | "name": "{{config.title}}", 7 | "short_name": "{{config.shortName}}", 8 | "theme_color": "{{config.themeColor}}", 9 | "background_color": "{{config.backgroundColor}}", 10 | "start_url": "/", 11 | "display": "minimal-UI", 12 | "icons": [ 13 | { 14 | "src": "/icon-192.jpg", 15 | "sizes": "192x192", 16 | "type": "image/png", 17 | "purpose": "any maskable" 18 | }, 19 | { 20 | "src": "/icon-512.jpg", 21 | "sizes": "512x512", 22 | "type": "image/png", 23 | "purpose": "any maskable" 24 | } 25 | ] 26 | } 27 | --------------------------------------------------------------------------------