├── .editorconfig
├── .eleventy.js
├── .eleventyignore
├── .gitignore
├── .node-version
├── .nvmrc
├── .prettierignore
├── .prettierrc
├── .tool-versions
├── CHANGELOG.md
├── LICENSE
├── README.md
├── docs
└── development.md
├── eleventy
├── collections.js
├── env.js
├── filters
│ ├── collections.js
│ ├── dates.js
│ ├── misc.js
│ └── urls.js
├── shortcodes.js
└── utils.js
├── netlify.toml
├── package-lock.json
├── package.json
├── paths.js
├── postcss.config.js
└── src
├── assets
├── css
│ ├── components
│ │ ├── author-card.css
│ │ ├── container.css
│ │ ├── notice.css
│ │ ├── post-card.css
│ │ └── post.css
│ ├── modules
│ │ ├── atkinson-hyperlegible-font.css
│ │ ├── sticky-footer.css
│ │ ├── syntax.css
│ │ └── typography.css
│ ├── style.css
│ ├── system
│ │ ├── mq.css
│ │ ├── selectors.css
│ │ └── tokens.css
│ └── themes
│ │ └── prism-one-light.css
├── font
│ ├── Atkinson-Hyperlegible-Bold-102.woff
│ ├── Atkinson-Hyperlegible-Bold-102.woff2
│ ├── Atkinson-Hyperlegible-BoldItalic-102.woff
│ ├── Atkinson-Hyperlegible-BoldItalic-102.woff2
│ ├── Atkinson-Hyperlegible-Italic-102.woff
│ ├── Atkinson-Hyperlegible-Italic-102.woff2
│ ├── Atkinson-Hyperlegible-Regular-102.woff
│ └── Atkinson-Hyperlegible-Regular-102.woff2
├── img
│ ├── 8EC7AF25-A29D-4414-9732-DAEB476C9B64.jpg
│ ├── 9DA6F832-DDEE-4C5B-A880-28046613BAE4.jpg
│ ├── jane-doe-this-person-does-not-exist.jpeg
│ ├── leaves.jpeg
│ ├── vivaldi.jpg
│ ├── vivaldi_fosstodon.png
│ └── vivaldi_plausible.png
└── js
│ └── index.js
├── content
├── content.11tydata.js
├── feeds
│ └── primary.liquid
├── pages
│ └── about.md
├── post
│ ├── note
│ │ ├── 94075ed4bf58.md
│ │ ├── b5cb4b5c1b88.md
│ │ └── dedf7ab03e83.md
│ ├── photo
│ │ ├── 4be63568ba03.md
│ │ └── ecd97ddb244e.md
│ └── reply
│ │ ├── 597a082f97d2.md
│ │ └── be7fa084d4e5.md
└── special-pages
│ ├── index.liquid
│ ├── posts.liquid
│ ├── robots.txt.liquid
│ ├── sitemap.liquid
│ └── tag.liquid
├── data
├── config.js
├── navigation.js
└── site.json
├── includes
├── author-card.liquid
├── comment-via-email.liquid
├── footer.liquid
├── head.liquid
├── header.liquid
├── old-post-notice.liquid
├── page-title.liquid
├── post-card-article.liquid
├── post-card-note.liquid
├── post-card-photo.liquid
├── post-card-reply-context.liquid
├── post-card-reply.liquid
└── post-card.liquid
└── layouts
├── default.liquid
├── page.liquid
└── post
├── article.liquid
├── note.liquid
├── photo.liquid
├── reply-context.liquid
└── reply.liquid
/.editorconfig:
--------------------------------------------------------------------------------
1 | # Unix-style newlines with a newline ending every file
2 | [*]
3 | end_of_line = lf
4 | insert_final_newline = true
5 | # Set default charset
6 | charset = utf-8
7 |
8 | # 4 space indentation
9 | [*.{html,js}]
10 | indent_style = tab
11 | indent_size = 4
12 |
13 | [*.{yml,yaml,css}]
14 | indent_style = space
15 | indent_size = 2
16 |
17 | # Matches the exact files either package.json or .travis.yml
18 | [{package.json,.travis.yml}]
19 | indent_style = tab
20 | indent_size = 2
21 |
22 | [*.md]
23 | indent_style = space
24 | indent_size = 2
25 |
--------------------------------------------------------------------------------
/.eleventy.js:
--------------------------------------------------------------------------------
1 | module.exports = function(config) {
2 | // *** Collection imports
3 | const collections = require("./eleventy/collections");
4 |
5 | // *** Filter imports
6 | const collectionFilters = require("./eleventy/filters/collections");
7 | const urlFilters = require("./eleventy/filters/urls");
8 | const dateFilters = require("./eleventy/filters/dates");
9 |
10 | // *** Shortcode imports
11 | const shortcodes = require("./eleventy/shortcodes");
12 |
13 | // *** Misc imports
14 | const env = require("./eleventy/env");
15 |
16 | // *** Plugins
17 | const rssPlugin = require("@11ty/eleventy-plugin-rss");
18 | config.addPlugin(rssPlugin);
19 | // Syntax highlighting
20 | config.addPlugin(require("@11ty/eleventy-plugin-syntaxhighlight"));
21 | // Typeset
22 | if (env.is11tyProduction || env.is11tyStaging)
23 | config.addPlugin(require("eleventy-plugin-typeset")());
24 | // Safe external links
25 | config.addPlugin(require("@hirusi/eleventy-plugin-safe-external-links"), {
26 | pattern: "https{0,1}://", // RegExp pattern for external links
27 | noopener: true, // Whether to include noopener
28 | noreferrer: true, // Whether to include noreferrer
29 | files: [
30 | // What output file extensions to work on
31 | ".html"
32 | ]
33 | });
34 | // Minified HTML.
35 | if (env.is11tyProduction || env.is11tyStaging) {
36 | config.addPlugin(require("@sardine/eleventy-plugin-tinyhtml"));
37 | }
38 | const Image = require("@11ty/eleventy-img");
39 |
40 | async function imageShortcode(src, alt, extraAttrs, sizes = "100vw") {
41 | if (alt === undefined) {
42 | // You bet we throw an error on missing alt (alt="" works okay)
43 | throw new Error(`Missing \`alt\` on responsiveimage from: ${src}`);
44 | }
45 |
46 | let metadata = await Image(src, {
47 | widths: [600, null],
48 | formats: ["avif", "webp", "jpeg"],
49 | urlPath: "/assets/img/",
50 | outputDir: "./dist/assets/img/"
51 | });
52 |
53 | let highsrc = metadata.jpeg[metadata.jpeg.length - 1];
54 |
55 | return `
56 | ${Object.values(metadata)
57 | .map(imageFormat => {
58 | return ` `;
63 | })
64 | .join("\n")}
65 |
74 | `;
75 | }
76 |
77 | // *** Shortcodes
78 | // Jekyll replacement for post_url tag as an 11ty shortcode
79 | config.addShortcode("getUrl", shortcodes.postUrl);
80 | config.addShortcode("getOwnerInfo", shortcodes.getOwnerInfo);
81 | config.addShortcode("getPostType", shortcodes.getPostType);
82 | config.addShortcode("isOldPost", shortcodes.isOldPost);
83 | config.addLiquidShortcode("image", imageShortcode);
84 |
85 | // *** Filters
86 | // Dates
87 | config.addFilter("friendlyDate", dateFilters.friendlyDate);
88 | config.addFilter("dateToIso8601", dateFilters.dateToIso8601);
89 | // Filter posts per tag
90 | config.addFilter("byTag", collectionFilters.byTag);
91 | // Absolute url
92 | config.addFilter("absoluteUrl", urlFilters.absoluteUrl);
93 |
94 | // The official RSS plugin exports only Nunjucks filters. They can be used with Liquid like so.
95 | config.addFilter("htmlToAbsoluteUrls", rssPlugin.convertHtmlToAbsoluteUrls);
96 | config.addFilter("dateToRfc3339", rssPlugin.dateToRfc3339);
97 | config.addFilter(
98 | "getNewestCollectionItemDate",
99 | rssPlugin.getNewestCollectionItemDate
100 | );
101 |
102 | // *** Collections
103 | // Articles
104 | config.addCollection("primary", collections.primary);
105 |
106 | // *** Misc
107 | // Copy fonts as-is.
108 | config.addPassthroughCopy({ "src/assets/font": "assets/font" });
109 |
110 | return {
111 | pathPrefix: "/", // useful for GitHub pages
112 | dir: {
113 | input: "./",
114 | output: "dist",
115 | includes: "src/includes",
116 | layouts: "src/layouts",
117 | data: "src/data"
118 | }
119 | };
120 | };
121 |
--------------------------------------------------------------------------------
/.eleventyignore:
--------------------------------------------------------------------------------
1 | gulpfile.babel.js
2 | gulp_tasks
3 | src/assets
4 | tailwind.config.js
5 | paths.js
6 | npm-debug.log
7 | package.json
8 | package-lock.json
9 | README.md
10 | LICENSE
11 | .editorconfig
12 | .babelrc
13 | .prettierrc
14 | CHANGELOG.md
15 | docs
16 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .vscode
2 | node_modules
3 | dist
4 | .DS_store
5 |
--------------------------------------------------------------------------------
/.node-version:
--------------------------------------------------------------------------------
1 | 16
2 |
--------------------------------------------------------------------------------
/.nvmrc:
--------------------------------------------------------------------------------
1 | 16
2 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | *.md
2 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": false,
3 | "useTabs": true,
4 | "tabWidth": 4,
5 | "overrides": [
6 | {
7 | "files": "*.{yaml,yml}",
8 | "options": {
9 | "useTabs": false,
10 | "tabWidth": 2
11 | }
12 | },
13 | {
14 | "files": "*.css",
15 | "options": {
16 | "useTabs": false,
17 | "tabWidth": 2
18 | }
19 | }
20 | ]
21 | }
22 |
--------------------------------------------------------------------------------
/.tool-versions:
--------------------------------------------------------------------------------
1 | nodejs lts
2 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
2 |
3 | ## v0.0.9 - Unreleased
4 |
5 | [All changes](https://github.com/hirusi/smix-eleventy-starter/compare/v0.0.8...main)
6 |
7 | ### Added
8 |
9 | - To-do.
10 |
11 | ### Changed
12 |
13 | - Instructions for local development have moved from `README.md` to `docs/development.md`.
14 | - Instructions for publishing on Forestry/Netlify have moved from `README.md` to `docs/development.md`.
15 | - Specify installation of Node.js via `asdf` as an alternate option to `nvm` in the development docs.
16 | - Remove emojis from `README.md` and use bold highlighting instead.
17 | - Remove webmentions from `To-Do` as I no longer wish to implement those.
18 | - Add note about setting `ELEVENTY_ENV` on staging and production environments.
19 | - Dependency updates (security-related PRs opened by @dependabot)
20 | - `lodash` from 4.17.20 to 4.17.21
21 | - `hosted-git-info` from 2.8.8 to 2.8.9
22 | - `cssnano` upgraded from `^4` to `^5`.
23 | - Upgrade to Node LTS v16 and npm v8.
24 |
25 | ### Removed
26 |
27 | - To-do.
28 |
29 | ## v0.0.8 - 2021-04-12
30 |
31 | [All changes](https://github.com/hirusi/smix-eleventy-starter/compare/v0.0.7...v0.0.8).
32 |
33 | ### Added
34 |
35 | * Compatibility with asdf-nodejs. #24
36 | * MIT license.
37 | * Netlify configuration to keep draft posts out from the production site, but include in staging site. #25 closed by #26
38 | * One-click Forestry import. #31
39 |
40 | ### Changed
41 |
42 | * Dependencies updated per SemVer.
43 | * Includes development dependencies.
44 | * Upgrade to Eleventy v0.12.1. #32.
45 | ## v0.0.7 - 21 October 2020
46 |
47 | ### Added
48 |
49 | * A central `CHANGELOG.md` file.
50 |
51 | ### Changed
52 |
53 | * SEO improvements for demo site
54 | * Fix the URL to forestry.io in README (@drnic)
55 | * Dependencies updated/affected per npm log:
56 | * **@11ty/eleventy-plugin-rss@1.0.9**
57 | * **@hirusi/eleventy-plugin-safe-external-links@0.14.3**
58 | * @11ty/eleventy@0.11.0
59 | * **autoprefixer@9.8.6**
60 | * browserify@16.5.2
61 | * @fullhuman/postcss-purgecss@1.3.0
62 | * babelify@10.0.0
63 | * @babel/runtime@7.12.1
64 | * @babel/plugin-transform-runtime@7.12.1
65 | * @babel/register@7.12.1
66 | * @babel/core@7.12.3
67 | * @babel/preset-env@7.12.1
68 | * child_process@1.0.2
69 | * cssnano@4.1.10
70 | * **date-fns@2.16.1**
71 | * gulp-imagemin@6.2.0
72 | * fancy-log@1.3.3
73 | * gulp-babel@8.0.0
74 | * gulp-concat@2.6.1
75 | * gulp@4.0.2
76 | * gulp-if@3.0.0
77 | * gulp-htmlmin@5.0.1
78 | * **date-fns-tz@1.0.12**
79 | * **liquidjs@9.16.1**
80 | * gulp-postcss@8.0.0
81 | * gulp-uglify@3.0.2
82 | * **postcss-import@12.0.1**
83 | * watchify@3.11.1
84 | * **lodash.merge@4.6.2**
85 | * vinyl-buffer@1.0.1
86 | * vinyl-source-stream@2.0.0
87 | * **postcss-nesting@7.0.1**
88 | * npm-run-all@4.1.5
89 | * **tailwindcss@1.9.5**
90 | * **eleventy-plugin-typeset@1.0.1**
91 |
92 | ## v0.0.6 - 10 August 2020
93 |
94 | ### Added
95 |
96 | * microformats2
97 | * h-card for author info
98 | * h-feed for articles
99 | * h-entry for article
100 | * typeset on staging and production environments for more professional looking content
101 |
102 | ### Changed
103 |
104 | * Custom liquid engine as Eleventy uses a very old version (v6 to v9, if I'm not wrong)
105 | * Update all dependencies per semver
106 | * Better site socials and site authors structure in site data file
107 | * Use JAMstack style content procesing for safe external links instead of client-side JS
108 | * Default design/layout
109 | * Work started on removing usage of deprecated include liquid tag
110 | * Cleanup of extra spacing in head
111 |
112 | ### Fixed
113 | * Use correct siteBaseUrl in meta tags
114 | * Ran npm audit fix to fix automatically fix-able dependency issues
115 | * Fix pagination for articles based on new liquid syntax
116 | * The develop script watches assets now
117 | * Node env correctly defaults to development if no environment specified
118 | * Draft content is automatically excluded from collections on production
119 |
120 | ### Removed
121 |
122 | * Client-side JS for safe external links -- externalLinks class names are no longer added toe external links (likewise for internal links)
123 |
124 | ## v0.0.5 - 08 August 2020
125 |
126 | ### Added
127 |
128 | - Add a sitemap.xml
129 | - Add a robots.txt
130 | - Add an Atom feed for articles
131 | - Add social meta tags (Twitter and Facebook Open Graph)
132 |
133 | ### Changed
134 |
135 | - Fix bug with permalink generation on production environment
136 | - Remove guests info from authors data file
137 | - Add author picture key in authors data file
138 | - Bump lodash from 4.17.15 to 4.17.19
139 | - Bump elliptic from 6.5.2 to 6.5.3
140 |
141 | ## v0.0.4 - 16 May 2020
142 |
143 | ### Added
144 |
145 | - Exclude from build: draft articles/pages on production
146 | - Ignore Markdown files from husky (ocassionally causing issue with YAML front-matter formatting)
147 | - New `clean` npm script to run before each development build
148 | - `.forestry` directory with a default configuration in place for posts and pages, as well as `site.json`, for faster CMS setup
149 | - Add a `page-title` include for displaying page titles on page templates and special pages like index, blog, tag
150 |
151 | ### Changed
152 |
153 | - Update to Eleventy v0.11.0
154 | - Refactor Eleventy configuration
155 | - Collections are now defined in a separate file
156 | - Filters have been modularized into separate files, each for `collections`, `dates`, `urls`, and `misc`
157 | - Single `env` file for all Eleventy files
158 | - Passthrough copy `admin` directory only on production
159 | - Move all content, layouts, includes, data to `src` directory
160 | - Renamed `config.js` to `paths.js` to better reflect its intention
161 | - Switch to `lodash.merge` for merging browserify configuration instead of `Object.assign`
162 | - Rename layout to `article` from `post`
163 | - Rename layout for sample articles to `article` (earlier `post`)
164 | - Update `blog/` permalinks to `articles/`
165 |
166 | ### Removed
167 | - Ability to specify files to clean before each build in `paths.js`
168 | - Type definitions for `browser-sync` and `axios`
169 | - `axios` removed as no calls being made in the starter kit. `node-fetch` recommended.
170 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 hirusi
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 🌻 Smix
2 |
3 | A standards-respecting starter kit for Eleventy. Go Indie.
4 |
5 | ⚠️ This project is now considered more-or-less complete for the author's needs. Any further enhancements will require a pull request to come from the community.
6 |
7 | ## Reading.
8 |
9 | For nice text, there's [Typeset](https://www.npmjs.com/package/typeset). While it adds to the build time, it makes for a more polished reading experience.
10 |
11 | It seems [people do rely on RSS feeds](https://twitter.com/mxbck/status/1490698469312536578) even in 2022! Cheers to that; there's an Atom feed that is standards-compliant. It understands the published and updated datetime stamps on posts, and uses the RFC822 date format.
12 |
13 | Dark mode is included out of the box using a custom media query. (More in future-ready section below).
14 |
15 | Date filters such as for friendly dates (10 March 2020) and machine-parseable dates (ISO8601) are available to use via filters.
16 |
17 | ## Discoverability/SEO.
18 |
19 | Meta tags for social networks (Open Graph as well as Twitter). This allows for a nice card display when you (or someone else) shares a link to your post or site. Support for `content-description` meta tag -- this helps decide what text to show for a page/post when shared on social media, as well as in search engines.
20 |
21 | Sitemap with `changeFrequency` -- so bots only come back when they need to. (please also see [issue #7](https://github.com/hirusi/smix-eleventy-starter/issues/7)). `robots.txt` is a cherry on the top -- I would also recommend using it to [hide your personal picture](https://rusingh.com/block-images-appearing-in-search/) if so desired.
22 |
23 |
24 | ## Writing
25 |
26 | Write in Markdown, much loved among developers. If you don't already know it, it's [easy to get started](https://commonmark.org/help/tutorial/). You can also use separate apps and then copy-paste your content into a new file. This allows for focusing on content first, before messing with any technicals. I recommend [Bear](https://bear.app/).
27 |
28 | ### Linking to pages or posts.
29 |
30 | `postUrl` shortcode similar to Jekyll's `post_url` and `link` liquid tags:
31 |
32 | ```liquid
33 | {% postUrl collections.primary 'on-burnout' %}
34 | ```
35 |
36 | ### Code blocks.
37 |
38 | Code blocks are made possible via [an Eleventy plugin](https://www.11ty.dev/docs/plugins/syntaxhighlight/). Many [Prism](https://prismjs.com/) themes are [available to use](https://github.com/PrismJS/prism-themes/tree/master/themes).
39 |
40 | ## IndieWeb
41 |
42 | For those pushing [#IndieWeb](https://www.smashingmagazine.com/2020/08/autonomy-online-indieweb/), some basic [Microformats2](https://indieweb.org/microformats2) support is included. From h-card to understand authorship, h-entry to understand a post, and h-feed to have Microformat feeds. This allows following a website in [Microsub readers](https://indieweb.org/Microsub).
43 |
44 | The following [post-types](https://indieweb.org/posts#Types_of_Posts) are supported:
45 |
46 | - 📄 Article
47 | - 📔 Note
48 | - ↪ Reply
49 | - 📷 Photo
50 |
51 | A single microformats2 feeds is offered via `h-feed`. This includes articles, notes, replies (with or without context), and image(s). These post types also seamlessly work in the Atom feed.
52 |
53 | ## Future-ready.
54 |
55 | The CSS is written with upcoming CSS standards in mind. This is made possible thanks to PostCSS. Inclusions: imports, nesting, purge, minification, autoprefixer, custom properties, custom media queries (this makes a dark mode easy to build!), custom selectors, and [LCH color coding](https://lea.verou.me/2020/04/lch-colors-in-css-what-why-and-how/).
56 |
57 | JavaScript is transpiled and bundled via `esbuild`.
58 |
59 | ## Accessible.
60 |
61 | [Atkinson font by The Braille Institute](https://brailleinstitute.org/freefont) is included if you wish to use it. If not, there's a sans, serif, and mono fallback to system fonts.
62 |
63 | Care is taken to have good contrast all around.
64 |
65 | Should you choose to include some animations, do make use of a custom media query for those who prefer less motion:
66 |
67 | ```css
68 | /* Prefers reduced motion. */
69 | @media screen and (--rm) {
70 | .fancy {
71 | /* Disable animations. */
72 | }
73 | }
74 | ```
75 |
76 | ## Under The Hood.
77 |
78 | ### Handling JavaScript.
79 |
80 | ES Modules are [now well supported](https://caniuse.com/es6-module) and you should move to them. In that spirit, we use [`esbuild`](https://esbuild.github.io/).
81 |
82 | If you want to bundle a single file and that is the default `index.js` source, running `npm run dev:js` is enough.
83 |
84 | To allow for page-specific JavaScript files, we have a convenience command to put together a new JS bundle.
85 |
86 | ```sh
87 | npm run dev:jsb --in=portfolio.js --out=portfolio.js
88 | ```
89 |
90 | This will create a JS bunlde (hence `jsb`), entering at `src/assets/js/portfolio.js` and outputting at `dist/assets/js/portfolio.js`
91 |
92 | Include them in the required page by using the `pageJavaScript` [`block`](https://liquidjs.com/tutorials/partials-and-layouts.html#Layout-Templates-Extends):
93 |
94 | ```liquid
95 | {% block pageJavascript %}
96 |
54 |
55 |
56 |
57 | {% block pageJavascript %}{% endblock %}
58 |
59 |
--------------------------------------------------------------------------------
/src/includes/header.liquid:
--------------------------------------------------------------------------------
1 | {% capture isHomePage %}{% if url == "/" %}true{% else %}false{% endif %}{% endcapture %}
2 |
3 | {% unless isHomePage == "true" %}
4 |