From 5e0eb0cdcf8f8d74133d12271811c74d4c38d431 Mon Sep 17 00:00:00 2001
From: N-Upchurch
Date: Wed, 5 Jul 2023 11:06:31 -0500
Subject: [PATCH] push my changes to new repo
---
.kateproject.notes | 9 +
README.md | 121 +----
README.md.backup | 26 +
_data/metadata.js | 13 +-
_includes/layouts/404.njk | 8 +
_includes/layouts/base.njk | 48 +-
_includes/layouts/home.njk | 14 +-
_includes/layouts/post.njk | 3 +-
_includes/postslist.njk | 32 +-
content/404.md | 16 +-
content/404.md.backup | 19 +
content/about/index.md | 7 +-
content/blog.njk | 10 +-
.../build-an-svg-circle-grid-with-p5js.md | 451 ++++++++++++++++++
content/blog/fifthpost.md | 6 -
content/blog/firstpost.md | 26 -
content/blog/floss-and-smes.md | 28 ++
content/blog/fourthpost/fourthpost.md | 16 -
content/blog/fourthpost/possum.png | Bin 130230 -> 0 bytes
content/blog/scp-command.md | 50 ++
content/blog/secondpost.md | 17 -
content/blog/thirdpost.md | 45 --
content/feed/feed.njk | 7 +
content/index.njk | 4 +-
content/tags-list.njk | 10 +-
content/tags.njk | 8 +-
eleventy.config.images.js | 2 +-
eleventy.config.js | 4 +-
package.json | 3 +
public/css/dropcap.css | 15 +
public/css/index.css | 283 +++++++++--
.../css/webfonts/manrope-bold-latin-ext.woff | Bin 0 -> 16612 bytes
.../css/webfonts/manrope-bold-latin-ext.woff2 | Bin 0 -> 14860 bytes
public/css/webfonts/manrope-bold-latin.woff | Bin 0 -> 20676 bytes
public/css/webfonts/manrope-bold-latin.woff2 | Bin 0 -> 18436 bytes
.../webfonts/manrope-extrabold-latin-ext.woff | Bin 0 -> 16448 bytes
.../manrope-extrabold-latin-ext.woff2 | Bin 0 -> 14612 bytes
.../css/webfonts/manrope-extrabold-latin.woff | Bin 0 -> 20332 bytes
.../webfonts/manrope-extrabold-latin.woff2 | Bin 0 -> 18056 bytes
.../manrope-extralight-latin-ext.woff | Bin 0 -> 15436 bytes
.../manrope-extralight-latin-ext.woff2 | Bin 0 -> 13836 bytes
.../webfonts/manrope-extralight-latin.woff | Bin 0 -> 19440 bytes
.../webfonts/manrope-extralight-latin.woff2 | Bin 0 -> 17312 bytes
.../css/webfonts/manrope-light-latin-ext.woff | Bin 0 -> 15840 bytes
.../webfonts/manrope-light-latin-ext.woff2 | Bin 0 -> 14224 bytes
public/css/webfonts/manrope-light-latin.woff | Bin 0 -> 20172 bytes
public/css/webfonts/manrope-light-latin.woff2 | Bin 0 -> 18020 bytes
.../webfonts/manrope-medium-latin-ext.woff | Bin 0 -> 16044 bytes
.../webfonts/manrope-medium-latin-ext.woff2 | Bin 0 -> 14368 bytes
public/css/webfonts/manrope-medium-latin.woff | Bin 0 -> 20448 bytes
.../css/webfonts/manrope-medium-latin.woff2 | Bin 0 -> 18224 bytes
.../webfonts/manrope-regular-latin-ext.woff | Bin 0 -> 15820 bytes
.../webfonts/manrope-regular-latin-ext.woff2 | Bin 0 -> 14096 bytes
.../css/webfonts/manrope-regular-latin.woff | Bin 0 -> 20320 bytes
.../css/webfonts/manrope-regular-latin.woff2 | Bin 0 -> 18012 bytes
.../webfonts/manrope-semibold-latin-ext.woff | Bin 0 -> 16244 bytes
.../webfonts/manrope-semibold-latin-ext.woff2 | Bin 0 -> 14572 bytes
.../css/webfonts/manrope-semibold-latin.woff | Bin 0 -> 20540 bytes
.../css/webfonts/manrope-semibold-latin.woff2 | Bin 0 -> 18308 bytes
...ayfair-display-black-italic-latin-ext.woff | Bin 0 -> 15616 bytes
...yfair-display-black-italic-latin-ext.woff2 | Bin 0 -> 12128 bytes
.../playfair-display-black-italic-latin.woff | Bin 0 -> 23400 bytes
.../playfair-display-black-italic-latin.woff2 | Bin 0 -> 18984 bytes
.../playfair-display-black-latin-ext.woff | Bin 0 -> 14448 bytes
.../playfair-display-black-latin-ext.woff2 | Bin 0 -> 11120 bytes
.../playfair-display-black-latin.woff | Bin 0 -> 24420 bytes
.../playfair-display-black-latin.woff2 | Bin 0 -> 19432 bytes
...layfair-display-bold-italic-latin-ext.woff | Bin 0 -> 16212 bytes
...ayfair-display-bold-italic-latin-ext.woff2 | Bin 0 -> 12648 bytes
.../playfair-display-bold-italic-latin.woff | Bin 0 -> 24888 bytes
.../playfair-display-bold-italic-latin.woff2 | Bin 0 -> 20328 bytes
.../playfair-display-bold-latin-ext.woff | Bin 0 -> 14720 bytes
.../playfair-display-bold-latin-ext.woff2 | Bin 0 -> 11384 bytes
.../webfonts/playfair-display-bold-latin.woff | Bin 0 -> 25516 bytes
.../playfair-display-bold-latin.woff2 | Bin 0 -> 20344 bytes
...ir-display-extrabold-italic-latin-ext.woff | Bin 0 -> 16160 bytes
...r-display-extrabold-italic-latin-ext.woff2 | Bin 0 -> 12596 bytes
...ayfair-display-extrabold-italic-latin.woff | Bin 0 -> 24680 bytes
...yfair-display-extrabold-italic-latin.woff2 | Bin 0 -> 20212 bytes
.../playfair-display-extrabold-latin-ext.woff | Bin 0 -> 14776 bytes
...playfair-display-extrabold-latin-ext.woff2 | Bin 0 -> 11440 bytes
.../playfair-display-extrabold-latin.woff | Bin 0 -> 25536 bytes
.../playfair-display-extrabold-latin.woff2 | Bin 0 -> 20156 bytes
.../playfair-display-italic-latin-ext.woff | Bin 0 -> 15796 bytes
.../playfair-display-italic-latin-ext.woff2 | Bin 0 -> 12296 bytes
.../playfair-display-italic-latin.woff | Bin 0 -> 23620 bytes
.../playfair-display-italic-latin.woff2 | Bin 0 -> 19068 bytes
...yfair-display-medium-italic-latin-ext.woff | Bin 0 -> 16204 bytes
...fair-display-medium-italic-latin-ext.woff2 | Bin 0 -> 12580 bytes
.../playfair-display-medium-italic-latin.woff | Bin 0 -> 24816 bytes
...playfair-display-medium-italic-latin.woff2 | Bin 0 -> 20216 bytes
.../playfair-display-medium-latin-ext.woff | Bin 0 -> 14644 bytes
.../playfair-display-medium-latin-ext.woff2 | Bin 0 -> 11316 bytes
.../playfair-display-medium-latin.woff | Bin 0 -> 25396 bytes
.../playfair-display-medium-latin.woff2 | Bin 0 -> 20096 bytes
.../playfair-display-regular-latin-ext.woff | Bin 0 -> 14108 bytes
.../playfair-display-regular-latin-ext.woff2 | Bin 0 -> 10832 bytes
.../playfair-display-regular-latin.woff | Bin 0 -> 24116 bytes
.../playfair-display-regular-latin.woff2 | Bin 0 -> 19080 bytes
...air-display-semibold-italic-latin-ext.woff | Bin 0 -> 16224 bytes
...ir-display-semibold-italic-latin-ext.woff2 | Bin 0 -> 12688 bytes
...layfair-display-semibold-italic-latin.woff | Bin 0 -> 24884 bytes
...ayfair-display-semibold-italic-latin.woff2 | Bin 0 -> 20280 bytes
.../playfair-display-semibold-latin-ext.woff | Bin 0 -> 14700 bytes
.../playfair-display-semibold-latin-ext.woff2 | Bin 0 -> 11288 bytes
.../playfair-display-semibold-latin.woff | Bin 0 -> 25436 bytes
.../playfair-display-semibold-latin.woff2 | Bin 0 -> 20212 bytes
public/css/webfonts/webfonts.css | 417 ++++++++++++++++
public/img/RSS.svg | 104 ++++
...na-sirotina-1NMPvajSt9Q-unsplash_copy.avif | Bin 0 -> 24926 bytes
public/img/logo_favicon.svg | 61 +++
.../circle-grid-canvas.webp | Bin 0 -> 10580 bytes
.../circle-grid-complete.webp | Bin 0 -> 152366 bytes
.../circle-grid-grid.webp | Bin 0 -> 319826 bytes
.../circle-grid-line.webp | Bin 0 -> 11720 bytes
.../circle-grid-post-image.webp | Bin 0 -> 51364 bytes
.../pedro-lastra-Nyvq2juw4_o-unsplash.webp | Bin 0 -> 638810 bytes
public/img/terminal.svg | 171 +++++++
118 files changed, 1696 insertions(+), 358 deletions(-)
create mode 100644 .kateproject.notes
create mode 100644 README.md.backup
create mode 100644 _includes/layouts/404.njk
create mode 100644 content/404.md.backup
create mode 100644 content/blog/build-an-svg-circle-grid-with-p5js/build-an-svg-circle-grid-with-p5js.md
delete mode 100644 content/blog/fifthpost.md
delete mode 100644 content/blog/firstpost.md
create mode 100644 content/blog/floss-and-smes.md
delete mode 100644 content/blog/fourthpost/fourthpost.md
delete mode 100644 content/blog/fourthpost/possum.png
create mode 100644 content/blog/scp-command.md
delete mode 100644 content/blog/secondpost.md
delete mode 100644 content/blog/thirdpost.md
create mode 100644 public/css/dropcap.css
create mode 100644 public/css/webfonts/manrope-bold-latin-ext.woff
create mode 100644 public/css/webfonts/manrope-bold-latin-ext.woff2
create mode 100644 public/css/webfonts/manrope-bold-latin.woff
create mode 100644 public/css/webfonts/manrope-bold-latin.woff2
create mode 100644 public/css/webfonts/manrope-extrabold-latin-ext.woff
create mode 100644 public/css/webfonts/manrope-extrabold-latin-ext.woff2
create mode 100644 public/css/webfonts/manrope-extrabold-latin.woff
create mode 100644 public/css/webfonts/manrope-extrabold-latin.woff2
create mode 100644 public/css/webfonts/manrope-extralight-latin-ext.woff
create mode 100644 public/css/webfonts/manrope-extralight-latin-ext.woff2
create mode 100644 public/css/webfonts/manrope-extralight-latin.woff
create mode 100644 public/css/webfonts/manrope-extralight-latin.woff2
create mode 100644 public/css/webfonts/manrope-light-latin-ext.woff
create mode 100644 public/css/webfonts/manrope-light-latin-ext.woff2
create mode 100644 public/css/webfonts/manrope-light-latin.woff
create mode 100644 public/css/webfonts/manrope-light-latin.woff2
create mode 100644 public/css/webfonts/manrope-medium-latin-ext.woff
create mode 100644 public/css/webfonts/manrope-medium-latin-ext.woff2
create mode 100644 public/css/webfonts/manrope-medium-latin.woff
create mode 100644 public/css/webfonts/manrope-medium-latin.woff2
create mode 100644 public/css/webfonts/manrope-regular-latin-ext.woff
create mode 100644 public/css/webfonts/manrope-regular-latin-ext.woff2
create mode 100644 public/css/webfonts/manrope-regular-latin.woff
create mode 100644 public/css/webfonts/manrope-regular-latin.woff2
create mode 100644 public/css/webfonts/manrope-semibold-latin-ext.woff
create mode 100644 public/css/webfonts/manrope-semibold-latin-ext.woff2
create mode 100644 public/css/webfonts/manrope-semibold-latin.woff
create mode 100644 public/css/webfonts/manrope-semibold-latin.woff2
create mode 100644 public/css/webfonts/playfair-display-black-italic-latin-ext.woff
create mode 100644 public/css/webfonts/playfair-display-black-italic-latin-ext.woff2
create mode 100644 public/css/webfonts/playfair-display-black-italic-latin.woff
create mode 100644 public/css/webfonts/playfair-display-black-italic-latin.woff2
create mode 100644 public/css/webfonts/playfair-display-black-latin-ext.woff
create mode 100644 public/css/webfonts/playfair-display-black-latin-ext.woff2
create mode 100644 public/css/webfonts/playfair-display-black-latin.woff
create mode 100644 public/css/webfonts/playfair-display-black-latin.woff2
create mode 100644 public/css/webfonts/playfair-display-bold-italic-latin-ext.woff
create mode 100644 public/css/webfonts/playfair-display-bold-italic-latin-ext.woff2
create mode 100644 public/css/webfonts/playfair-display-bold-italic-latin.woff
create mode 100644 public/css/webfonts/playfair-display-bold-italic-latin.woff2
create mode 100644 public/css/webfonts/playfair-display-bold-latin-ext.woff
create mode 100644 public/css/webfonts/playfair-display-bold-latin-ext.woff2
create mode 100644 public/css/webfonts/playfair-display-bold-latin.woff
create mode 100644 public/css/webfonts/playfair-display-bold-latin.woff2
create mode 100644 public/css/webfonts/playfair-display-extrabold-italic-latin-ext.woff
create mode 100644 public/css/webfonts/playfair-display-extrabold-italic-latin-ext.woff2
create mode 100644 public/css/webfonts/playfair-display-extrabold-italic-latin.woff
create mode 100644 public/css/webfonts/playfair-display-extrabold-italic-latin.woff2
create mode 100644 public/css/webfonts/playfair-display-extrabold-latin-ext.woff
create mode 100644 public/css/webfonts/playfair-display-extrabold-latin-ext.woff2
create mode 100644 public/css/webfonts/playfair-display-extrabold-latin.woff
create mode 100644 public/css/webfonts/playfair-display-extrabold-latin.woff2
create mode 100644 public/css/webfonts/playfair-display-italic-latin-ext.woff
create mode 100644 public/css/webfonts/playfair-display-italic-latin-ext.woff2
create mode 100644 public/css/webfonts/playfair-display-italic-latin.woff
create mode 100644 public/css/webfonts/playfair-display-italic-latin.woff2
create mode 100644 public/css/webfonts/playfair-display-medium-italic-latin-ext.woff
create mode 100644 public/css/webfonts/playfair-display-medium-italic-latin-ext.woff2
create mode 100644 public/css/webfonts/playfair-display-medium-italic-latin.woff
create mode 100644 public/css/webfonts/playfair-display-medium-italic-latin.woff2
create mode 100644 public/css/webfonts/playfair-display-medium-latin-ext.woff
create mode 100644 public/css/webfonts/playfair-display-medium-latin-ext.woff2
create mode 100644 public/css/webfonts/playfair-display-medium-latin.woff
create mode 100644 public/css/webfonts/playfair-display-medium-latin.woff2
create mode 100644 public/css/webfonts/playfair-display-regular-latin-ext.woff
create mode 100644 public/css/webfonts/playfair-display-regular-latin-ext.woff2
create mode 100644 public/css/webfonts/playfair-display-regular-latin.woff
create mode 100644 public/css/webfonts/playfair-display-regular-latin.woff2
create mode 100644 public/css/webfonts/playfair-display-semibold-italic-latin-ext.woff
create mode 100644 public/css/webfonts/playfair-display-semibold-italic-latin-ext.woff2
create mode 100644 public/css/webfonts/playfair-display-semibold-italic-latin.woff
create mode 100644 public/css/webfonts/playfair-display-semibold-italic-latin.woff2
create mode 100644 public/css/webfonts/playfair-display-semibold-latin-ext.woff
create mode 100644 public/css/webfonts/playfair-display-semibold-latin-ext.woff2
create mode 100644 public/css/webfonts/playfair-display-semibold-latin.woff
create mode 100644 public/css/webfonts/playfair-display-semibold-latin.woff2
create mode 100644 public/css/webfonts/webfonts.css
create mode 100644 public/img/RSS.svg
create mode 100644 public/img/default_post_image/vasilina-sirotina-1NMPvajSt9Q-unsplash_copy.avif
create mode 100644 public/img/logo_favicon.svg
create mode 100644 public/img/posts/build-an-svg-circle-grid-with-p5js/circle-grid-canvas.webp
create mode 100644 public/img/posts/build-an-svg-circle-grid-with-p5js/circle-grid-complete.webp
create mode 100644 public/img/posts/build-an-svg-circle-grid-with-p5js/circle-grid-grid.webp
create mode 100644 public/img/posts/build-an-svg-circle-grid-with-p5js/circle-grid-line.webp
create mode 100644 public/img/posts/build-an-svg-circle-grid-with-p5js/circle-grid-post-image.webp
create mode 100644 public/img/posts/floss-and-smes/pedro-lastra-Nyvq2juw4_o-unsplash.webp
create mode 100644 public/img/terminal.svg
diff --git a/.kateproject.notes b/.kateproject.notes
new file mode 100644
index 0000000..5aaed1f
--- /dev/null
+++ b/.kateproject.notes
@@ -0,0 +1,9 @@
+TODO:
+
+Handle main post image and in-article images
+Integrate est. read time
+Integrate % done in article
+Investigate pagination for /blog/
+Add Favicon
+Integrate recipe structured data for recipe type articles
+Consider optimising character count per line
\ No newline at end of file
diff --git a/README.md b/README.md
index 927d5bb..9ae6f57 100644
--- a/README.md
+++ b/README.md
@@ -1,123 +1,6 @@
-# eleventy-base-blog v8
-
-A starter repository showing how to build a blog with the [Eleventy](https://www.11ty.dev/) site generator (using the [v2.0 release](https://www.11ty.dev/blog/eleventy-v2/)).
-
-[](https://app.netlify.com/sites/eleventy-base-blog/deploys)
-
-## Getting Started
-
-* [Want a more generic/detailed getting started guide?](https://www.11ty.dev/docs/getting-started/)
-
-1. Make a directory and navigate to it:
-
-```
-mkdir my-blog-name
-cd my-blog-name
-```
-
-2. Clone this Repository
-
-```
-git clone https://github.com/11ty/eleventy-base-blog.git .
-```
-
-_Optional:_ Review `eleventy.config.js` and `_data/metadata.js` to configure the site’s options and data.
-
-3. Install dependencies
-
-```
-npm install
-```
-
-4. Run Eleventy
-
-Generate a production-ready build to the `_site` folder:
-
-```
-npx @11ty/eleventy
-```
-
-Or build and host on a local development server:
-
-```
-npx @11ty/eleventy --serve
-```
-
-Or you can run [debug mode](https://www.11ty.dev/docs/debugging/) to see all the internals.
-
-## Features
-
-- Using [Eleventy v2.0](https://www.11ty.dev/blog/eleventy-v2/) with zero-JavaScript output.
- - Content is exclusively pre-rendered (this is a static site).
- - Can easily [deploy to a subfolder without changing any content](https://www.11ty.dev/docs/plugins/html-base/)
- - All URLs are decoupled from the content’s location on the file system.
- - Configure templates via the [Eleventy Data Cascade](https://www.11ty.dev/docs/data-cascade/)
-- **Performance focused**: four-hundos Lighthouse score out of the box!
- - [View the Lighthouse report for the latest build](https://eleventy-base-blog.netlify.app/reports/lighthouse/) courtesy of the [Netlify Lighthouse plugin](https://github.com/netlify/netlify-plugin-lighthouse).
- - _0 Cumulative Layout Shift_
- - _0ms Total Blocking Time_
-- Local development live reload provided by [Eleventy Dev Server](https://www.11ty.dev/docs/dev-server/).
-- Content-driven [navigation menu](https://www.11ty.dev/docs/plugins/navigation/)
-- [Image optimization](https://www.11ty.dev/docs/plugins/image/) via the `{% image %}` shortcode.
- - Zero-JavaScript output.
- - Support for modern image formats automatically (e.g. AVIF and WebP)
- - Prefers `` markup if possible (single image format) but switches automatically to `` for multiple image formats.
- - Automated `` syntax markup with `srcset` and optional `sizes`
- - Includes `width`/`height` attributes to avoid [content layout shift](https://web.dev/cls/).
- - Includes `loading="lazy"` for native lazy loading without JavaScript.
- - Includes [`decoding="async"`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/decoding)
- - Images can be co-located with blog post files.
- - View the [Image plugin source code](https://github.com/11ty/eleventy-base-blog/blob/main/eleventy.config.images.js)
-- Per page CSS bundles [via `eleventy-plugin-bundle`](https://github.com/11ty/eleventy-plugin-bundle).
-- Built-in [syntax highlighter](https://www.11ty.dev/docs/plugins/syntaxhighlight/) (zero-JavaScript output).
-- Blog Posts
- - Draft posts: use `draft: true` to mark a blog post as a draft. Drafts are **only** included during `--serve`/`--watch` and are excluded from full builds. View the [Drafts plugin source code](https://github.com/11ty/eleventy-base-blog/blob/main/eleventy.config.drafts.js).
- - Automated next/previous links
- - Accessible deep links to headings
-- Generated Pages
- - Home, Archive, and About pages.
- - [Feeds for Atom and JSON](https://www.11ty.dev/docs/plugins/rss/)
- - `sitemap.xml`
- - Zero-maintenance tag pages ([View on the Demo](https://eleventy-base-blog.netlify.app/tags/))
- - Content not found (404) page
-
-## Demos
-
-- [Netlify](https://eleventy-base-blog.netlify.com/)
-- [GitHub Pages](https://11ty.github.io/eleventy-base-blog/)
-- [Remix on Glitch](https://glitch.com/~11ty-eleventy-base-blog)
-
-## Deploy this to your own site
-
-Deploy this Eleventy site in just a few clicks on these services:
-
-- [Get your own Eleventy web site on Netlify](https://app.netlify.com/start/deploy?repository=https://github.com/11ty/eleventy-base-blog)
-- If you run Eleventy locally you can drag your `_site` folder to [`drop.netlify.com`](https://drop.netlify.com/) to upload it without using `git`.
-- [Get your own Eleventy web site on Vercel](https://vercel.com/import/project?template=11ty%2Feleventy-base-blog)
-- Read more about [Deploying an Eleventy project](https://www.11ty.dev/docs/deployment/) to the web.
+# nathanupchurch.com - Based on eleventy-base-blog v8
### Implementation Notes
-- `content/about/index.md` is an example of a content page.
- `content/blog/` has the blog posts but really they can live in any directory. They need only the `posts` tag to be included in the blog posts [collection](https://www.11ty.dev/docs/collections/).
-- Use the `eleventyNavigation` key (via the [Eleventy Navigation plugin](https://www.11ty.dev/docs/plugins/navigation/)) in your front matter to add a template to the top level site navigation. This is in use on `content/index.njk` and `content/about/index.md`.
-- Content can be in _any template format_ (blog posts needn’t exclusively be markdown, for example). Configure your project’s supported templates in `eleventy.config.js` -> `templateFormats`.
-- The `public` folder in your input directory will be copied to the output folder (via `addPassthroughCopy` in the `eleventy.config.js` file). This means `./public/css/*` will live at `./_site/css/*` after your build completes.
-- Provides two content feeds:
- - `content/feed/feed.njk`
- - `content/feed/json.njk`
-- This project uses three [Eleventy Layouts](https://www.11ty.dev/docs/layouts/):
- - `_includes/layouts/base.njk`: the top level HTML structure
- - `_includes/layouts/home.njk`: the home page template (wrapped into `base.njk`)
- - `_includes/layouts/post.njk`: the blog post template (wrapped into `base.njk`)
-- `_includes/postslist.njk` is a Nunjucks include and is a reusable component used to display a list of all the posts. `content/index.njk` has an example of how to use it.
-
-If your site enforces a Content Security Policy (as public-facing sites should), either, in `base.njk`, disable
-```html
-
-```
-and enable
-```html
-
-```
-or configure the server with the CSP directive `style-src: 'unsafe-inline'` (which is less secure).
+- Use the `eleventyNavigation` key (via the [Eleventy Navigation plugin](https://www.11ty.dev/docs/plugins/navigation/)) in your front matter to add a template to the top level site navigation. This is in use on `content/index.njk` and `content/about/index.md`.
\ No newline at end of file
diff --git a/README.md.backup b/README.md.backup
new file mode 100644
index 0000000..0b3d524
--- /dev/null
+++ b/README.md.backup
@@ -0,0 +1,26 @@
+# nathanupchurch.com - Based on eleventy-base-blog v8
+
+### Implementation Notes
+
+- `content/blog/` has the blog posts but really they can live in any directory. They need only the `posts` tag to be included in the blog posts [collection](https://www.11ty.dev/docs/collections/).
+- Use the `eleventyNavigation` key (via the [Eleventy Navigation plugin](https://www.11ty.dev/docs/plugins/navigation/)) in your front matter to add a template to the top level site navigation. This is in use on `content/index.njk` and `content/about/index.md`.
+- Content can be in _any template format_ (blog posts needn’t exclusively be markdown, for example). Configure your project’s supported templates in `eleventy.config.js` -> `templateFormats`.
+- The `public` folder in your input directory will be copied to the output folder (via `addPassthroughCopy` in the `eleventy.config.js` file). This means `./public/css/*` will live at `./_site/css/*` after your build completes.
+- Provides two content feeds:
+ - `content/feed/feed.njk`
+ - `content/feed/json.njk`
+- This project uses three [Eleventy Layouts](https://www.11ty.dev/docs/layouts/):
+ - `_includes/layouts/base.njk`: the top level HTML structure
+ - `_includes/layouts/home.njk`: the home page template (wrapped into `base.njk`)
+ - `_includes/layouts/post.njk`: the blog post template (wrapped into `base.njk`)
+- `_includes/postslist.njk` is a Nunjucks include and is a reusable component used to display a list of all the posts. `content/index.njk` has an example of how to use it.
+
+If your site enforces a Content Security Policy (as public-facing sites should), either, in `base.njk`, disable
+```html
+
+```
+and enable
+```html
+
+```
+or configure the server with the CSP directive `style-src: 'unsafe-inline'` (which is less secure).
diff --git a/_data/metadata.js b/_data/metadata.js
index 5a5c99b..7342717 100644
--- a/_data/metadata.js
+++ b/_data/metadata.js
@@ -1,11 +1,14 @@
module.exports = {
- title: "Eleventy Base Blog v8",
- url: "https://example.com/",
+ title: "Nathan Upchurch",
+ logo: "/img/logo_favicon.svg",
+ url: "https://nathanupchurch.com/",
language: "en",
- description: "I am writing about my experiences as a naval navel-gazer.",
+ description: "The personal website and blog of Nathan Upchurch.",
author: {
- name: "Your Name Here",
+ name: "Nathan Upchurch",
email: "youremailaddress@example.com",
url: "https://example.com/about-me/"
- }
+ },
+ defaultPostImageURL: "/img/default_post_image/vasilina-sirotina-1NMPvajSt9Q-unsplash_copy.avif",
+ defaultPostImageAlt: "The default post image: a close picture of the dark green leaves of a plant."
}
diff --git a/_includes/layouts/404.njk b/_includes/layouts/404.njk
new file mode 100644
index 0000000..d7a6205
--- /dev/null
+++ b/_includes/layouts/404.njk
@@ -0,0 +1,8 @@
+---
+layout: layouts/base.njk
+showPostListHeader: yep
+---
+
+
+{{ content | safe }}
diff --git a/_includes/layouts/base.njk b/_includes/layouts/base.njk
index 3b3226f..7233c9e 100644
--- a/_includes/layouts/base.njk
+++ b/_includes/layouts/base.njk
@@ -4,48 +4,56 @@
{{ title or metadata.title }}
+
- {#- Atom and JSON feeds included by default #}
- {#- Uncomment this if you’d like folks to know that you used Eleventy to build your site! #}
- {#- #}
+
- {#-
- CSS bundles are provided via the `eleventy-plugin-bundle` plugin:
- 1. You can add to them using `{% css %}`
- 2. You can get from them using `{% getBundle "css" %}` or `{% getBundleFileUrl "css" %}`
- 3. You can do the same for JS: {% js %}{% endjs %} and
- 4. Learn more: https://github.com/11ty/eleventy-plugin-bundle
- #}
-
- {#- Add an arbitrary string to the bundle #}
- {%- css %}* { box-sizing: border-box; }{% endcss %}
- {#- Add the contents of a file to the bundle #}
+ {#- Bundle CSS #}
{%- css %}{% include "public/css/index.css" %}{% endcss %}
- {#- Or add from node_modules #}
{# {%- css %}{% include "node_modules/prismjs/themes/prism-okaidia.css" %}{% endcss %} #}
{#- Render the CSS bundle using Inlined CSS (for the fastest site performance in production) #}
+
+ {%- css %}{% include "public/css/webfonts/webfonts.css" %}{% endcss %}
+ {%- css %}{% include "public/css/dropcap.css" %}{% endcss %}
- {#- Renders the CSS bundle using a separate file, if you can't set CSP directive style-src: 'unsafe-inline' #}
- {#- #}
+ {% if title %}
+
+
+ {% endif %}
Skip to main content
- {{ metadata.title }}
+
- {#- Read more about `eleventy-navigation` at https://www.11ty.dev/docs/plugins/navigation/ #}
diff --git a/_includes/layouts/home.njk b/_includes/layouts/home.njk
index cfb97f6..7851efc 100644
--- a/_includes/layouts/home.njk
+++ b/_includes/layouts/home.njk
@@ -1,16 +1,8 @@
---
layout: layouts/base.njk
+showPostListHeader: yep
---
-
-{%- css %}{% include "public/css/message-box.css" %}{% endcss %}
-
-
-
Edit the _data/metadata.js with your blog’s information.
Welcome to my personal website and blog, where I write about tech, free and open source software, design, vegan cooking, incense, music, and all sorts of other topics that I find interesting.
{{ content | safe }}
diff --git a/_includes/layouts/post.njk b/_includes/layouts/post.njk
index 9543d2d..0824277 100644
--- a/_includes/layouts/post.njk
+++ b/_includes/layouts/post.njk
@@ -10,7 +10,7 @@ layout: layouts/base.njk
{%- for tag in tags | filterTagList %}
{%- set tagUrl %}/tags/{{ tag | slugify }}/{% endset %}
-
+
diff --git a/content/404.md b/content/404.md
index bd51f61..ab399dd 100644
--- a/content/404.md
+++ b/content/404.md
@@ -1,19 +1,5 @@
---
-layout: layouts/home.njk
+layout: layouts/404.njk
permalink: 404.html
eleventyExcludeFromCollections: true
---
-# Content not found.
-
-Go home.
-
-
diff --git a/content/404.md.backup b/content/404.md.backup
new file mode 100644
index 0000000..bd51f61
--- /dev/null
+++ b/content/404.md.backup
@@ -0,0 +1,19 @@
+---
+layout: layouts/home.njk
+permalink: 404.html
+eleventyExcludeFromCollections: true
+---
+# Content not found.
+
+Go home.
+
+
diff --git a/content/about/index.md b/content/about/index.md
index 18367d8..f383e99 100644
--- a/content/about/index.md
+++ b/content/about/index.md
@@ -1,9 +1,8 @@
---
layout: layouts/base.njk
eleventyNavigation:
- key: About Me
+ key: About
order: 3
---
-# About Me
-
-I am a person that writes stuff.
+# About the author, Nathan Upchurch.
+
I'm a prolific vegan home cook, classical trombonist, a FLOSS enthusiast, daily GNU/Linux user and unabashed KDE stan, speaker of subpar elementary Spanish, incense enthusiast, writer, electronics hobbyist, designer, programmer, music producer, print lover, and human with too many interests and too little time. This is my personal website and blog.
Because this is my personal website, I'm not here to talk about work, but I will link my professional bio here when I've gotten around to making it. If you would like to say something nice, you can find me on Mastodon.
This website is made with 11ty, Manrope, Playfair Display, and plain-old HTML & CSS. I don't collect any of your data, full-stop. No analytics, no "anonymized data," nothing. All webfonts, icons, and images are hosted locally (Instead of by Google, for instance, or any other company which might use them to track you).
{% set postslist = collections.posts %}
{% include "postslist.njk" %}
diff --git a/content/blog/build-an-svg-circle-grid-with-p5js/build-an-svg-circle-grid-with-p5js.md b/content/blog/build-an-svg-circle-grid-with-p5js/build-an-svg-circle-grid-with-p5js.md
new file mode 100644
index 0000000..cbbaa9f
--- /dev/null
+++ b/content/blog/build-an-svg-circle-grid-with-p5js/build-an-svg-circle-grid-with-p5js.md
@@ -0,0 +1,451 @@
+---
+title: Build an SVG Circle Grid with p5.js
+description: Make a configurable SVG graphic of a grid of circles in random colors and sizes with p5.js.
+date: 2023-06-18
+tags:
+ - Processing
+ - p5.js
+ - Code Tutorial
+ - SVG
+synopsis: In this tutorial, we'll learn how to make a configurable SVG graphic of a grid of circles in random colors and sizes with p5.js.
+imageURL: /img/terminal.svg
+imageAlt: A stylized illustration of a terminal prompt.
+---
+Processing is a fantastic language for creative programming and learning how to code, allowing programmers of all skill levels to quickly and simply create complex graphics, data visualizations, and generative art. Its Javascript implementation, p5.js, is perfect for those already familiar with Javascript, or who want to use processing to make graphics for the web without the complexity of SVG, or the insanity of using CSS for complex graphics. Today we're going to build [a simple but pretty graphic using P5](#et-voila).
+
+## Our goal
+First, let's define exactly what we're going to be making. We want to make a grid of circles that:
+1. Fills the viewport
+2. Randomly assigns a size to each circle
+3. Randomly assigns a color to each circle
+4. Is flexible and avoids hardcoded values, allowing us to get a variety of different looks depending on our parameters
+5. Allows us to download our generated image as an SVG
+
+With that nailed down, let's go ahead and get set up.
+
+## Setup
+Processing has a handy IDE, much like Arduino, that we can use to get started quickly. Processing IDE is available as a Flatpak, so it should be simple to install no matter what distro you're running. If, sadly, you're on Windows or MacOS, I'm sure there is also a simple way to install it on your machine that can be worked out with a quick search on the internet.
+
+Once you've installed and launched the IDE, at the top right you'll notice a dropdown that says "Java." This is the Processing IDE's mode selector. Click the dropdown, and choose "Manage Modes." In the new window, install "p5.js Mode," and switch to p5.js using the mode selector.
+
+## Getting started
+If you've done everything correctly up to now, you should see two tabs in your IDE: a .js file, and index.html. Our .js file should look like this:
+``` javascript
+function setup() {
+
+}
+
+
+function draw() {
+
+}
+```
+and our index.html should look like this:
+``` html
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+In any processing sketch, there are two main functions, as you can see by looking at our .js file. `setup()` will run once when the sketch is loaded, and `draw()` will loop repeatedly. For our purposes, we don't need `draw()`, so we'll just leave it empty.
+
+Now that we have our boilerplate, the next thing we need to do is set up the canvas for our sketch. As you may recall, we want our sketch to fill the viewport, so let's set up a canvas inside of our `setup()` function like so:
+``` javascript
+function setup() {
+ createCanvas(window.innerWidth, window.innerHeight);
+ background(0);
+ noStroke();
+}
+```
+Now if we click the play icon at the top left of the Processing IDE, a browser window should open and load a page showing our sketch so far. We ought to see a viewport entirely covered with one large black canvas.
+[](../../img/posts/build-an-svg-circle-grid-with-p5js/circle-grid-canvas.webp)
+
+## Random results
+To meet conditions two and three of our goal, we'll need a way to get random numbers. Let's write a quick function inside `setup()` to provide us with random integers:
+``` javascript
+ const getRandomInt = (min, max) => {
+ min = Math.ceil(min);
+ max = Math.floor(max);
+ return Math.floor(Math.random() * (max - min) + min);
+ }
+```
+
+## Let's make some circles
+To make a circle in p5, we need to define three parameters: x position, y position, and its diameter. With that in mind, we can define a circle like so:
+``` javascript
+circle(10,10,10);
+```
+Add one to the bottom of `setup()` and refresh your browser tab if you'd like to test it out. Be sure and delete it afterwards.
+
+We're going to be making a grid of circles, however, so we are going to need a little more information. First, let's start by generating a line of circles. Although we only need to generate a line of circles on one axis for the purpose of making a grid, a row or a column, for the sake of future flexibility, we'll assume that our line might be horizontal, vertical, or diagonal. To do this, we'll need the following information:
+* Line start position x
+* Line start position y
+* Distance between circles on x
+* Distance between circles on y
+* Minimum circle diameter
+* Maximum circle diameter
+* Quantity of circles
+* The axis upon which our line extends
+* An array of colors for our circles
+
+You'll notice that we have min-max values for circle diameter, and an array for our circle colors. This is so that a size and color can be chosen randomly by our program.
+
+With that out of the way, let's start writing a function to generate our line of circles inside `setup()`:
+``` javascript
+const generateCircleLine = (startX, startY, distX, distY, minD, maxD, qty, axis, fillArr) => {
+}
+```
+
+We are going to need to increment our starting coordinates, so let's assign two variables to those parameters:
+``` javascript
+let x = startX;
+let y = startY;
+```
+
+And we can write our loop inside of `generateCircleLine()`:
+``` javascript
+for (let i = 0; i < qty; i++) {
+
+ const diameter = getRandomInt(minD-1, maxD);
+
+ if (!i) {
+ fill(...fillArr[getRandomInt(0, fillArr.length)]);
+ circle(x,y,diameter);
+
+ continue;
+ }
+
+ switch (axis) {
+ case 'x':
+ x = !distX ? x + startX : x + distX;
+ break;
+ case 'y':
+ y = !distY ? y + startY : y + distY;
+ break;
+ case 'xy':
+ x = !distX ? x + startX : x + distX;
+ y = !distY ? y + startY : y + distY;
+ break;
+ }
+
+ fill(...fillArr[getRandomInt(0, fillArr.length)]);
+ circle(x,y,diameter);
+}
+```
+In the loop above:
+* We start by assigning `diameter` to a random integer between `minD` and `maxD`
+* Then, if `i` is false / 0, indicating that we're on our first iteration, we randomly choose a fill color value from `fillArr`, draw our first circle, and continue on to our next iteration.
+* Now that we're on iteration 1 / circle 2, we need to figure out what axis or axes our line is on, and calculate the new starting coordinates for the circle about to be drawn. For this, we use a switch statement, so if we are operating on the x asis, only the x starting coordinate will be incremented, et cetera. We have used the ternary operator here to indicate that if a distance is not specified along any given axis, the program should increment by a distance equal to its starting coordinate.
+* As we now have our coordinates, we choose a random fill color from fillArr, draw our next circle, and repeat until `i < qty`.
+
+That was a lot, so let's look at our code and make sure everything is alright. This is what our code should look like at the moment:
+``` javascript
+function setup() {
+ createCanvas(window.innerWidth, window.innerHeight);
+ background(0);
+ noStroke();
+
+ const getRandomInt = (min, max) => {
+ min = Math.ceil(min);
+ max = Math.floor(max);
+ return Math.floor(Math.random() * (max - min) + min);
+ }
+
+ const generateCircleLine = (startX, startY, distX, distY, minD, maxD, qty, axis, fillArr) => {
+
+ let x = startX;
+ let y = startY;
+
+ for (let i = 0; i < qty; i++) {
+
+ const diameter = getRandomInt(minD-1, maxD);
+
+ if (!i) {
+ fill(...fillArr[getRandomInt(0, fillArr.length)]);
+ circle(x,y,diameter);
+
+ continue;
+ }
+
+ switch (axis) {
+ case 'x':
+ x = !distX ? x + startX : x + distX;
+ break;
+ case 'y':
+ y = !distY ? y + startY : y + distY;
+ break;
+ case 'xy':
+ x = !distX ? x + startX : x + distX;
+ y = !distY ? y + startY : y + distY;
+ break;
+ }
+
+ fill(...fillArr[getRandomInt(0, fillArr.length)]);
+ circle(x,y,diameter);
+ }
+ }
+}
+
+
+function draw() {
+
+}
+```
+
+We can check that everything is working by calling our new function at the bottom of `setup()`:
+``` javascript
+generateCircleLine(10, 10, 20, 0, 5, 10, 10, 'x', [[255,255,255]]);
+```
+[](../../img/posts/build-an-svg-circle-grid-with-p5js/circle-grid-line.webp)
+And look at that! We have a line!
+
+## Repeating rows
+As we now have a function built to generate lines of circles, all we need to do is repeat the process and we'll have a grid. In `setup()`, let's go ahead and create `generateCircleGrid()` to do just that. Because we'll be passing our parameter values from `generateCircleGrid()` to `generateCircleLine()`, we'll need all of the same information, plus a few new parameters:
+``` javascript
+ const generateCircleGrid = (rowStartX, rowStartY, rowDistX, minD, maxD, rowCircleQty, numRows, rowSpacing, fillArr) => {
+}
+```
+Inside our new function, all we need to do is call `generateCircleLine()` in a loop and we'll have ourselves a grid:
+``` javascript
+for (let i = 0; i < numRows; i++) {
+ rowYPosition = !i ? rowStartY : rowStartY + rowSpacing*i;
+ generateCircleLine(rowStartX, rowYPosition, rowDistX, 0, minD, maxD, rowCircleQty, 'x', fillArr);
+}
+```
+In the first line of our for loop, we're checking whether we're in the first iteration (`i == 0`). If so, `rowYPosition` is assigned to rowStartY; otherwise, `rowYPosition` is assigned to `rowStartY + rowSpacing*i`. That means that on our second+ iterations, our row starting coordinate is incremented by our row spacing value multiplied by the current iteration number, ensuring that each iteration draws a row at the correct y coordinate.
+
+We've hardcoded 'x' in the `generateCircleLine()` parameter, so that we only have to worry about incrementing one axis as we generate our grid: `generateCircleLine()` will create columns, and `generateCircleGrid()` loops them to generate rows. To this end, we're also passing 0 to the `distY` in generateCircleLine()`.
+
+## The perfect fit
+So, we can create lines of circles, and use those to make a grid, but we have a problem. Right now, our sketch needs to be explicitly told how many circles to draw in each row. We need a way to determine how many circles ought to be drawn in order to fill the canvas on a given axis.
+
+Fortunately, this is an easy fix. If write a function inside `setup()` to subtract our starting coordinate from the window dimension for a given axis, divide the result by the distance between circles, and return the result, we should wind up with just the right nimber of circles to fit within that axis. We'll also give our function a parameter called `axis`. Using this parameter, we'll specify whether the operation should use `window.innerWidth` to return a result for the x axis, or `window.innerHeight` to return a result for the y axis.
+
+``` javascript
+const getMaxCircles = (distance, axis, startDistance)=> {
+ return Math.floor(axis == 'x' ? (window.innerWidth - startDistance) / distance :
+ (window.innerHeight - startDistance) / distance);
+}
+```
+
+## Specifying the grid
+We're now all set up to begin actually generating grids, so let's make one! To keep things neat, let's specify our grid in an object called `myGrid` that contains all the parameters we'll need. Here's what mine looks like:
+``` javascript
+const myGrid = {
+ rowStartX: 20,
+ rowStartY: 20,
+ rowDistX: 20,
+ minDiameter: 5,
+ maxDiameter: 15,
+ rowSpacing: 20,
+ rowCircleQty: function() {return getMaxCircles(this.rowDistX, 'x', this.rowStartX)},
+ numRows: function() {return getMaxCircles(this.rowSpacing, 'y', this.rowStartY)},
+ fillArray: [
+ [100, 50, 255],
+ [100, 100, 255],
+ [100, 150, 255],
+ [100, 200, 255],
+ [100, 250, 255]
+ ]
+}
+```
+You may notice a couple of things:
+* I've taken advantage of the `getMaxCircles()` function we wrote earlier to calculate ideal values for `myGrid.rowCircleQty`, and `myGrid.numRows`.
+* `myGrid.fillArray` is using RGB values. Check the [p5.js documentation](https://p5js.org/reference/#/p5/fill) for other color values you can use.
+
+Feel free to customize `myGrid` to make your ideal circle grid, and call `generateCircleGrid()` to see the result:
+
+``` javascript
+generateCircleGrid(
+ myGrid.rowStartX,
+ myGrid.rowStartY,
+ myGrid.rowDistX,
+ myGrid.minDiameter,
+ myGrid.maxDiameter,
+ myGrid.rowCircleQty(),
+ myGrid.numRows(),
+ myGrid.rowSpacing,
+ myGrid.fillArray
+);
+```
+
+[](../../img/posts/build-an-svg-circle-grid-with-p5js/circle-grid-grid.webp)
+
+## SVG export
+Looking back on our goals, we've accomplished all but one: SVG export. Happily, there's [a library](https://github.com/zenozeng/p5.js-svg) that makes this trivial. All we need to do is link the script in the `` of index.html,
+``` html
+
+```
+add a button in ``,
+``` html
+
+```
+style it in `
+
+
+
+
+
+
+```
+
+## Et voilà
+And we're done! Now you can tweak the parameters and make grids with all sorts of colors and size variations, and even export and edit them in Inkscape!
+[](../../img/posts/build-an-svg-circle-grid-with-p5js/circle-grid-complete.webp)
+If you'd like to make this project even better, maybe consider implementing a GUI to adjust your grid paramaters, or adding some interactivity.
diff --git a/content/blog/fifthpost.md b/content/blog/fifthpost.md
deleted file mode 100644
index b173821..0000000
--- a/content/blog/fifthpost.md
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: This is a fifth post (draft)
-date: 2023-01-23
-draft: true
----
-This is a draft post
diff --git a/content/blog/firstpost.md b/content/blog/firstpost.md
deleted file mode 100644
index 0557716..0000000
--- a/content/blog/firstpost.md
+++ /dev/null
@@ -1,26 +0,0 @@
----
-title: This is my first post.
-description: This is a post on My Blog about agile frameworks.
-date: 2018-05-01
-tags:
- - another tag
----
-Leverage agile frameworks to provide a robust synopsis for high level overviews. Iterative approaches to corporate strategy foster collaborative thinking to further the overall value proposition. Organically grow the holistic world view of disruptive innovation via workplace diversity and empowerment.
-
-Bring to the table win-win survival strategies to ensure proactive domination. At the end of the day, going forward, a new normal that has evolved from generation X is on the runway heading towards a streamlined cloud solution. User generated content in real-time will have multiple touchpoints for offshoring.
-
-## Section Header
-
-Capitalize on low hanging fruit to identify a ballpark value added activity to beta test. Override the digital divide with additional clickthroughs from DevOps. Nanotechnology immersion along the information highway will close the loop on focusing solely on the bottom line.
-
-```diff-js
- // this is a command
- function myCommand() {
-+ let counter = 0;
-- let counter = 1;
- counter++;
- }
-
- // Test with a line break above this line.
- console.log('Test');
-```
diff --git a/content/blog/floss-and-smes.md b/content/blog/floss-and-smes.md
new file mode 100644
index 0000000..f34ce60
--- /dev/null
+++ b/content/blog/floss-and-smes.md
@@ -0,0 +1,28 @@
+---
+title: Free Software is the Future for SMEs and Small Nonprofits
+description: Tech giants aren't meeting the needs of SMEs and nonprofits. Combined with digital privacy concerns, a perfect storm is brewing for increased adoption of free and open source software for these organizations.
+date: 2022-10-28
+tags:
+ - FOSS/FLOSS
+ - Digital Privacy
+synopsis: Tech giants aren't meeting the needs of SMEs and nonprofits. Combined with digital privacy concerns, a perfect storm is brewing for increased adoption of free and open source software for these organizations.
+imageURL: /img/posts/floss-and-smes/pedro-lastra-Nyvq2juw4_o-unsplash.webp
+imageAlt: A stylized illustration of a terminal prompt.
+---
+If you're a cottage industry solopreneur, a cricut hobbyist, or a makerspace regular, you've probably heard of Inkscape. Often dismissed by design professionals as a poor substitute for fully fleshed out design tools or simply "not industry standard," this 19 year old vector graphics powerhouse allows artists, designers, scrapbookers and makers alike to create high quality graphics and illustrations that can be used anywhere, from the browser to printed collateral and laser-etched goods. Inkscape, like many other free and open source software (FOSS) projects, has been taking great strides in recent years to match, if not surpass, commercial alternatives in terms of features, output, and usability. FOSS users have long been privy to a a world of software all but unknown to those who have never ventured from the comfort of Microsoft, Adobe, Alphabet, and Oracle, or the shimmering walled-garden of the Apple ecosystem. It hasn't always been easy, pretty, or even stable, but these days free and open source software projects are more organized, better funded, and more accountable than ever before, and people are starting to take notice.
+
+## FOSS offers a level of flexibility and transparency that proprietary mainstays can't or won't provide.
+As free and open source software becomes increasingly attractive to small businesses and nonprofits due to expanding feature-sets and improved user-interfaces, the principles at the core of its creation, perhaps counterintuitively, render projects such as Inkscape ideal for a business environment. While those unfamiliar with the concept of FOSS projects may interpret "free" to reflect its pricing structure, developers can and do charge for access to their products. Instead, the "F" in FOSS represents the freedom to run the program however you want, to study how it works, to change it, and to redistribute copies. FOSS software, in addition, must also publish its source code publicly. This radically transparent approach, beyond the obvious implication that FOSS software is vastly more flexible than proprietary mainstays, can have a tremendous effect on security and privacy, both key with software present on devices containing sensitive employee information, intellectual property, and credentials. While the dialogue surrounding digital privacy has almost exclusively focused on individual users, as we're now aware of the ability of marketers, campaigns, ([or even John Oliver](https://www.youtube.com/watch?v=wqn3gR1WTcA)) to purchase highly targeted, fine-grained data for any purpose, it's only a matter of time before more organizations begin to consider the implications of the potential for proprietary software to indiscriminately collect employee web-searches, map routes, downloads, and discussions to turn into data-points available for purchase by anyone with the budget, such as competitors, marketers, journalists, or government and regulatory bodies, domestic and abroad.
+
+This is where FOSS starts to make a lot more sense from a privacy perspective; because human-readable source code is generally transformed, or compiled, into a more efficient language that can only be read by computers before software is distributed to users, FOSS software authors publish their human-readable source code publicly, enabling anyone to review it. In contrast, companies behind proprietary software do not publicly publish their source code, making it almost impossible to understand precisely how their software works, or what it's doing at any given time. We already know that just about all big names in tech collect private data; we either shrug our shoulders and make peace with it, or we suffer through innumerable privacy policies, settings, sliders, and toggles, and still itch a little afterwards. But what about the tools we use every day that don't have a privacy policy? What about your picture viewer, your file browser, or even your calculator app? The stringent efforts of even the most militant IT departments to block users from installing unapproved software are moot in the face of the fact that we have no way of truly knowing what even the most fundamental software tools from trusted brands are actually doing on the devices that we use to do our work each day. By enabling public access to its source code, free and *open source* software can see have dozens, hundreds or even thousands of tech-savvy users pointing out security flaws to be fixed, alerting developers to bugs, and raising alarm bells about potential privacy issues.
+
+## Individual users and small organizations can directly influence development of the FOSS tools they use every day.
+The focus on transparency in FOSS software engenders a culture of collaboration all but alien to organizations accustomed to proprietary solutions. Successful projects build communities of developers and other contributors, who are each free to work in their own way. Some contributors are individuals who stop by to implement a feature they wish a project had, while others are teams paid by large enterprises to improve open source projects that form a part of their digital infrastructure. Some individuals simply work on FOSS projects as a hobby, and others, like [Inkscape's Martin Owens](https://www.youtube.com/channel/UCPxxdsRV92DZGE-RcRsw_gw), are freelance developers who collect donations to work on bug fixes and features using donor feedback to prioritize their tasks and steer their work. Martin regularly uploads videos on his [YouTube channel](https://www.youtube.com/channel/UCPxxdsRV92DZGE-RcRsw_gw) and [Patreon](https://www.patreon.com/doctormo) to fill in donors on the latest Inkscape updates and development work, and uses polls to allow them to vote on which features should be prioritized for the next release. Donors can message him directly, for technical support, questions, or suggestions. Developers on Inkscape and other FOSS projects can be reached via public mailing lists and chat channels, and software users often interact directly with them via bug reports and feature requests. This makes each user a potential collaborator in the development of the tools they use.
+
+Only a few weeks ago, I filed [a feature request](https://bugs.kde.org/show_bug.cgi?id=454674) for [Kasts](https://apps.kde.org/kasts/), a desktop app that syncs and plays podcasts. After a discussion with one of the developers, they eventually sent me a link to test the feature, which is now in the latest release. This culture of collaboration represents a unique opportunity for SMEs and nonprofits that may not have the budget for custom enterprise solutions. So long as organizations understand and respect the culture, a reasonable donation budget and a willingness to collaborate can open avenues for smaller organizations to work with developers, freelancers, designers, and others within FOSS projects to work towards better experiences and expanded feature sets. Whether this takes the shape of donating a sum in support of the project, and participating by filing competent bug reports and feature requests, or directly commissioning a developer on the project to design and implement a needed feature, needed funds are usually a far cry away from big-budget proprietary-software customizations, and having the option to even speak to a developer at all is a breath of fresh air when compared to the usual experience dealing with sales representatives and account managers. Of course, commercial users of free and open source software must temper their expectations; as with proprietary software, there are no guarantees that the project will go in the direction you'd like, and FOSS projects have no obligation to provide support or develop suggested features no matter how much you donate.
+
+## Many FOSS projects have long been ready for professional and enterprise use.
+Beyond privacy, security, and collaboration potential, FOSS alternatives are getting better by the day. Many open source projects are being developed at a breakneck pace while receiving major corporate support, and projects strictly manned by volunteers are more organized than ever before. An uptick in donations sees some projects considering diverting a portion of donated funds to outsourcing some of the more arduous development tasks less likely to be quickly tackled by volunteers. While FOSS projects such as GNU/Linux based operating systems and the software written for them have long played a critical role in the world's digital infrastructure, often even serving as the base upon which commercial products are built, free software is no longer resigned to the server room, with consumer products such as Valve's Steam Deck being based on projects such as the Arch Linux desktop operating system and KDE's Plasma desktop environment, a computer graphical user interface that looks good enough to compete with large commercial players like Microsoft's Windows Shell and Apple's Aqua, and flogs both of them when it comes to flexibility and customization. It is not uncommon for free-of-charge FOSS projects such as Inkscape to now boast a feature-set comparable, or as in the case of Inkscape, even exceeding that of their paid competitors, and large communities such as those of GNOME and KDE have developed extensive collections of software that can take the place of hundreds of proprietary software tools at zero cost.
+
+## As organizations begin to see FOSS benefits, big tech is likely to begin losing market share.
+While big names in tech continue to erode user privacy and ownership of their software via expanding data collection and subscription models that see users unable to use a PDF reader without connecting to the internet, knowledge of FOSS projects is becoming less and less of the domain of the hyper tech-literate. Our world has already become one in which feature-rich, fast, and well designed free and open source software can replace most black-box proprietary solutions, and for SMEs and nonprofits in the know, the flexibility, privacy expectations, and price-point makes FOSS an extremely attractive proposition. Tech giants won't lose sluggish enterprise clients any time soon, but the writing is on the wall for the many smaller organizations without the budgets for multi-million dollar IT contracts, unless they do something fast.
diff --git a/content/blog/fourthpost/fourthpost.md b/content/blog/fourthpost/fourthpost.md
deleted file mode 100644
index 8149f7c..0000000
--- a/content/blog/fourthpost/fourthpost.md
+++ /dev/null
@@ -1,16 +0,0 @@
----
-title: This is my fourth post.
-description: This is a post on My Blog about touchpoints and circling wagons.
-date: 2018-09-30
-tags: second tag
----
-Leverage agile frameworks to provide a robust synopsis for high level overviews. Iterative approaches to corporate strategy foster collaborative thinking to further the overall value proposition. Organically grow the holistic world view of disruptive innovation via workplace diversity and empowerment.
-
-Bring to the table win-win survival strategies to ensure proactive domination. At the end of the day, going forward, a new normal that has evolved from generation X is on the runway heading towards a streamlined cloud solution. User generated content in real-time will have multiple touchpoints for offshoring.
-
-{% image "./possum.png", "A possum parent and two possum kids hanging from the iconic red balloon" %}
-
-## Section Header
-
-Capitalize on low hanging fruit to identify a ballpark value added activity to beta test. Override the digital divide with additional clickthroughs from DevOps. Nanotechnology immersion along the information highway will close the loop on focusing solely on the bottom line.
-
diff --git a/content/blog/fourthpost/possum.png b/content/blog/fourthpost/possum.png
deleted file mode 100644
index f332150e73c8054c9287addbbb8c33eedcbd838f..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 130230
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