22 |
23 |
33 | 36 | {% endif %} 37 | {% if tags %} 38 | 52 | {% endif %} 53 |
├── .eleventy.js
├── .gitignore
├── .prettierrc
├── README.md
├── contributing.md
├── netlify.toml
├── package-lock.json
├── package.json
├── rollup.config.js
└── src
├── _data
├── global.js
├── helpers.js
├── navigation.json
├── site.json
├── styleguide.js
└── tokens.json
├── _includes
├── icons
│ └── arrow.svg
├── layouts
│ ├── archive.njk
│ ├── base.njk
│ ├── feed-item.njk
│ ├── home.njk
│ ├── page.njk
│ └── post.njk
└── partials
│ ├── components
│ ├── intro.njk
│ ├── nav.njk
│ ├── pagination.njk
│ └── post-list.njk
│ └── global
│ ├── availability.njk
│ ├── meta-info.njk
│ ├── service-worker.js
│ ├── site-foot.njk
│ ├── site-head.njk
│ └── third-party-comments.njk
├── _redirects
├── archive.md
├── assets
└── captions
│ └── client-screencast-example.vtt
├── feed
├── all.njk
└── writing.njk
├── filters
├── date-filter.js
├── likes-filter.js
├── markdown-filter.js
└── w3-date-filter.js
├── images
├── demo-image-1.jpg
├── demo-image-2.jpg
├── noise.webp
└── social-share.jpg
├── index.md
├── js
└── components
│ └── theme-toggle.js
├── pages
├── 404.md
├── freelance-pals-code-of-conduct.md
├── now.md
├── pages.json
├── projects.md
└── uses.md
├── posts
├── 2018-a-year-in-review.md
├── 2019-a-year-in-review.md
├── a-dive-into-freelance-life.md
├── a-double-launch-day.md
├── a-minimal-react-base-project.md
├── a-modern-css-reset.md
├── a-progressive-disclosure-component.md
├── a-short-note-on-my-social-activity.md
├── adding-webmentions-to-my-personal-site.md
├── break-out-of-the-echo-chamber.md
├── browser-diversity.md
├── burnout-a-long-recovery.md
├── burnout.md
├── bypass-service-worker-on-localhost.md
├── community.md
├── competing-by-mimicking.md
├── context-and-caveats.md
├── contraction-logger.md
├── create-a-responsive-grid-layout-with-no-media-queries-using-css-grid.md
├── create-a-semantic-break-out-button-to-make-an-entire-element-clickable.md
├── create-a-split-faux-container-layout-with-css-grid-and-flexbox.md
├── create-a-user-controlled-dark-or-light-mode.md
├── creating-a-full-bleed-css-utility.md
├── creating-an-aspect-ratio-css-utility.md
├── css-doesnt-suck.md
├── css-naked-day-2020.md
├── css-specifity-and-the-cascade.md
├── custom-property-controlled-fluid-type-sizing.md
├── eating-my-own-dog-food.md
├── every-layout-how-it-works.md
├── feed-page.md
├── flow-and-rhythm-in-css-with-stalfos.md
├── fluid-scale-and-tokens-a-match-made-in-heaven.md
├── freelance-pro-tip.md
├── front-end-challenges-club-is-moving-to-piccalilli.md
├── get-css-custom-property-value-with-javascript.md
├── hello-im-andy-and-im-addicted-to-twitter.md
├── honesty-is-the-best-policy.md
├── im-a-web-designer.md
├── im-warming-to-tailwind-css.md
├── introducing-developurrs.md
├── introducing-the-button-element.md
├── jamstack-ifttt-and-netlify-a-power-trio.md
├── keep-it-simple.md
├── keeping-it-simple-with-css-that-scales.md
├── keeping-it-simple-with-image-alt-text-for-accessibility.md
├── making-the-new-piccalilli-logo.md
├── my-first-month-as-a-freelancer.md
├── my-fractured-relationship-with-big-tech.md
├── new-baby-visiting-user-flow.md
├── no-more-anchor-buttons.md
├── open-letter-to-laurence-robertson-mp.md
├── piccalilli-is-changing.md
├── piccalilli-the-future.md
├── posts.json
├── progressive-overflow-management-with-a-scroll-track-utility.md
├── relative-sizing-with-em-units.md
├── screencasting-the-secret-sauce-for-less-time-wasted-in-meetings.md
├── shipping.md
├── so-long-hankchizljaw.md
├── the-extremely-loud-minority.md
├── the-if-theres-time-line.md
├── the-p-in-progressive-enhancement-stands-for-pragmatism.md
├── the-power-of-progressive-enhancement.md
├── the-power-of-self-publishing.md
├── this-blog-in-2020.md
├── tracking-my-time.md
├── two-simple-methods-to-vertically-and-horizontally-center-content-with-css.md
├── walking.md
├── week-notes-1.md
├── week-notes-10.md
├── week-notes-11.md
├── week-notes-12.md
├── week-notes-13.md
├── week-notes-14.md
├── week-notes-15.md
├── week-notes-2.md
├── week-notes-4.md
├── week-notes-5.md
├── week-notes-6.md
├── week-notes-7.md
├── week-notes-8.md
├── week-notes-9.md
├── weeknotes-3.md
├── well-being-on-twitter.md
└── what-i-searched-for-in-a-day-of-fighting-with-php.md
├── scss
├── _config.scss
├── _highlight.scss
├── _theme.scss
├── _typography.scss
├── components
│ ├── _availability.scss
│ ├── _avatar-group.scss
│ ├── _avatar.scss
│ ├── _button.scss
│ ├── _comments.scss
│ ├── _heading-permalink.scss
│ ├── _input-field.scss
│ ├── _intro.scss
│ ├── _nav.scss
│ ├── _noise-wrapper.scss
│ ├── _pagination.scss
│ ├── _post-list.scss
│ ├── _post.scss
│ ├── _scroll-track.scss
│ ├── _site-foot.scss
│ ├── _site-head.scss
│ ├── _skip-link.scss
│ ├── _syntax-highlighting.scss
│ └── _video-player.scss
├── global.scss
├── mixins
│ └── _dark-mode.scss
└── utilities
│ ├── _desaturate.scss
│ ├── _dot-bg.scss
│ ├── _highlight.scss
│ ├── _inner-wrapper.scss
│ ├── _str-replace.scss
│ ├── _visually-hidden.scss
│ └── _wrapper.scss
├── service-worker.njk
├── shortcodes
└── codepen.js
├── styleguide.njk
├── tags.njk
├── transforms
├── html-min-transform.js
└── parse-transform.js
└── utils
└── minify.js
/.eleventy.js:
--------------------------------------------------------------------------------
1 | require('dotenv').config();
2 |
3 | const rssPlugin = require('@11ty/eleventy-plugin-rss');
4 | const syntaxHighlight = require('@11ty/eleventy-plugin-syntaxhighlight');
5 |
6 | // Import filters
7 | const dateFilter = require('./src/filters/date-filter.js');
8 | const likesFilter = require('./src/filters/likes-filter.js');
9 | const markdownFilter = require('./src/filters/markdown-filter.js');
10 | const w3DateFilter = require('./src/filters/w3-date-filter.js');
11 |
12 | // Import transforms
13 | const htmlMinTransform = require('./src/transforms/html-min-transform.js');
14 | const parseTransform = require('./src/transforms/parse-transform.js');
15 |
16 | // Import shortcodes
17 | const codepen = require('./src/shortcodes/codepen.js');
18 |
19 | // Import data files
20 | const site = require('./src/_data/site.json');
21 |
22 | module.exports = function(config) {
23 | // Filters
24 | config.addFilter('dateFilter', dateFilter);
25 | config.addFilter('likesFilter', likesFilter);
26 | config.addFilter('markdownFilter', markdownFilter);
27 | config.addFilter('w3DateFilter', w3DateFilter);
28 |
29 | // Layout aliases
30 | config.addLayoutAlias('home', 'layouts/home.njk');
31 |
32 | // Transforms
33 | config.addTransform('htmlmin', htmlMinTransform);
34 | config.addTransform('parse', parseTransform);
35 |
36 | // Shortcodes
37 | config.addShortcode('codepen', codepen);
38 |
39 | // Passthrough copy
40 | config.addPassthroughCopy('src/assets');
41 | config.addPassthroughCopy('src/_redirects');
42 | config.addPassthroughCopy('src/images');
43 | config.addPassthroughCopy('src/js');
44 |
45 | const now = new Date();
46 |
47 | // Custom collections
48 | const livePosts = post => post.date <= now && !post.data.draft;
49 | const feedExcluded = post => !['weeknotes'].some(x => post.data.tags.includes(x));
50 |
51 | config.addCollection('posts', collection => {
52 | return [
53 | ...collection
54 | .getFilteredByGlob('./src/posts/*.md')
55 | .filter(livePosts)
56 | .filter(feedExcluded)
57 | ].reverse();
58 | });
59 |
60 | config.addCollection('postFeed', collection => {
61 | return [
62 | ...collection
63 | .getFilteredByGlob('./src/posts/*.md')
64 | .filter(livePosts)
65 | .filter(feedExcluded)
66 | ]
67 | .reverse()
68 | .slice(0, site.maxPostsPerPage);
69 | });
70 |
71 | config.addCollection('feed', collection => {
72 | const notes = collection.getFilteredByTag('notes');
73 | const links = collection.getFilteredByTag('links');
74 | return [...notes, ...links].sort((a, b) => {
75 | return new Date(b.date) - new Date(a.date);
76 | });
77 | });
78 |
79 | config.addCollection('sortedNotes', function(collection) {
80 | return collection.getFilteredByTag('notes').reverse();
81 | });
82 |
83 | config.addCollection('sortedLinks', function(collection) {
84 | return collection.getFilteredByTag('links').reverse();
85 | });
86 |
87 | config.addCollection('allFeed', function(collection) {
88 | const posts = collection.getFilteredByGlob('./src/posts/*.md').filter(livePosts);
89 | return [...posts].sort((a, b) => {
90 | return new Date(b.date) - new Date(a.date);
91 | });
92 | });
93 |
94 | // Plugins
95 | config.addPlugin(rssPlugin);
96 | config.addPlugin(syntaxHighlight);
97 |
98 | return {
99 | dir: {
100 | input: 'src',
101 | output: 'dist'
102 | },
103 | passthroughFileCopy: true
104 | };
105 | };
106 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.log
2 | npm-debug.*
3 | *.scssc
4 | *.log
5 | *.swp
6 | .DS_Store
7 | .sass-cache
8 | .env
9 | node_modules
10 | dist
11 |
12 | # Specifics
13 |
14 | # Hide design tokens
15 | src/scss/_tokens.scss
16 |
17 | # Hide compiled CSS
18 | src/_includes/assets/*
19 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | printWidth: 90,
3 | tabWidth: 2,
4 | singleQuote: true,
5 | bracketSpacing: false
6 | }
7 |
--------------------------------------------------------------------------------
/netlify.toml:
--------------------------------------------------------------------------------
1 | [build]
2 | command = "npm run production"
3 | publish = "dist"
4 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "hylia",
3 | "version": "0.4.0",
4 | "description": "A simple Eleventy starter kit to help you have a blog of your own",
5 | "main": "index.js",
6 | "dependencies": {
7 | "@11ty/eleventy": "^0.10.0",
8 | "@11ty/eleventy-plugin-rss": "^1.0.6",
9 | "@11ty/eleventy-plugin-syntaxhighlight": "^2.0.3",
10 | "@tbranyen/jsdom": "^13.0.0",
11 | "axios": "^0.19.0",
12 | "concurrently": "^4.1.0",
13 | "dotenv": "^8.0.0",
14 | "html-minifier": "^4.0.0",
15 | "json-to-scss": "^1.3.1",
16 | "sanitize-html": "^1.20.1",
17 | "sass": "^1.21.0",
18 | "slugify": "^1.3.4",
19 | "stalfos": "git://github.com/andybelldesign/stalfos.git#49f9e68a7a590b8739df2087f05901dcc6baa761"
20 | },
21 | "devDependencies": {
22 | "chokidar-cli": "^1.2.2",
23 | "cross-env": "^5.2.0",
24 | "make-dir-cli": "^2.0.0",
25 | "prettier": "^1.18.2",
26 | "rollup": "^1.16.1",
27 | "rollup-plugin-commonjs": "^10.0.0",
28 | "rollup-plugin-json": "^4.0.0",
29 | "rollup-plugin-node-builtins": "^2.1.2",
30 | "rollup-plugin-node-resolve": "^5.0.3"
31 | },
32 | "scripts": {
33 | "sass:tokens": "npx json-to-scss src/_data/tokens.json src/scss/_tokens.scss",
34 | "sass:process": "npm run sass:tokens && sass src/scss/global.scss src/_includes/assets/css/global.css --style=compressed",
35 | "start": "concurrently 'npm run sass:process -- --watch' 'npm run serve'",
36 | "serve": "cross-env ELEVENTY_ENV=development npx eleventy --serve",
37 | "production": "npm run sass:process && npx eleventy"
38 | },
39 | "repository": {
40 | "type": "git",
41 | "url": "git+https://github.com/andybelldesign/personal-site-hylia.git"
42 | },
43 | "keywords": [],
44 | "author": "",
45 | "license": "MIT",
46 | "bugs": {
47 | "url": "https://github.com/andybelldesign/personal-site-hylia/issues"
48 | },
49 | "homepage": "https://github.com/andybelldesign/personal-site-hylia#readme"
50 | }
51 |
--------------------------------------------------------------------------------
/rollup.config.js:
--------------------------------------------------------------------------------
1 | const builtins = require('rollup-plugin-node-builtins');
2 | const commonjs = require('rollup-plugin-commonjs');
3 | const nodeResolve = require('rollup-plugin-node-resolve');
4 | const json = require('rollup-plugin-json');
5 |
6 | export default {
7 | input: 'src/admin/util',
8 | output: {
9 | file: 'dist/admin/util.js',
10 | format: 'iife',
11 | name: 'previewUtil',
12 | },
13 | plugins: [
14 | builtins(),
15 | nodeResolve(),
16 | commonjs(),
17 | json(),
18 | ]
19 | };
20 |
--------------------------------------------------------------------------------
/src/_data/global.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | random() {
3 | const segment = () => {
4 | return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
5 | };
6 | return `${segment()}-${segment()}-${segment()}`;
7 | }
8 | };
9 |
--------------------------------------------------------------------------------
/src/_data/helpers.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | getNextHeadingLevel(currentLevel) {
3 | return parseInt(currentLevel, 10) + 1;
4 | },
5 | getReadingTime(text) {
6 | const wordsPerMinute = 200;
7 | const numberOfWords = text.split(/\s/g).length;
8 | return Math.ceil(numberOfWords / wordsPerMinute);
9 | }
10 | };
11 |
--------------------------------------------------------------------------------
/src/_data/navigation.json:
--------------------------------------------------------------------------------
1 | {
2 | "items": [
3 | {
4 | "text": "Writing",
5 | "url": "/writing/",
6 | "rel": null
7 | },
8 | {
9 | "text": "Projects",
10 | "url": "/projects/",
11 | "rel": null
12 | },
13 | {
14 | "text": "RSS",
15 | "url": "https://hankchizljaw.com/feed/all.xml",
16 | "rel": null
17 | },
18 | {
19 | "text": "Micro Blog",
20 | "url": "//microblog.hankchizljaw.com",
21 | "rel": "external"
22 | },
23 | {
24 | "text": "Twitter",
25 | "url": "//twitter.com/hankchizljaw",
26 | "rel": "me"
27 | },
28 | {
29 | "text": "CodePen",
30 | "url": "//codepen.io/andybelldesign",
31 | "rel": null
32 | },
33 | {
34 | "text": "GitHub",
35 | "url": "//github.com/hankchizljaw",
36 | "rel": "me"
37 | }
38 | ]
39 | }
40 |
--------------------------------------------------------------------------------
/src/_data/site.json:
--------------------------------------------------------------------------------
1 | {
2 | "showThemeCredit": true,
3 | "name": "Andy Bell",
4 | "availability": "I produce front-end development tutorials over at [Front-End Challenges Club](//front-end-challenges.club) and [Piccalilli](//piccalil.li). You can sign up for updates on Piccalilli to stay up to date with its progress.",
5 | "shortDesc": "Freelance web designer ➤ CSS stuff ➤ Curates piccalil.li ➤ Co-author of [Every Layout](https://every-layout.dev) ➤ Writing [CSS From Scratch](https://cssfromscratch.com)",
6 | "url": "https://hankchizljaw.com",
7 | "authorEmail": "me@andy-bell.design",
8 | "authorHandle": "@hankchizljaw",
9 | "authorName": "Andy Bell",
10 | "enableThirdPartyComments": false,
11 | "maxPostsPerPage": 5
12 | }
13 |
--------------------------------------------------------------------------------
/src/_data/styleguide.js:
--------------------------------------------------------------------------------
1 | const tokens = require('./tokens.json');
2 |
3 | module.exports = {
4 | colors() {
5 | let response = [];
6 |
7 | Object.keys(tokens.colors).forEach(key => {
8 | response.push({
9 | value: tokens.colors[key],
10 | key
11 | });
12 | });
13 |
14 | return response;
15 | },
16 | sizes() {
17 | let response = [];
18 |
19 | Object.keys(tokens['size-scale']).forEach(key => {
20 | response.push({
21 | value: tokens['size-scale'][key],
22 | key
23 | });
24 | });
25 |
26 | return response;
27 | }
28 | };
29 |
--------------------------------------------------------------------------------
/src/_data/tokens.json:
--------------------------------------------------------------------------------
1 | {
2 | "size-scale": {
3 | "base": "1rem",
4 | "300": "0.8rem",
5 | "500": "1.25rem",
6 | "600": "1.56rem",
7 | "700": "1.95rem",
8 | "800": "2.44rem",
9 | "900": "3.05rem",
10 | "max": "4rem"
11 | },
12 | "colors": {
13 | "dark": "#252525",
14 | "light": "#dedede"
15 | },
16 | "fonts": {
17 | "base": "\"Georgia, serif\"",
18 | "sans": "\"'Segoe UI', 'Roboto', 'Helvetica Neue', Arial, sans-serif\""
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/_includes/icons/arrow.svg:
--------------------------------------------------------------------------------
1 |
14 |
--------------------------------------------------------------------------------
/src/_includes/layouts/archive.njk:
--------------------------------------------------------------------------------
1 | {% extends 'layouts/base.njk' %}
2 | {% set pageType = 'Post Archive' %}
3 |
4 | {# Intro content #}
5 | {% set introHeading = title %}
6 | {% set introSummary %}{{ content | safe }}{% endset %}
7 |
8 | {# Post list content #}
9 | {% set postListHeading = 'All posts' %}
10 | {% set postListItems = collections.posts %}
11 |
12 | {% block content %}
13 |
22 |
23 |
9 | Hire me 10 |
11 | {% endset %} 12 | 13 | {# Post list content #} 14 | {% set postListHeading = postsHeading %} 15 | {% set postListItems = collections.postFeed %} 16 | 17 | {# Archive link #} 18 | {% if postListItems.length < collections.posts.length %} 19 | {% set paginationNextText = archiveButtonText %} 20 | {% set paginationNextUrl = '/writing' %} 21 | {% endif %} 22 | 23 | {% block content %} 24 |12 | 13 |
14 |5 | Sign up for updates 6 |
7 |
34 |
35 |