Compare commits

..

44 Commits

Author SHA1 Message Date
0b9b30f6c2 Blah 2024-08-13 21:57:03 -05:00
e4f4a0ba26 Add masto ID 2024-08-05 09:26:26 -05:00
db56e011eb Add article 2024-08-04 21:02:38 -05:00
54bd9ad9ec Fix typo 2024-08-04 21:02:31 -05:00
3d672ce033 Edit index page 2024-08-04 21:02:11 -05:00
2c93d9199e Styling updates; Add author image to posts
mastodon comments inside cards, added fleuron to indicate end of article
2024-08-04 19:01:05 -05:00
621ad15006 Add more closely cropped author profile pic 2024-08-04 18:58:35 -05:00
345a62ea47 Add article 2024-08-04 18:58:07 -05:00
cdb82fe827 Article correction 2024-07-31 10:48:24 -05:00
7f80d0615c Fix fluid scaling 2024-07-28 23:34:11 -05:00
2913703074 Fix punctuation 2024-07-28 23:33:56 -05:00
777d33a4bb Add article 2024-07-28 23:33:37 -05:00
0cdf1e297b Add masto ID to "poison" 2024-07-16 18:48:48 -05:00
b09aa47d06 Add new post 2024-07-16 18:35:01 -05:00
7b00d49d43 Style blockquotes 2024-07-16 18:34:51 -05:00
62f6268651 Fix mastodon comment author URL 2024-07-16 18:34:31 -05:00
0387793868 update readme 2024-07-09 12:58:50 -05:00
ed1acf8cc8 update readme 2024-07-09 12:33:53 -05:00
bd04a9be19 Fix broken link 2024-07-09 12:30:44 -05:00
77067c7e01 update readme 2024-07-09 12:24:21 -05:00
ccdaea6d80 update readme 2024-07-09 12:19:41 -05:00
836463ad92 Move docs to wiki; update readme 2024-07-09 12:15:30 -05:00
54ec74c6ed Add toot embedding 2024-07-09 11:39:02 -05:00
e55fa73d92 Remove bottom margin from card component 2024-07-09 11:37:17 -05:00
4569060d41 Upgrade 11ty version 2024-07-09 11:36:40 -05:00
a7c7d31552 Update documentation 2024-07-09 11:36:16 -05:00
0536a3aeb7 Update JS to ES modules 2024-07-09 11:36:02 -05:00
a0dc421189 Add article 2024-06-23 20:04:32 -05:00
cf18f89e10 fix typo and add commenting to post 2024-06-14 09:18:17 -05:00
6379ce0041 Add article 2024-06-11 19:40:05 -05:00
07f3be8083 Add post 2024-05-09 00:11:05 -05:00
3de856f413 Add new /now entry 2024-04-13 21:50:15 -05:00
59484d8363 Refactor /now to use built in postslist include 2024-04-13 21:49:58 -05:00
a6bd281946 Add the latest /now entry to index page 2024-04-13 21:49:30 -05:00
049ba826dc Add option to hide author info
Allows use of post layout for /about-feeds, which fixes a layout issue
2024-04-13 21:49:01 -05:00
b1b57c7b6a Update Metadata 2024-04-13 21:47:34 -05:00
bfb31ba036 Fix typo 2024-04-13 19:06:35 -05:00
e0e09bcea1 add a post 2024-04-13 19:03:17 -05:00
8100e05cc3 Update /about 2024-04-13 19:02:23 -05:00
0aee314908 Style <th> 2024-04-13 19:02:10 -05:00
779cce9f9d Fix my HTML and integrate prettier 2024-03-29 14:19:01 -05:00
12baf5df2e Fix header sizes 2024-03-29 12:01:08 -05:00
dfa3989409 Remove cli-tools tag 2024-03-29 12:00:55 -05:00
e3061b9f5b Block AI shit 2024-03-29 12:00:38 -05:00
55 changed files with 1013 additions and 253 deletions

View File

@ -1,17 +1,37 @@
# nathanupchurch.com
My blog, based on the very helpful eleventy-base-blog v8.
# My 11ty Blog
My blog, originally based on the very helpful eleventy-base-blog v8, although it has come a long way from its humble beginnings. For documentation, check [the wiki](https://upchur.ch/gitea/n_u/nathanupchurch.com/wiki).
![](https://upchur.ch/piwigo/i.php?/upload/2023/09/22/20230922131353-32037f24-la.png)
## Features
### Design
* Fluid type and spacing systems for responsive pages with zero breakpoints
* Dark mode
* Graceful but unobtrusive page transitions
* Pretty variable typefaces
* Pretty 401 and 403 error pages
## Documentation
### Fediverse Integration
* Mastodon [toot embedding](https://upchur.ch/gitea/n_u/nathanupchurch.com/wiki/Home#embed-a-toot-from-mastodon-using-the-toot-shortcode)
* [Commenting](https://upchur.ch/gitea/n_u/nathanupchurch.com/wiki/Home#adding-comments-via-mastodon) via Mastodon
### Metadata
Site metadata such as author info, title, etc. lives in _data/metadata.js. Links on the /me page, and default post images are also configured here.
### Indieweb
* [Auto-generated linktree-style page](https://upchur.ch/gitea/n_u/nathanupchurch.com/wiki#me) for the blog owner with support for custom attributes such as: `rel="me"`
* Built in support for [webring links](https://upchur.ch/gitea/n_u/nathanupchurch.com/wiki#webrings)
* Auto-generated, **styled** RSS feeds
* All blog posts
* Each individual tag
* /now page that nicely handles posts tagged with "now"
### How to add a cowsay to a post with the custom nunjucks filter
You can use the `cowsay` filter to output a captioned `<figure>` containing a copy of an output from the cowsay program. Instead of using the usual three backticks, this method is accessible to visually impaired users thanks to the automatic captioning. Here's how to do it:
### Technical
* Reusable web components:
* Card
* Mastodon comment
* Profile picture
* Embedded toot
1. Add a copy of the cowsay output you'd like to display to _data/cowList.js. Be sure and escape any backslashes.
2. Use the filter like this: `{{ cowList.name | cowsay | safe }}`.
### Quality of Life
* Copyright notice, default post image, alt text, and author details defined in `metadata.js`.
* "Read Next" highlighting the previous blog post at the bottom of every post
* robots.txt tells AI scrapers to GTFO
The `safe` filter is necessary so that Eleventy doesn't sanitize our HTML.
### Weird and Wonderful
* [Accessible cowsay output embedding](https://upchur.ch/gitea/n_u/nathanupchurch.com/wiki#add-a-cowsay-to-a-post)

View File

@ -1,4 +1,4 @@
module.exports = {
export default {
onScience: `
_________________________________________
( Once, when the secrets of science were )

View File

@ -1,4 +1,4 @@
module.exports = {
export default {
title: "Nathan Upchurch",
logo: "/img/logo.svg",
url: "https://nathanupchurch.com/",
@ -8,14 +8,14 @@ module.exports = {
name: "Nathan Upchurch",
email: "blog@upchur.ch",
url: "https://nathanupchurch.com/me",
profilePic: "/img/CN20191025_301_Srt_SQUARE.jpg"
profilePic: "/img/CN20191025_301_Srt_SQUARE_crop.jpg"
},
copyrightNotice: "© Nathan Upchurch 2022 - 2024",
defaultPostImageURL: "/img/vasilina-sirotina-1NMPvajSt9Q-unsplash_copy.avif",
defaultPostImageAlt: "The default post image: a close picture of the dark green leaves of a plant.",
mastodonHost: "lounge.town",
mastodonUser: "nathanu",
postlistHeaderText: "Latest Posts",
postlistHeaderText: "Latest posts from the blog:",
socialLinks: [
{
title: "My Blog",

View File

@ -1,5 +1,12 @@
<a href="#skip" class="visually-hidden">Skip to main content</a>
<header>
<a href="/" class="home-link"><img class="logo" src="{{ metadata.logo }}" alt="{{ metadata.title }}"></a>
<a
href="/"
class="home-link">
<img
class="logo"
src="{{ metadata.logo }}"
alt="{{ metadata.title }}">
</a>
{% if not hideNav %}{% include "nav.njk" %}{% endif %}
</header>

View File

@ -2,7 +2,7 @@
layout: layouts/base.njk
showPostListHeader: yep
---
<h1>Welcome to Nathans Website and Blog.</h1>
<p class="nodropcap page-block">Hi there, Im Nathan Upchurch. 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 <a href="/tags">other topics</a> that I find interesting. Learn more <a href="about">about me</a>, see <a href="now">what Ive been up to lately</a>, or have a look at my latest posts below.</p>
<h1>Hi there, friend.</h1>
<p class="nodropcap page-block">My name is Nathan Upchurch. Welcome to my personal website and blog, where I write about <a href="./tags/incense/">incense,</a> <a href="./tags/foss-floss/">free and open source software,</a> design, <a href="./tags/vegan-cooking/">vegan cooking,</a> music, and all sorts of <a href="/tags">other topics</a> that I find interesting. Learn more <a href="about">about me,</a> see <a href="now">what Ive been up to lately,</a> or have a look at my latest blog posts below.</p>
{{ content | safe }}

View File

@ -5,29 +5,42 @@ layout: layouts/base.njk
{%- css %}{% include "public/css/code.css" %}{% endcss %}
<article class="post">
<h1>{{ title }}</h1>
{% if not hideMetadata %}
<div class="post-metadata">
{% if author %}
{% if author.url %}<a href="{{ author.url }}">{% endif %}
<p>{% if author.name %}{{ author.name }}, {% endif %}{% if author.url %}</a>{% endif %}<time datetime="{{ page.date | htmlDateString }}">{{ page.date | readableDate }}</time></p>
{% if author.profilePic %}
<img class="profilePic" src="{{ author.profilePic }}">
{% endif %}
<div class="post-metadata-copy">
<p>{% if author.url %}<a href="{{ author.url }}">{% endif %}
{% if author.name %}{{ author.name }},&nbsp;{% endif %}{% if author.url %}</a>{% endif %}<time datetime="{{ page.date | htmlDateString }}">{{ page.date | readableDate }}</time></p>
{% else %}
{% if metadata.author.url %}<a href="{{ metadata.author.url }}">{% endif %}
<p>{% if metadata.author.name %}{{ metadata.author.name }}, {% endif %}{% if metadata.author.url %}</a>{% endif %}<time datetime="{{ page.date | htmlDateString }}">{{ page.date | readableDate }}</time></p>
{% if metadata.author.profilePic %}
<img class="profilePic" src="{{ metadata.author.profilePic }}">
{% endif %}
<div class="post-metadata-copy">
<p>{% if metadata.author.url %}<a href="{{ metadata.author.url }}">{% endif %}
{% if metadata.author.name %}{{ metadata.author.name }},&nbsp;{% endif %}{% if metadata.author.url %}</a>{% endif %}<time datetime="{{ page.date | htmlDateString }}">{{ page.date | readableDate }}</time></p>
{% endif %}
<ul>
{%- for tag in tags | filterTagList %}
{%- set tagUrl %}/tags/{{ tag | slugify }}/{% endset %}
<li><a href="{{ tagUrl }}" class="post-tag">{{ tag }}&nbsp;</a></li>
{%- endfor %}
</ul>
<ul>
{%- for tag in tags | filterTagList %}
{%- set tagUrl %}/tags/{{ tag | slugify }}/{% endset %}
<li>
<a
href="{{ tagUrl }}"
class="post-tag">
{{ tag }}&nbsp;
</a>
</li>
{%- endfor %}
</ul>
</div>
</div>
{% endif %}
{{ content | safe }}
</article>
{% include "mastodonComments.njk" %}

View File

@ -11,40 +11,24 @@
Reply on Mastodon to comment &#187;
</button>
</a>
</div>
</section>
<template id="comment-template">
<wc-comment
author_name=""
author_url=""
avatar_url=""
comment_content=""
publish_date=""
sharp_corner="">
</wc-comment>
<wc-card>
<wc-comment
author_name=""
author_url=""
avatar_url=""
comment_content=""
publish_date=""
sharp_corner="">
</wc-comment>
</wc-card>
</template>
<script>
const monthMap = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
const dateSuffixAdder = (date) => {
if (date > 9 && date < 20) {
return "th";
} else {
let dateString = date < 10 ? "0" + date : "" + date;
if (dateString[1] < 4 && dateString[1] > 0) {
return dateString[1] == 1 ? "st" :
dateString[1] == 2 ? "nd" :
dateString[1] == 3 ? "rd" : null;
} else {
return "th"
}
}
}
const timeFormatter = (hours, minutes) => {
return `${hours < 12 ? hours : hours - 12}:${minutes < 10 ? "0" : ""}${minutes} ${hours < 12 ? "AM" : "PM"}`
}
<script type="module">
import {dateSuffixAdder, monthMap, timeFormatter} from "../../js/modules/mastodonDateTools.js";
const renderComment = (comment, target, parentIdm) => {
const node = document
@ -56,8 +40,7 @@ const renderComment = (comment, target, parentIdm) => {
const dateTime = `${dateObj.getDate()}${dateSuffixAdder(dateObj.getDate())} of ${monthMap[dateObj.getMonth()]}, ${dateObj.getFullYear()}, at ${timeFormatter(dateObj.getHours(), dateObj.getMinutes())}`;
node.querySelector("wc-comment").setAttribute("author_name", comment.account.display_name);
node.querySelector("wc-comment").setAttribute("author_url",
`${comment.account.acct == "{{ metadata.mastodonUser }}" ? "https://{{ metadata.mastodonHost }}/@{{ metadata.mastodonUser }}" : comment.account.acct}`);
node.querySelector("wc-comment").setAttribute("author_url", comment.url.replace(/\/[0-9]+/, ""));
node.querySelector("wc-comment").setAttribute("avatar_url", comment.account.avatar_static);
node.querySelector("wc-comment").setAttribute("comment_content", comment.content);
node.querySelector("wc-comment").setAttribute("publish_date", dateTime);

View File

@ -1,51 +1,62 @@
{%- if collections.posts %}
{%- set previousPost = collections.posts | getPreviousCollectionItem %}
{%- set nextPost = collections.posts | getNextCollectionItem %}
{%- if nextPost or previousPost %}
<section class="links-nextprev">
<h2>Read Next</h2>
<div class="postlist-item-container">
{%- if previousPost %}
<article class="postlist-item{% if post.url == url %} postlist-item-active{% endif %}">
<a href="{{ previousPost.url }}" class="postlist-link">
<div class="post-image-container">
<img class="post-image" {% if previousPost.data.imageURL %} src="{{ previousPost.data.imageURL }}" alt="{{ previousPost.data.imageAlt }}" {% else %} src="{{ metadata.defaultPostImageURL }}" alt="{{ metadata.defaultPostImageAlt }}"{% endif %}>
</div>
</a>
<div class="post-copy">
<a href="{{ previousPost.url }}" class="postlist-link">
<p>Previous Article:</p>
<h3>
{% if previousPost.data.title %}{{ previousPost.data.title }}{% else %}<code>{{ previousPost.url }}</code>{% endif %}
</h3>
</a>
<time class="postlist-date" datetime="{{ previousPost.date | htmlDateString }}">{{ previousPost.date | readableDate("LLLL yyyy") }}</time>
{% if previousPost.data.synopsis %}<p>{{ previousPost.data.synopsis | truncate(105) | safe }}</p>{% else %}{{ previousPost.content | truncate(105) | safe }}{% endif %}
</div>
</article>
{% if collections.posts %}
{% set previousPost = collections.posts | getPreviousCollectionItem %}
{% set nextPost = collections.posts | getNextCollectionItem %}
{% if nextPost or previousPost %}
<section class="links-nextprev">
<h2>Read Next</h2>
<div class="postlist-item-container">
{% if previousPost %}
<article class="postlist-item{% if post.url == url %} postlist-item-active{% endif %}">
<a href="{{ previousPost.url }}" class="postlist-link">
<div class="post-image-container">
<img class="post-image" {% if previousPost.data.imageURL %} src="{{ previousPost.data.imageURL }}" alt="{{ previousPost.data.imageAlt }}" {% else %} src="{{ metadata.defaultPostImageURL }}" alt="{{ metadata.defaultPostImageAlt }}"{% endif %}>
</div>
</a>
<div class="post-copy">
<a href="{{ previousPost.url }}" class="postlist-link">
<p>Previous Article:</p>
<h3>
{% if previousPost.data.title %}{{ previousPost.data.title }}{% else %}<code>{{ previousPost.url }}</code>{% endif %}
</h3>
</a>
<time class="postlist-date" datetime="{{ previousPost.date | htmlDateString }}">{{ previousPost.date | readableDate("LLLL yyyy") }}</time>
{% if previousPost.data.synopsis %}
<p>{{ previousPost.data.synopsis | truncate(105) | safe }}</p>
{% else %}
<p>{{ previousPost.content | truncate(105) | safe }}</p>
{% endif %}
</div>
</article>
{% if not nextPost %}
</div>
</section>
{% endif %}
{% endif %}
{% if nextPost %}
<article class="postlist-item{% if post.url == url %} postlist-item-active{% endif %}">
<a href="{{ nextPost.url }}" class="postlist-link">
<div class="post-image-container">
<img class="post-image" {% if nextPost.data.imageURL %} src="{{ nextPost.data.imageURL }}" alt="{{ nextPost.data.imageAlt }}" {% else %} src="{{ metadata.defaultPostImageURL }}" alt="{{ metadata.defaultPostImageAlt }}"{% endif %}>
</div>
</a>
<div class="post-copy">
<a href="{{ nextPost.url }}" class="postlist-link">
<p>Next Article:</p>
<h3>
{% if nextPost.data.title %}{{ nextPost.data.title }}{% else %}<code>{{ nextPost.url }}</code>{% endif %}
</h3>
</a>
<time class="postlist-date" datetime="{{ nextPost.date | htmlDateString }}">{{ nextPost.date | readableDate("LLLL yyyy") }}</time>
{% if nextPost.data.synopsis %}
<p>{{ nextPost.data.synopsis | truncate(105) | safe }}</p>
{% else %}
<p>{{ nextPost.content | truncate(105) | safe }}</p>
{% endif %}
</div>
</article>
</div>
</section>
{% endif %}
{%- if nextPost %}
<article class="postlist-item{% if post.url == url %} postlist-item-active{% endif %}">
<a href="{{ nextPost.url }}" class="postlist-link">
<div class="post-image-container">
<img class="post-image" {% if nextPost.data.imageURL %} src="{{ nextPost.data.imageURL }}" alt="{{ nextPost.data.imageAlt }}" {% else %} src="{{ metadata.defaultPostImageURL }}" alt="{{ metadata.defaultPostImageAlt }}"{% endif %}>
</div>
</a>
<div class="post-copy">
<a href="{{ nextPost.url }}" class="postlist-link">
<p>Next Article:</p>
<h3>
{% if nextPost.data.title %}{{ nextPost.data.title }}{% else %}<code>{{ nextPost.url }}</code>{% endif %}
</h3>
</a>
<time class="postlist-date" datetime="{{ nextPost.date | htmlDateString }}">{{ nextPost.date | readableDate("LLLL yyyy") }}</time>
{% if nextPost.data.synopsis %}<p>{{ nextPost.data.synopsis | truncate(105) | safe }}</p>{% else %}{{ nextPost.content | truncate(105) | safe }}{% endif %}
</div>
</div>
</section>
{% endif %}
</div>
{%- endif %}
{%- endif %}
{% endif %}

View File

@ -1,5 +1,6 @@
---
layout: layouts/base.njk
layout: layouts/post.njk
hideMetadata: yep
---
# How to use feeds.
<p><!-- a <p> just to stop the dropcap from happening --></p>

View File

@ -6,17 +6,16 @@ eleventyNavigation:
---
<article>
<h1>About me and this website Ive built.</h1>
<h2>All about Nathan</h2>
<p>Im a prolific vegan home cook, classical trombonist, a <abbr title="Free/Libre Open Source Software">FLOSS</abbr> enthusiast, daily GNU/Linux user and unabashed <a href="https://kde.org/">KDE</a> stan, speaker of subpar elementary Spanish, incense appreciator, writer, electronics hobbyist, designer, programmer, music producer, print lover, and human with too many interests and too little time.
<p>Im a prolific vegan home cook, classical trombonist, a <abbr title="Free/Libre Open Source Software">FLOSS</abbr> enthusiast, daily GNU/Linux user and unabashed <a href="https://kde.org/">KDE</a> stan, speaker of subpar elementary Spanish, incense maker and appreciator, writer, electronics hobbyist, designer, programmer, music producer, print lover, and human with too many interests and too little time.</p>
This is my personal website and blog, a little corner of the internet where I can talk about whatever I like without worrying about maintaining a personal brand, or constraining subject matter to those topics which might help advance my career or establish me as a thought leader. Im here to express myself as a human and have fun writing about topics I enjoy. If youd like to learn more about my professional accomplishments and work, Ill link my professional website here soon.</p>
<p>This is my personal website and blog, a little corner of the internet where I can talk about whatever I like without worrying about maintaining a personal brand, or constraining subject matter to those topics which might help advance my career or establish me as a thought leader. Im here to express myself as a human and have fun writing about topics I enjoy. If youd like to learn more about my professional accomplishments and work, Ill link my professional website here soon.</p>
<h2>About this website</h2>
<p>This website is made with <a href="https://www.11ty.dev/">the 11ty static site generator</a>, free and open source variable typefaces <a href="https://www.gent.media/manrope">Manrope</a> and <a href="https://fraunces.undercase.xyz/">Fraunces</a>, along with plain-old HTML, CSS, and some vanilla JavaScript for the web components that I built to handle comments. I used the handy calculators on <a href="https://utopia.fyi">utopia.fyi</a> to help me implement fluid typography and spacing.
<p>This website is made with <a href="https://www.11ty.dev/">the 11ty static site generator</a>, free and open source variable typefaces <a href="https://fraunces.undercase.xyz/">Fraunces</a> and <a href="https://www.gent.media/manrope">Manrope</a>, along with plain-old HTML, CSS, and some vanilla JavaScript for the web components that I built to handle comments. I used the handy calculators on <a href="https://utopia.fyi">utopia.fyi</a> to help me implement fluid typography and spacing.</p>
I dont collect any of your personal information, full-stop. All webfonts, icons, and images are hosted locally (these things can sometimes be used to <a href="https://www.firstpost.com/world/how-google-uses-fonts-to-track-what-users-do-online-and-sell-data-to-advertisers-12496552.html">track people across the internet</a> otherwise). I use <a href="https://umami.is/">umami</a>, an open source, privacy-respecting analytics tool, to see how many people visit this website.
<p>I dont collect any of your personal information, full-stop. All webfonts, icons, and images are hosted locally (these things can sometimes be used to <a href="https://www.firstpost.com/world/how-google-uses-fonts-to-track-what-users-do-online-and-sell-data-to-advertisers-12496552.html">track people across the internet</a> otherwise). I use <a href="https://umami.is/">umami</a>, an open source, privacy-respecting analytics tool, to see how many people visit this website.</p>
Miss when the internet was fun? Find more interesting personal blogs at <a href="https://blogroll.org">blogroll.org</a>, or <a href="https://ooh.directory/">ooh.directory</a>.</p>
<p>Miss when the internet was fun? Find more interesting personal blogs at <a href="https://blogroll.org">blogroll.org</a>, <a href="https://ooh.directory/">ooh.directory</a>, or surf through the webrings at the bottom of the page.</p>
<h2>Contact Me</h2>
<p>If you would like to say something nice, ask a question, or simply follow me on the fediverse, <a href="../me">heres where you can find me</a>.</p>

View File

@ -0,0 +1,57 @@
---
title: "Grand Dame: A Breakthrough Incense Blend?"
description: "An attempt at a lavender incense stick goes remarkably well thanks to an unusual technique."
date: 2024-07-28
tags:
- Incense
synopsis: "An attempt at a lavender incense stick goes remarkably well thanks to an unusual technique."
imageURL: /img/sending-incense-samples.webp
imageAlt: An uncapped fountain pen on top of a pretty, gold-foiled pad of paper beside some envelopes with stamps featuring coffee drinks on them.
mastodon_id: "112867886475498806"
---
I wrote two letters today, sealing each into a cotton envelope alongside a colorful cardboard straw, taped at both ends, containing two minuscule sticks of incense. I'm very excited about what's in those straws: incense sticks resulting from a blend I've dubbed *Grand Dame.*
---
*A quick note:
You can [see everything I've written on incense here,](../../tags/incense/) or [subscribe to just incense posts via RSS.](../../feeds/incense.xml)*
*Correction: When this article was first published, I wrongly attributed the suggestion that Yi-Xin's "Heart of Lavender" isn't likely to use lavender essential oil to Irene of [rauchfahne.de](https://blog.rauchfahne.de/en/) who has since let me know that it wasn't her who suggested this.*
---
[![An uncapped fountain pen on top of a pretty, gold-foiled pad of paper beside some envelopes with stamps featuring coffee drinks on them.](/img/sending-incense-samples.webp "If you're going to snail-mail, you might as well do it in style.")](/img/sending-incense-samples.webp)
These sticks are interesting for a couple of reasons. First, they make use of ambrette seeds, which are mentioned in places such as [incensemaking.com,](https://incensemaking.com/aromatics/musk-seeds/) but there's precious little information available about people *actually using them* in incense. The sticks also involve an experimental technique that I used to try to achieve a lavender fragrance similar to that in Yi-Xin's *Heart of Lavender.*
## Ambrette
Ambrette seeds, or musk seeds, are used in perfumery as a natural alternative to animal musk. Far be it from me to deprive an innocent creature of any of its organs, no matter how fragrant, I have been curious about this ingredient for some time as a way to imbue incense with a measure of animalic depth and complexity.
One of the factors that makes traditional incense making so difficult is that most plants reek to high heaven when burned unless you very precisely control the ratio of the ingredient and the temperature at which it burns. Knowing that tonka beans are notorious for smelling less than rosy when used in too high a concentration, I treated the ambrette seeds with a similar trepidation. Through experimentation, I've found that ambrette seeds make their presence well known at as little as two percent of a total blend.
Ambrette seed really does need to be a part of a blend. Upon lighting, it's one of the first ingredients you'll notice, and as a stick of *Grand Dame* was burning while I wore a mask during a visit to Dave of [The World Makes Scents](https://theworldmakesscents.com/) in his workshop (a great time that I plan to write about soon - thanks Dave!), the ambrette was one of the few notes that made it through the tight fibers of a KN95. In isolation, the burning musk seeds aren't pretty, but I really think they add something special to the blend as a whole.
## The Experiment
I've been a bit obsessed with Yi-Xin's [*Heart of Lavender*](https://craft-incense.com/products/lavenwood) since I first tried it. You see, creating floral incense is notoriously difficult; burning flowers rarely produce a fragrance that's even remotely pleasant, and when they do, it's still tricky to get the blend right. As Ken of Yi-Xin wrote on the *Heart of Lavender* product page:
>Blending lavender flowers into incense basically makes the scent quite herbaceous and sharp. So it took a lot of tweaking and some special techniques to get correct.
He also hints at one of these special techniques:
>Firstly, the base ingredient is a specially processed Stanford Cedar material that integrated lavender in a very unique way
Whatever Ken is doing to those ingredients, it produces a beautiful lavender stick which somehow circumvents the sharpness he describes altogether. It's practically *juicy* — floral, but fruity and tart like a plum. As an incense maker, how you could know that this is possible and *not* try to do it is beyond me, so I came up with an idea and tested my hypothesis in *Grand Dame.* The best guess I could muster as to how he'd managed to avoid that familiar scent of burning plant material that is usually part and parcel of, well, burning plant material, was that he must have either omitted it entirely or significantly reduced the quantity used. If I recall, someone mentioned to me at one point that *Heart of Lavender* didn't strike them as containing any significant quantity of essential oil, and I had forgotten that hydrosols exist, which left me with the idea that perhaps Ken had used a tincture.
I started out by soaking whole dried lavender flowers in [Pisco,](https://catanpisco.com/) which smelled incredible. I soon did a little reading on tinctures, however, and found that I was going about it all wrong. The proof of the Pisco and the ratio of flowers to Pisco were both too low, and I'd need to wait several weeks to see how my tincture had turned out in any case. At this point, I bought an ounce of lavender tincture to experiment with. I combined the entire bottle with six grams of stunning powdered [Juniperus Virginiana from The World Makes Scents;](https://theworldmakesscents.com/products/premium-super-fine-red-cedar-powder-juniperus-virginiana) after stirring well and letting the mixture sit for twenty-four hours, I removed the lid from the jar and allowed the liquid to evaporate. The result of a quick burn test was thrilling: the trail of cedar produced the beautiful, fruity lavender fragrance that I'd hoped for.
Now that I had some lavender fragranced wood, I decided to make some sticks from it. To the cedar, I added benzoin for sweetness and for its fixative properties, acacia gum to help modulate burn temperature and to strengthen the sticks, cinnamon, borneol, a small amount of powdered lavender, the ambrette seed, and guar gum to bind. In my opinion, the sticks turned out very well.
Weeks later, I reflected on the original purpose of my tincture experiment while taking a look at the last of my *Heart of Lavender* sticks from Yi-Xin. As I did, I realised something: these sticks are *dark.* There had to be a significant amount of lavender flowers in them.
[![A dark stick of "Heart of Lavender" seen through a printer's loupe.](/img/heart-of-lavender.webp "There's no way this doesn't contain a significant amount of lavender flowers.")](/img/heart-of-lavender.webp)
Here is a comparison between *Grand Dame* and *Heart of Lavender*:
[![The two sticks seen through a printer's loupe. Mine is significantly lighter in color.](/img/incense-stick-comparison.webp "Left: Grand Dame; Right: Heart of Lavender. Quite a difference. ")](/img/incense-stick-comparison.webp)
With that, while it produces a lovely stick, I think my tincture idea is out of the window. Knowing that Ken was taught by [Kyarazen,](https://www.kyarazen.com/) who writes on traditional Chinese incense techniques as does his student [Dr. Incense,](https://dr-incense.com/) I wonder whether the cedar and lavender might have been processed by [steaming](https://dr-incense.com/blogs/dr-incense-blog/traditional-processing-of-aloeswood) them together. At any rate, despite my disappointment at failing to discover how Ken of Yi-Xin made his lavender incense so good, I did manage to find a way of achieving a similar result, and I'm keen to hear what some of my fellow incense-heads think providing those samples arrive in good condition. It continues to be an interesting line of enquiry as tinctures are expensive, even when you make them yourself, so I'd be grateful to discover a more frugal alternative. I've also started some more tinctures to play with, one with osmanthus and another using jasmine. I'll let you know how those work out.

View File

@ -1,4 +1,4 @@
module.exports = {
export default {
tags: [
"posts"
],

View File

@ -0,0 +1,41 @@
---
title: "Red Cedar & Frankincense"
description: I make a simple, three-ingredient, red cedar and frankincense batch of incense sticks.
date: 2024-05-08
tags:
- Incense
synopsis: I make a simple, three-ingredient, red cedar and frankincense batch of incense sticks.
imageURL: /img/cedar_frank.webp
imageAlt: A bunch of coreless incense sticks on top of some cedar planks next to a pile of frankincense tears.
mastodon_id: "112409293978326719"
---
I've seen a recurring theme on the internet among (all three of us) incense makers: sometimes you just get tired of relegating [not-quite-combustible](../gourmand-sandalwood-incense-a-perplexing-failure/) sticks to the 'use on the incense heater' pile, or making sticks that *almost* smell nice, but don't quite. After a few knock-backs like this, going back to basics and making something simple really keeps your ego from getting too bruised. That's partially why I decided to make these red cedar and frankincense sticks. In addition, I'm a huge fan of [Yi-Xin Craft Incense's](https://craft-incense.com/) white cedar and frankincense, and I'd also read that resins can really sing when used in surprisingly low quantities, so I was keen to try this out.
[![A bunch of coreless incense sticks on top of some cedar planks next to a pile of frankincense tears. The cedar planks have part og the Whole Foods logo branded on them.](/img/cedar_frank.webp "Yes, dear reader, those are pieces of a Whole Foods cedar grilling plank.")](/img/cedar_frank.webp)
If you know me in meat-space, you'll likely know that I'm an avid classical trombonist. While it is obviously true that [playing Rimsky-Korsakov's *Flight of the Bumblebee* on a tenor trombone](https://inv.tux.pizza/watch?v=dfTHNpOge0Q) isn't easy, sometimes the most difficult pieces are [those that](https://inv.tux.pizza/watch?v=xKCcFxBP2o0) look [quite simple](https://inv.tux.pizza/watch?v=tcbFpgkHNc0) on paper. It's surely a feat of technical prowess to play many short notes in rapid succession, but to play even a single note in a tone quality that people will want to listen to for several seconds at a time takes an entirely different set of skills — also honed over years — and if jazz music and small-town brass bands have taught us anything, it's that technical prowess in a brass player is no guarantee of tone quality.
So it is with simple incense. In a two or three ingredient build, all flaws are laid bare for insufflation and observation. While I'm pleased with this batch overall, there are some problems with these sticks. But first:
## The Build
|Ingredient|Grams|% of Build|
|----------|------|-----------|
|Western Red Cedar|8|58%|
|Hojari Frankincense Resin (Boswellia Sacra)|2.2|16%|
|Joss Powder (Litsea Glutinosa)|3.5|26%|
As I mentioned earlier, I'd read somewhere that using smaller quantities of resins can bring out their best; this held true. At 16%, the Hojari Frankincense really presents well after two weeks of curing. With B. Sacra, you know you've done well when those citrus and eucalyptus notes you're used to on the heater come out in the burn. At the ratios listed above, the cedar and frankincense are pretty well balanced: neither takes precedence over the other. If anything, I would prefer that the frankincense tip the scale ever so slightly in its favor; I might try 17-18% next time.
## Problems
Whoever fooled the world into thinking that [joss powder](https://scents-of-earth.com/joss-powder-litsea-glutinosa-superior-vietnam/) was "near odorless" is either hyposmic, a liar, or a hyposmic liar. It's not just the frankincense that sings in this build, so too does the joss. Admittedly, 26% is rather a large chunk of the total build for joss powder, so I only have myself to blame here.
[![A flat round censer filled with ash. Atop the ash, a shaped trail of incense powder is burning.](/img/incense_seal.webp "A Chinese style incense seal made with unfortunately coarse powder.")](/img/incense_seal.webp)
When you burn a properly executed Chinese style incense seal, the lack of binder leaves you with a very pure fragrance; one of the hallmarks of Yi-Xin's work is the near absence of any detectable binder, which gives the it that clean quality, as though you're burning an incense seal instead of a joss stick. I haven't managed to achieve this with my cedar and frankincense, largely because instead of patiently cutting slivers from my cedar plank and putting them through my hand-crank flour mill, I dumped a big chunk of it into my Vitamix dry container and let 2.2 peak horsepower of blender handle the matter. This resulted in a very fluffy cedar powder which was difficult to bind and even more difficult to extrude. (It's also bad practice in general because when you introduce heat via machine processing you begin to lose aromatics.) I do wonder whether the joss powder could by further reduced by using it in combination with a gum binder, such as tragacanth.
Irene of [Rauchfahne](https://blog.rauchfahne.de/en/) recommends resting your incense dough after hydration, which I also did not do. It seems that [patience](../patience/) does not come naturally to me.
## Conclusion
I'd burn this stuff on purpose. Problems aside, these sticks are plesant, good even, but they are not *great* in the same way as those made in middle-of-nowhere Hawaii by Yi-Xin's [onewheeling artisan](https://www.instagram.com/kencannata/reel/C5hslbrL9tB/). Feel free to give the build a try; get that binder down a bit, grind your cedar sensibly, and you may wind up with something special.

View File

@ -0,0 +1,33 @@
---
title: A Perplexing Failure
description: Failing to make the most delicious batch of incense ever.
date: 2024-04-13
tags:
- Incense
synopsis: My grand designs crumble as I fail to make the most delicious batch of incense ever devised.
imageURL: /img/_DSC0079_copy.avif
imageAlt: A small pile of short smooth brown incense sticks on a piece of MDF.
mastodon_id: "112266582201922869"
---
This January, I had grand visions for a sweet, gourmand batch of incense sticks. I'd start with a creamy base of sandalwood, combine it with plenty of guggul resin for that touch of caramel, a dash of warm cinnamon, and a sprinkling of sweet, vanillic tonka bean; these things were going to smell like dessert, like baking cookies, like your high-school English teacher's classroom when her most cloyingly sweet scented candle had been burning for the past four hours.
Things seemed to be going well while making the sticks; the dough smelled incredible, and extrusion was a dream — long, straight noodles that could be manipulated without breaking came one after another. I didn't sense that something might be wrong until I saw the sticks after they'd dried overnight, when I noticed that they were very smooth, compact, and *hard.* They didn't burn, either, which [isn't necessarily the death-knell](../patience) for a batch of incense sticks, but neither is it a good sign.
[![A small pile of short smooth brown incense sticks on a piece of MDF.](/img/_DSC0079_copy.avif "The sticks in question.")](/img/_DSC0079_copy.avif)
It's now three months since the sticks were extruded; they haven't shown any signs of improvement, and I'm left scratching my head. The ingredient ratios in the build I used were based on those of a successful batch; by all estimations, this batch had everything it needed to combust! It may or may not smell nice, but surely, I thought, the batch will burn! Alas, my hubris was met with disappointment. Here's the build I used:
|Ingredient|Grams|% of Build|
|----------|------|-----------|
|Tonka Bean|0.3|5%|
|Cinnamon|0.75|11%|
|Guggul Resin|1.5|23%|
|Sandalwood|3|46%|
|Joss Powder (Litsea Glutinosa)|1|15%|
My best guess as to why this build didn't work out has to do with the cinnamon. I know that some cinnamon varieties are mucilaginous, producing a mucilage (plant slime), when mixed with water. Knowing that gum binders, such as xanthan gum, can cause combustion issues in incense when used in higher concentrations, I suspect that the combination of 15% joss powder plus another 11% of the mucilaginous cinnamon somehow bound the sticks too tightly, preventing combustion.
[![A tiny MHP30 circuit board heater with a little tin of incense powder on top. The heater is shown beside a mostly used blackwing pencil and a fountain pen; it's barely wider than the length of the blackwing ferrule and eraser.](/img/_DSC0014_copy.avif "This dusty wee MHP30 circuit board heater makes a great warmer for incense powders, woods, and resins. The pencil beside it may give you some idea as to just how small it is.")](/img/_DSC0014_copy.avif)
Hypotheses aside, I may never know why exactly this build failed. It's always a shame when a batch turns out to be a complete flop after you've put so much time into carefully grinding and sifting precious aromatics, then kneading, extruding and drying neat little noodles of incense — waiting weeks or months to see whether your hopes for them have come to fruition. But all is not lost after all: when I break up the sticks into small pieces and put them on my mini ~~circuit board,~~ erm, *incense* heater, the fragrance is everything I had thought it might be. I'll content myself with that as I wait for yesterday's batch of rose and myrrh to cure.

View File

@ -6,7 +6,6 @@ date: 2024-03-18
tags:
- GNU/Linux
- KDE
- CLI Tools
imageURL: /img/sidePanel/sidePanel_copy.avif
imageAlt: A cropped screenshot of my plasma desktop showing a side-panel on the right side of the screen containing the clipboard history widget and the media player widget. On the bottom panel is the Scriptinator plugin, showing a tooltip the following title&#58; "Show Panel," and body text&#58; "Show the hidden right panel."
mastodon_id: "112119633092992081"

View File

@ -0,0 +1,21 @@
---
title: "Incense Review: Kheouns Blend"
description: Reviewing Kheouns Blend by The World Makes Scents.
date: 2024-06-23
tags:
- Incense
- Incense Review
synopsis: Reviewing Kheouns Blend by The World Makes Scents.
imageURL: /img/kheouns-blend-incense-sticks.webp
imageAlt: A partially opened box of incense sticks
mastodon_id: "112668846624633338"
---
There is a reason that much incense on the market makes extensive use of fragrance oils: it's simply easier. As returning readers [will know,](https://nathanupchurch.com/blog/gourmand-sandalwood-incense-a-perplexing-failure/) blending combustible incense made with plain old plants is extraordinarily difficult, even when only using two or three ingredients. [The World Makes Scents](https://theworldmakesscents.com/) is a Chicago-based incense maker that does just that. Their Kheoun's Blend incense sticks are based on a unique blend of plants introduced to the team by Kheoun, [a traditional incense maker based in Cambodia](https://blog.rauchfahne.de/en/2023/07/18/the-world-makes-scents-en/).
[![A partially opened box of incense sticks labelled "Keoun's Blend"](/img/kheouns-blend-incense-sticks.webp "Kheon's Blend incense sticks.")](/img/kheouns-blend-incense-sticks.webp)
The twelve sticks in my order came extremely well packaged, in a sturdy paper-over-board box with with a layer of batting both on top and beneath the sticks to prevent breakage in the post. The back of the box describes the product within as "Incense as it was made for thousands of years before industrialization and greed." I'm all for it. The hand-extruded, coreless sticks are light brown in color, roughly 185mm long, very thick at around 3.5mm, and just a little wiggly. There is a sweet, baking-spice fragrance on the unlit sticks.
I've long felt that you can't get a proper impression of the character of a stick of incense before the first ash has fallen. Often, incense briefly smells quite harsh when initially lit. Interestingly, in that first half-second of lighting, these sticks briefly emit a rather pleasant campfire / wood smoke scent. As the stick begins to burn in earnest, however, I'm met with an almost Tibetan herbaceousness, a stevia-leaf like sweetness, notes of cinnamon, anise, and sage, with occasional wafts of something bright and camphorous.
Overall the fragrance is very pleasant. Subdued baking-spice notes sit alongside a sage-like herbaceousness atop a mellow, ever-present sweetness, which is lifted by a blink-and-you'll-miss-it camphor note. Excellent temperature modulation keeps this blend very fragrant throughout; smoke production is modest for a stick of this size, and the fragrance in the burn is very much like that of the unlit stick. This is a very interesting stick unlike anything I've burned before; absolutely worth experiencing, and a great incense to burn in the living room when you have company.

View File

@ -0,0 +1,37 @@
---
title: "Learning to Love Myrrh: Myrrh & Rose Incense"
description: "I finally figure out how to make myrrh work in a composition."
date: 2024-08-05
tags:
- Incense
synopsis: "I finally figure out how to make myrrh work in a composition."
imageURL: /img/pexels-david-roberts-940521-8323579.webp
imageAlt: A beautiful light-pink dog rose, rosa canina.
mastodon_id: "112909867440319574"
---
Myrrh can be a challenging note. I've seen the resins collected from various members of the Commiphora genus described as everything from loamy, bitter, and mushroomy, to reminiscent of cleaning fluid or a dental clinic; whatever impression you take from the fragrance of myrrh resin, there's no denying that it's unique; there is no mistaking myrrh. While I'm rarely a fan of myrrh alone, or as the predominant note in a sparse composition, I've always felt that there is something compelling about it. Despite its overall unpleasantness, I find heated myrrh resin to produce a dark, mysterious, and somehow sexy fragrance. When balanced well, such as in *Mystic Jade* from Shoyeido's *Magnifiscents* collection, it adds a wonderful, earthy warmth to a composition that's hard to beat.
For some time I've struggled to incorporate myrrh into a stick that I can be proud of; it isn't a resin that you can just drop into a composition with the expectation that it'll work. My experiments with commiphora kua, opoponax, and wightii have all ended in disappointment… until recently.
I've long had an inkling that myrrh would pair well with rose. It's challenging to incorporate flowers into combustible incense; some say it's close to impossible to do without winding up with an incense that smells of acrid burning plant material with, if you're lucky, a touch of whatever flower you've added. Certainly, I have realized that often other methods of incorporating floral fragrances work best. Recently I have discovered, however, that if you start with very good material, and methodically try varying ratios in a series of trail-burning tests, you may wind up surprised by how close a fragrance you can achieve to the fragrance of fresh flowers while minimizing acrid notes. For instance, in my testing, I found that a combination of 30% Rosa Canina and 70% Santalum Spicatum, both very high quality powders given to me by [Dave of *The World Makes Scents*,](../visiting-chicago-incense-maker-dave-of-the-world-makes-scents/) smells absolutely wonderful.
[![A beautiful light-pink dog rose, rosa canina.](/img/pexels-david-roberts-940521-8323579.webp "Rosa Canina in bloom, by [David Roberts on Pexels](https://www.pexels.com/photo/close-up-shot-of-a-dog-rose-in-bloom-8323579/)")](/img/pexels-david-roberts-940521-8323579.webp)
With that knowledge, I composed a stick featuring myrrh, rose, and sandalwood. While the build isn't perfect, I'm already really enjoying the small batch of sticks that I made only a few days ago. The fragrance is gentle and powdery, with a hint of smoke, a soft rose note and that fruitiness that occurs when rose petals are heated. Benzoin lends a subtle sweetness alongside the sandalwood, while the myrrh adds it's unmistakable fragrance and a bittersweet molasses note. The whole ensemble is lifted and brought together by a smidgen of borneol camphor. The myrrh reduces the need for binders, so I've gone with a weak binder, acacia gum, which also helps to firm up and strengthen the extruded sticks once dried.
## The Build
Note that this is a test build that produces less than four grams of dough; you may want to double the amount.
|Ingredient|Grams|% of Build|
|-|-|-|
|Myrrh Resin (Commiphora Kua) |0.2|5.6%|
|Rose Petal (Rosa Canina)|1|27.9%|
|Sandalwood (Santalum Spicatum)|2|55.9%|
|Benzoin Siam|0.14|3.9%|
|Acacia Gum|0.2|5.6%|
|Borneol Camphor|0.04|1.1%|
## Thoughts
I really like this stick, but I do think that it could stand some improvement. Some spices might round out the profile a little, maybe a little clove and cinnamon. It's not the *cleanest* fragrance in the world, likely due to both the myrrh and the high ratio of flowers, but I have been finding it incredibly moreish nonetheless. I hope someone will try to make this and let me know their thoughts!

View File

@ -10,8 +10,10 @@ imageURL: /img/dragons_blood_incense_copy.avif
imageAlt: A small piece of a coreless, Japanese-style incense stick burning in a black cast-iron burner.
mastodon_id: "111732713202024407"
---
Some time ago, maybe a year or so, I extruded a batch of incense sticks from some ingredients I thought might go well together: sandalwood, cinnamon, dragon's blood resin, a touch of Hojari frankincense for acidity, and some tonka bean for sweetness, if I recall correctly. After leaving the sticks to dry overnight, I was disappointed to see that they didn't stay lit; the stick would shrink behind the ember, and it would fizzle out in short order. Even worse, the little scent I was able to detect during the short burn was terrible: acrid and smoky. Dejected, I put the sticks away, returning to attempt to burn a small fragment every few days or so before I lost interest entirely. A few months later, the tube of crooked red incense sticks caught my eye, and I once again attempted to burn a stick. To my surprise, it stayed lit throughout the entire burn. The fragrance had transformed also, from leafy-campfire to a simple, warm, slightly sweet, and medicinal fragrance. While this was enough of an improvement to encourage me to light one every now and then, I remained disappointed that the fragrance was so far from what I'd hoped to achieve. After half-heartedly burning each stick in the little plastic tube that housed them over a period of weeks, the tube disappeared into a basket on the shelf beneath my coffee table amidst a mess of bundled cables and game-controllers, never to be seen again until just a few days ago.
Some time ago, maybe a year or so, I extruded a batch of incense sticks from some ingredients I thought might go well together: sandalwood, cinnamon, dragon's blood resin, a touch of Hojari frankincense for acidity, and some tonka bean for sweetness, if I recall correctly. After leaving the sticks to dry overnight, I was disappointed to see that they didn't stay lit; the stick would shrink behind the ember, and it would fizzle out in short order. Even worse, the little scent I was able to detect during the short burn was terrible: acrid and smoky. Dejected, I put the sticks away, returning to attempt to burn a small fragment every few days or so before I lost interest entirely.
A few months later, the tube of crooked red incense sticks caught my eye, and I once again attempted to burn a stick. To my surprise, it stayed lit throughout the entire burn. The fragrance had transformed also, from leafy-campfire to a simple, warm, slightly sweet, and medicinal fragrance. While this was enough of an improvement to encourage me to light one every now and then, I remained disappointed that the fragrance was so far from what I'd hoped to achieve. After half-heartedly burning each stick in the little plastic tube that housed them over a period of weeks, the tube disappeared into a basket on the shelf beneath my coffee table amidst a mess of bundled cables and game-controllers, never to be seen again until just a few days ago.
[![A small piece of a coreless, Japanese-style incense stick burning in a black cast-iron burner.](/img/dragons_blood_incense_copy.avif "The last fragment.")](/img/dragons_blood_incense_copy.avif)
While rustling around in search of a controller, I discovered the thin plastic tube, noticing two small fragments of incense sliding about as I lifted the tube from the basket. As I lit the first fragment this morning, I was met with a wonderfully clear impression of dragon's blood, uplifted by the bright citrus of Hojari frankincense, on a sweet, warm, woody base; my incense had turned out well after all. Unfortunately, the recipe, written on the tube in dry-erase marker, had long worn off; thinking the batch was a failure, I hadn't recorded it anywhere else. Burning those last two fragments today was bittersweet; all I had needed to do was wait. I'm frustrated about a number of things here, but there is something oddly gratifying about the situation. By failing to record the recipe, I got to experience something rare and unique today. In those peaceful, fragrant moments, I experienced something lovely for the first and last time and I learned a thing or two about patience.
While rustling around in search of a controller, I discovered the thin plastic tube, noticing two small fragments of incense sliding about as I lifted the tube from the basket. As I lit the first fragment this morning, I was met with a wonderfully clear impression of dragon's blood, uplifted by the bright citrus of Hojari frankincense, on a sweet, warm, woody base; my incense had turned out well after all. Unfortunately, the recipe, written on the tube in dry-erase marker, had long worn off; thinking the batch was a failure, I hadn't recorded it anywhere else. Burning those last two fragments today was bittersweet; all I had needed to do was wait. I'm frustrated about a number of things here, but there is something oddly gratifying about the situation. By failing to record the recipe, I got to experience something rare and unique today. In those peaceful, fragrant moments, I experienced something lovely for the first and last time and I learned a thing or two about patience.

26
content/blog/poison.md Normal file
View File

@ -0,0 +1,26 @@
---
title: "Poison"
description: "Reflecting on eating, and cooking, habits in light of Pete Wells' stepping down from his role as Times restaurant critic."
date: 2024-07-16
tags:
- Quick Thoughts
- Restaurants
- Vegan Cooking
synopsis: Reflecting on eating, and cooking, habits in light of Pete Wells' stepping down from his role as Times restaurant critic."
imageURL: /img/pexels-davideibiza-1771809.webp
imageAlt: Amber glass bottles with poison warnings.
mastodon_id: "112798801312124662"
---
I recently happened across the article in which Pete Wells [announces that he will be stepping down](https://www.nytimes.com/2024/07/16/dining/pete-wells-steps-down-food-critic.html?unlocked_article_code=1.7k0.R2zu.sGv5x7hNrfba) from his role as Times' restaurant critic. Health stood tall among the reasons behind the decision:
> My scores were bad across the board; my cholesterol, blood sugar and hypertension were worse than Id expected even in my doomiest moments. The terms pre-diabetes, fatty liver disease and metabolic syndrome were thrown around.
I've been having a similar reckoning. In 2013 I turned vegan. At the time, this meant that you had better either learn to cook or learn to love whatever meager offerings you were lucky enough to find in the miniscule corner of your local grocery store reserved for you and the other crusties: gluten deniers; allergy sufferers; and so on. Rather than endure the pasty, sour blocks of potato starch that then passed for 'vegan cheese', I started to develop my cooking skills in earnest, and not just at home; I would work in kitchens, never as a cook, but as a cocktail bartender and later a barista, both at places upscale enough to warrant cocktail or coffee stations in the kitchen. I learned a lot from those places, especially in the cocktail bar where the chef and I practically stepped on each others toes. From the talented people in that kitchen, I learned what it was to deglaze a pan, how to balance salt, fat, and acid in a dish, and that a dish is over-seasoned when you can *feel* the salt on your tongue. Through these experiences, and through consistent practice at home, I became a very competent home cook.
Using what I've learned in kitchens and from my own practice and research, I can make a Beyond Meat / Impossible style ground beef analogue at home. I can make a competent béchamel sauce with home-made cultured vegan butter, throw together a romesco, red sauce, or salsa verde at a moment's notice, and whip up fresh falafel, tamales, mushroom stroganoff, a Thai green curry, or South Indian sambar on a weeknight without so much as looking at a recipe. All of it poison, I increasingly realize.
Restaurants are places where the preparation of food, necessary to sustain life, meets with a profit motive. In order to retain custom, restaurant dishes are designed with aspirations of meeting the zenith of human tastes, forged thousands of years ago when scraping together sufficient calories of plant and animal matter to see one through the day was no mean feat. If you are among the lucky sliver of the human population that can participate in today's world of plenty, however, restaurant food doesn't only fill those key nutritional silos that drive the most intense of cravings; it utterly overwhelms them, and the consequences from overindulging can be dire.
Learning to cook this way has done me a tremendous disservice. The talented people who I've learned from over the years have inculcated into me, as gospel truth, techniques to create food that delights the palate and utterly destroys the body.
Since giving up smoking, I've learned that the craving never really leaves you entirely. As I glance down at my beautiful little marble pinch-bowl piled high with large white crystals of kosher salt, I wonder whether this craving will never truly leave me also?

View File

@ -0,0 +1,46 @@
---
title: "Switching to GNU/Linux: Mentally"
description: The mindset shift that produces happy users of GNU/Linux and other Free/Libre and Open Source Software.
date: 2024-06-11
tags:
- GNU/Linux
- FOSS/FLOSS
- KDE
synopsis: The mindset shift that produces happy users of GNU/Linux and other Free/Libre and Open Source Software.
imageURL: /img/pexels-ds-stories-9228363_copy.webp
imageAlt: A very cute photo by DS stories on pexels.com of a little pink brain-shaped candle on a light blue background.
mastodon_id: "112615355114722806"
---
[Stallman was right;](https://www.benzinga.com/news/24/06/39219971/edward-snowden-echoes-richard-stallmans-warnings-on-proprietary-software-after-user-says-adode-can-n) in the wake of Microsoft's announcement of its [much-maligned](https://www.wired.com/story/microsoft-recall-off-default-security-concerns/) Recall feature and widespread public backlash to the [terms and conditions](https://www.benzinga.com/top-stories/24/06/39209804/it-is-time-to-cancel-adobe-new-photoshop-terms-conditions-spark-outrage-among-professionals) for Adobe Creative Cloud products, it's clear that trust in big tech and the software it produces is rapidly eroding. Under the circumstances, it's no surprise that Free/Libre and Open Source Software (FLOSS) is seeing an uptick in interest from the public at large. So as ever more average users consider "switching to Linux," it strikes me that while there exist tomes on the technical aspects, there seems to be much less written on the shift in thinking that is part and parcel of every experienced and well-adjusted FLOSS user. So if you're making the switch or know someone who is, here's some advice to make the most of the transition.
[![A rather beautiful picture of a young Richard Stallman playing the recorder to a large pink butterfly perched on some beige computer equipment.](/img/rms.jpg "He was right. [CC BY-NC-ND 3.0](https://creativecommons.org/licenses/by-nc-nd/3.0/)")](/img/rms.jpg)
## Welcome
First of all: welcome to GNU/Linux! You've chosen the operating system [that powers](https://www.vrogue.co/post/linux-is-everywhere-infographic) bullet trains, the world's fastest supercomputers, U.S.A. air traffic control, CERN's Large Hadron Collider, and Google, Amazon, and Microsoft's cloud services, [used by](https://en.wikipedia.org/wiki/List_of_Linux_adopters) NASA, the People's Liberation Army, the Turkish government, whitehouse.gov, the U.S.A. Department of Defense, France's national police force, ministry of agriculture, and parliament, Iceland's public schools, the Dutch Police Internet Research and Investigation Network, Burlington Coat Factory, Peugeot, DreamWorks Animation, the Chicago Mercantile Exchange, the London Stock Exchange, the New York Stock Exchange, and [Stephen Fry.](https://en.wikipedia.org/wiki/List_of_Linux_adopters#Celebrities)
As you've no doubt inferred by now, GNU/Linux users span from your everyday cat-video viewer to large institutions and organizations where operating system reliability and performance mean the difference between life and death. No matter where you are on this spectrum, with a little humility, open-mindedness, and perseverance, I promise that you can find your self every bit as happily at-home with GNU/Linux as you were with whatever OS you've been using up to this point. This may mean giving up a long-trusted piece of software for something new and different, but for many new users the most hard-won battle is a change in mentality.
## You're not a power-user anymore
I've heard it said that the most "computer literate" people often find it especially arduous to adjust to GNU/Linux. I've been there; it's a frightening thing to go from the person family, friends, and neighbors call to help with problems with any device that has so much as an LED on it to feeling like that clueless relative with a dozen toolbars installed on their outdated version of Internet Explorer. The reality is that while you've gotten very good at navigating the operating system that you've been using for the past twenty years, very little of that knowledge is useful in GNU/Linux. This is something you're going to have to accept early on: no matter what distro you choose, it's going to be different to Windows or MacOS in very fundamental ways.
This means that, no matter your mastery of Windows keyboard shortcuts, or how convoluted your [AutoHotkey](https://www.autohotkey.com/) config may be, it's going to take you some time to grasp the basics. Beyond that, the bar to become a GNU/Linux power-user is much, much higher than it is on proprietary operating systems. In case you're feeling intimidated, know that this comes with some serious advantages. GNU/Linux systems come with a practically limitless potential for mastery, efficiency, and customization. In time, you'll be able to customize your GUI to your exact specifications, automate system maintenance, and knock out common tasks with a speed you wouldn't have thought possible on your old OS.
## Embrace the new
Switching to GNU/Linux is, in some ways, much more convenient than switching from, say, MacOS to Windows. Chiefly, most distros can be configured to run a wide range of software built for MacOS, Windows, or Android with minimal fuss. That said, I strongly encourage new users to explore FLOSS alternatives built on and for GNU/Linux. FLOSS projects often get a bad rap among users of proprietary operating systems because while a piece of software may run on these systems, the experience is rarely as good as it is on the system is was designed for: usually, GNU/Linux. FLOSS mainstays such as [LibreOffice,](https://www.libreoffice.org/) [Krita,](https://krita.org/en/) [Inkscape,](https://inkscape.org/) [Scribus,](https://www.scribus.net/) [Kdenlive,](https://kdenlive.org/en/) and [Ardour](https://ardour.org/) are at their best on GNU/Linux in terms of appearance, performance, and features. There are professionals of every stripe who do their work with an exclusively FLOSS toolset, from graphic design to video editing, audio production, data analytics, and more. If they can do it, so can you! Don't let the one piece of proprietary software that just won't work put you off of your new operating system when there's a whole new ecosystem of incredible software to explore.
[![A screenshot of Scribus.](/img/scribus_copy.webp "The latest development version of Scribus running on EndeavourOS. I guarantee you it doesn't look this good on Windows.")](/img/scribus_copy.webp)
New users of FLOSS projects often complain that the user interface or workflow of the tool they're trying is "unintuitive." Occasionally, these complaints hit on an area that genuinely could use some improvement, but more often, new users are simply expressing frustration that the workflow of a FLOSS project is different from what they are used to. These applications are not mere clones of their proprietary counterparts; they are projects in their own right, with unique goals, ideals, features, and workflows. Getting through a work project a little more slowly at first is not necessarily a flaw in the tool, it likely just means that you need a bit more practice. In time, you'll come to learn and appreciate killer features that go above and beyond the capabilities of software produced by even the largest tech companies.
## As a GNU/Linux user, you're part of a community
When you switch to GNU/Linux, you're not a customer any more. FLOSS projects are largely build by communities of volunteers who work on what they find interesting or important for their own reasons. There's no support line to call, no one to complain to if something breaks, and no one is losing anything by you choosing not to use their software. If you need help, or if you want to help make a FLOSS project better, you're going to have to engage with the wider community. Every project has a forum, a Matrix or IRC channel, or some other means of connecting users and developers. If you have a problem you can't solve on your own, these are the places to go to get help. Sign up and make a good faith effort to learn the rules and etiquette of the community, and chances are someone will be more than willing to help you find a solution out of sheer civic-mindedness.
There is likewise a great deal of pleasure and satisfaction to be gained by returning that kindness: by being an active participator in the communities you join, you'll help others overcome the stumbling blocks you once faced and foster connections with others who share your interests. Beyond the community alone, there is something wonderful about using software that you've helped shape; contributing well written bug reports, monetary donations, writing documentation, or testing new releases makes a direct positive impact on the tools you rely on each day. It's one thing to use FLOSS projects for reasons of ethics, privacy, or mere utility, but seeing a page of documentation you've written go live for anyone in the world to learn from, seeing a bug you reported vanish after an update, [a theme you created get added to a game,](https://nathanupchurch.com/blog/new-kmines-themes/) or experiencing your feature request given form in a release *really* draws you in. You're no longer at the mercy of some large tech company who only cares about profit; you're part of a community that cares about people, ideas, and making its software better, more efficient, more usable, and more useful for everyone.
## The FLOSS mindset
To distill what I've said above: Things are going to be different, and you may feel disempowered and frustrated for a while until you catch up again. The solution to this, beyond simple patience, is to embrace the fact that by using FLOSS projects, you become a part of the process of making them. Join the community with respect and humility, allow yourself to receive help and kindness from others, and you'll begin to once again remember how it feels to earn your skills. In time, you'll be the one offering help, you'll dance circles around any Windows power-user, and you'll be using tools that you've helped make better. Again I say: welcome. With these small shifts in your thinking, you're going to be in for a good time.

Binary file not shown.

After

Width:  |  Height:  |  Size: 277 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 462 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 235 KiB

View File

@ -0,0 +1,33 @@
---
title: "Visiting Chicago Incense Maker Dave of The World Makes Scents"
description: "I had the pleasure of meeting Dave at The World Makes Scents studio in Bridgeport, Chicago."
date: 2024-08-04
tags:
- Incense
- Chicago
synopsis: "I had the pleasure of meeting Dave at The World Makes Scents studio in Bridgeport, Chicago."
imageURL: /img/pexels-harris-rigorad-478484242-25261413.webp
imageAlt: The Chicago flag.
mastodon_id: "112906515155787958"
---
Whether due to trauma inflicted by gas-station sticks laden with synthetic patchouli oil or the stigma unfairly landed upon the fragrant sticks by association with generations of teenagers seeking to obscure the olfactory remnants of their smoky intemperance, in the part of the world that I currently occupy, incense remains a niche interest — not only with respect to those who enjoy it; fewer yet ever attempt the art of incense-making. Western incense makers seem to huddle together into whatever dusty corner of the internet they can occupy, often knowing each other by handle and legal name alike, where together they scratch and scrape into one small pile whatever little crumbs of knowledge regarding this ancient craft are to be had in languages written with Latin-script alphabets. You can imagine, then, how thrilled I was to be invited by Dave of [The World Makes Scents](https://theworldmakesscents.com/) to see the studio that he shares with his wife, Raksmey.
The workshop is situated in an arts complex: part gallery, and part studio and event space. The walls are lined with pieces from the artists who let space there; as your footsteps echo across the lacquered wooden floors, you can't help but allow your attention to be arrested every few steps by some piece or another. In particular, I recall several striking pieces not far from The World Makes Scents' small studio featuring large nude figures at the fore of a shallow depth of field, a lenticular effect making the images appear to shift and change as you walk by them.
When we reached the studio a stick from a recent test batch was burning; coated with coarsely ground orange zest, it emitted an impressively clear and sweet note of orange oil. Dave told me the story of how Raksmey learned to make incense from women at a Buddhist temple near her home in Cambodia, how the two met, traveled through Vietnam together, rescued their pet dog from perilous circumstances, and disembarked from a plane in the U.S. right as the pandemic was entering the American collective consciousness. It's not my story to tell, so I'll leave it there, but the tale of how the pair came to be making such lovely incense in Chicago's Bridgeport neighborhood is nothing short of miraculous, and likely the most compelling pandemic hobby success story I've heard.
Since first sampling their incense through [the incense exchange subreddit,](https://www.reddit.com/r/IncenseExchange/) I had been impressed with how clean the fragrances were from their cones. I had chalked this up to the cones' golf-tee shape, which keeps the ember from becoming too large, and consequently, the burn temperature from becoming too high; seeing how the materials were processed, however, showed me how much more there was to the story. As if sourcing high quality fragrant materials wasn't enough of a challenge, processing them when they arrive is fraught.
Incense materials should, ideally, be reduced down to a particle size of 100 microns or less. The fastest methods of grinding introduce heat, which breaks down fragrant oils, and renders resins sticky and impossible to work with. Most small incense makers throughout history have thus resorted to processes such as stone grinding or the even more agonizingly slow filing of fragrant woods. Quietly humming in the background was Dave's solution to this conundrum: an array of ball mills, like giant rock-tumblers designed to carefully mill heat-sensitive materials such as black powder for firearms and pyrotechnics; the machines each consist of a rubber-lined drum atop a pair of motorized rollers that turns the drum continuously. The material to be ground is loaded into the machine alongside a series of stainless-steel balls that collide with material inside the spinning drum to break down everything from dried rose petals to cedar wood into a stunningly fine powder. The process takes hours, sometimes days, but at least it's hands-off. Following this, the ground plant matter is run through a series of increasingly fine sieves stacked atop a machine that shakes them so violently that it will soon be bolted to the floor of the studio. Suitably fine material will be used to produce incense; the rest will undergo the process once more.
The results of this procedure are striking; among the samples I left with was a bag of ground patchouli leaf, the texture of talcum powder, so redolent with its natural oils and aromatics that it almost smelled of fresh mint and myrrh resin. Once ground, ingredients are blended together with a small amount of binder; water is then added to form a dough. If destined to become cones, the dough is loaded into a sort of caulking-gun, which is used to extrude a long sausage which will be cut at regular intervals and shaped by hand into those signature golf-tee cones. To make sticks, the dough is packed into a large hand-cranked extrusion machine, capable of extruding some eight to ten noodles of incense at a time which are collected onto a wooden board before being straightened and transferred to a screen for drying. When the cones or sticks have dried completely, they are packaged by hand, labeled, and sent out to incense appreciators world-over.
Of course, the recipes that result in various fragrant doughs to extrude don't spring from nowhere; research and development is an area for which Dave clearly has a great interest and affinity. A whirlwind in the workshop, he produced innumerable ingredients, from wormwood to various frankincense varieties, sprinkling them atop a burning coal to give an impression of the fragrance of each as it burns. The small space housed many drawers and shelves of powders, tinctures, and oils, experiments both successful and otherwise. Vanilla was present in every form and variety as a part of the development process for an upcoming product, from simple extracts to pastes and a high end powdered variety that smelled rich, complex, and tobacco-like. Boxes of incense samples were produced from makers across the globe, from independent makers to large incense houses; all styles were represented, from Tibetan rope incense to bakhoor.
Very much in-line with the brand's emphasis on transparency, Dave's openness regarding processes and ingredients was impressive in an industry where players keep secrets close to their chests. Further, scaling up incense making into a viable business is no mean feat when you're not willing to compromise on quality. Even the famed Singapore incense maker [Kyara Zen wrote](https://www.kyarazen.com/incense-stick-making-a-walk-through/) of this difficulty:
> The truth is, Ive not been able to scale up production as everythings still very much purely hand made, from converting the raw material into powder, to the ingredient blending, to the extrusion, drying, collection etc.
Outside of large incense houses that use industrial hammer mills to break down whole aromatics, it's a painstaking endeavor to produce even small amounts of incense for personal enjoyment, let alone managing to increase output and reduce labor time such that it's viable to sell the incense you make. There is a reason quick and easy to make "hand dipped" incense is seen so often in stores despite its clear inferiority to its traditionally made, non-synthetic counterpart. What Dave and Raksmey have achieved in such a short time is nothing short of remarkable.
I'm very grateful to Dave for the invitation, for showing me the studio, offering a fascinating insight into The World Makes Scents' incense production methods, and for all of the incredible samples and goodies I left with. It's a wonderful thing to be able to meet with another incense maker and share knowledge and enthusiasm over the topic, and hopefully we'll be able to meet again soon; I'll no doubt have some samples to share myself when that time arrives!

View File

@ -1,3 +1,3 @@
module.exports = {
export default {
eleventyExcludeFromCollections: true
}

View File

@ -4,11 +4,28 @@ eleventyNavigation:
key: Home
order: 1
numberOfLatestPostsToShow: 5
numberOfNowPostsToShow: 1
---
<div class="now">
<h2>What I've been up to:</h2>
{% set postsCount = collections.now | length %}
{% set latestPostsCount = postsCount | min(numberOfNowPostsToShow) %}
{% set postslist = collections.now | head(-1 * numberOfNowPostsToShow) %}
{% set postslistCounter = postsCount %}
{% set showPostListHeader = false %}
{% include "postslist.njk" %}
<a class="link-button" href="/now/">
<button type="button">
See more on the “now” page
</button>
</a>
</div>
{% set postsCount = collections.posts | length %}
{% set latestPostsCount = postsCount | min(numberOfLatestPostsToShow) %}
{% set postslist = collections.posts | head(-1 * numberOfLatestPostsToShow) %}
{% set postslistCounter = postsCount %}
{% set showPostListHeader = true %}
{% include "postslist.njk" %}
{% set morePosts = postsCount - numberOfLatestPostsToShow %}

View File

@ -3,50 +3,20 @@ layout: layouts/base.njk
eleventyNavigation:
key: Now
order: 4
numberOfLatestPostsToShow: 4
---
{% set postsCount = collections.now | length %}
{% set latestPostsCount = postsCount | min(numberOfLatestPostsToShow) %}
{% set postslist = collections.now | head(-1 * numberOfLatestPostsToShow) %}
{% set postslistCounter = postsCount %}
{% set morePosts = postsCount - numberOfLatestPostsToShow %}
<article>
<article class="post">
<h1>Now: Whats Been Going on Lately?</h1>
{% set now = collections.now | last %}
<h2>{{ now.data.title }}</h2>
{{ now.content | safe }}
<p class="metadata">Updated: {{ now.date | readableDate }} |&nbsp;<a href="https://nownownow.com/about">What is a now page?</a></p>
</article>
<p class="metadata">Updated: {{ now.date | readableDate }} |&nbsp;<a href="https://nownownow.com/about">What is a now page?</a></p>
{% set postsCount = collections.now | removeMostRecent | length %}
{% if postsCount > 1 %}
<h2>Previous Entries:</h2>
<section class="postlist">
<div class="postlist-item-container">
{% for post in postslist | reverse %}
{% if post.data.title != now.data.title %}
<article class="postlist-item{% if post.url == url %} postlist-item-active{% endif %}">
<a href="{{ post.url }}" class="postlist-link">
<div class="post-image-container">
<img class="post-image" {% if post.data.imageURL %} src="{{ post.data.imageURL }}" alt="{{ post.data.imageAlt }}" {% else %} src="{{ metadata.defaultPostImageURL }}" alt="{{ metadata.defaultPostImageAlt }}"{% endif %}>
</div>
</a>
<div class="post-copy">
<a href="{{ post.url }}" class="postlist-link">
<h3>
{% if post.data.title %}{{ post.data.title }}{% else %}<code>{{ post.url }}</code>{% endif %}
</h3>
</a>
<time class="postlist-date" datetime="{{ post.date | htmlDateString }}">{{ post.date | readableDate("LLLL yyyy") }}</time>
{% if post.data.synopsis %}<p>{{ post.data.synopsis | truncate(150) | safe }}</p>{% else %}{{ post.content | truncate(150) | safe }}{% endif %}
</div>
</article>
{% endif %}
{% endfor %}
</div>
{% if morePosts > 0 %}
<a href="/tags/now"><p>See {{ morePosts }} more post{% if morePosts != 1 %}s{% endif %}</a>.</p>
{% set postslist = collections.now | removeMostRecent %}
{% set showPostListHeader = false %}
{% include "postslist.njk" %}
{% endif %}
</section>
{% endif %}

View File

@ -1,4 +1,4 @@
module.exports = {
export default {
tags: [
"now"
],

View File

@ -0,0 +1,15 @@
---
title: Touching Grass
description: What I've been up to lately — fresh air, more incense making, and doing more KDE stuff.
synopsis: I go outside, make more incense, contribute to KDE, and eat brownies.
date: 2024-04-13
imageURL: /img/justin-veenema-gf03H-I7C9Y-unsplash_copy.webp
imageAlt: A blue neon sign that reads "Time is precious."
---
For some reason, I just seem to be itching to get outside lately. Perhaps I'm coming out of some sort of hibernation — after all, spring has sprung, the ornamental pear trees are [somewhat unfortunately](https://www.vice.com/en/article/7x4zza/heres-why-the-trees-on-your-street-smell-like-semen) in full bloom, turtles are basking in the sunshine on riverside logs, and I just don't feel right if I haven't fed a duck some frozen peas in a few days. I've been making heavy use of my under-desk treadmill too; walking a few miles while checking my feeds and answering emails is a surprisingly nice thing to do in the morning after breakfast.
But lest my doctor fall and injure himself from shock, I've also been engaging in plenty of activities that *don't* involve sunshine, exercise, and fresh air. Just this morning I broke a freshly-dried batch of incense down into five inch pieces. This time I modified a previously successful build to feature rose and myrrh. While there are many varieties of myrrh, the variety I used predominantly (Commiphora Kua) is pungent, bitter, perfumey, and dignified. I wish I could describe it better, but it's quite a difficult fragrance to relate to much else. It really sings in a blend, and I thought it would play nicely with the classic combination of rose and agarwood. The sticks extruded extremely well, and they burn nicely after one night of drying. I'm going to come back to them in two weeks to see how the fragrance has turned out after they've had time to cure and settle.
I've started to muck-in a bit more with KDE which, if you don't know, is an international community that creates free and open source software. Since [my first contribution](../../blog/new-kmines-themes/) (barring bug reports) several months ago, I've been more active on the KDE forum, participating in the visual design group on Matrix and joining in conversations on KDE's GitLab when design issues arise. I may not know C++, but I have been designing things professionally for over a decade; as a huge fan of KDE and a daily user of their Plasma desktop and many KDE applications, I'm delighted to be helping. I'd also like to point out that KDE is doing some really exciting work; KDE is recommending their [Kirigami framework](https://develop.kde.org/frameworks/kirigami/) for all new KDE applications. Kirigami is a *convergent* UI framework, a framework that allows developers to easily create "beautiful apps that run on computers, phones, TVs and everything in between." KDE also has teams working on [Plasma Bigscreen,](https://plasma-bigscreen.org/) a version of the Plasma desktop for TVs, and [Plasma Mobile,](https://plasma-mobile.org/) for smartphones. *Who else* is doing this? Not only does KDE provide desktop environments for TVs, personal computers, and phones — they've created a framework that allows developers to create applications that work on all of these platforms, without making separate versions. The very same application that works on your desktop can run on your phone. How exciting!
To complete this update, my partner has recently gotten back into baking brownies, so over the past few weeks I've exercised the solemn duty of ensuring that not the least morsel of the several batches they've baked goes to waste, whether they're hazelnut and chocolate chip, walnut, or cookie butter. It's a hard life, this one. Perhaps this might go some way towards an explanation as to where all of my extra energy has come from of late.

View File

@ -6,7 +6,7 @@ date: 2024-02-26
imageURL: /img/pexels-pixabay-277458_copy.webp
imageAlt: A series of clocks on tall black poles in a clearing in front of some trees.
---
I spent about a month working on my blog, while [not blogging on the thing](../blog/up-to-my-eyeballs/), but Im very pleased about the new changes. The biggest new feature as a result of the work is the ability to comment on my posts via Mastodon!
I spent about a month working on my blog, while [not blogging on the thing](https://nathanupchurch.com/blog/up-to-my-eyeballs/), but Im very pleased about the new changes. The biggest new feature as a result of the work is the ability to comment on my posts via Mastodon!
After a failed batch, I went back to basics and made some plain Palo Santo incense that turned out very, very well. I expect Ill write a post about it soon. I also caved and got three varieties from [Yi-Xin Craft Incense](https://craft-incense.com/pages/about-the-artist)s February collection. Not only is his stuff consistently gorgeous, its also great reference incense for those masochists who like to make their own. If you want to know what a *good* stick can be, you cant go wrong with one of Kens.

View File

@ -1,19 +1,22 @@
const { DateTime } = require("luxon");
const markdownIt = require("markdown-it");
const markdownItFootnote = require("markdown-it-footnote");
const markdownItAnchor = require("markdown-it-anchor");
const mdfigcaption = require('markdown-it-image-figures');
const pluginRss = require("@11ty/eleventy-plugin-rss");
const pluginSyntaxHighlight = require("@11ty/eleventy-plugin-syntaxhighlight");
const pluginBundle = require("@11ty/eleventy-plugin-bundle");
const pluginNavigation = require("@11ty/eleventy-navigation");
const { EleventyHtmlBasePlugin } = require("@11ty/eleventy");
import { DateTime } from "luxon";
import { eleventyImageTransformPlugin } from "@11ty/eleventy-img";
import markdownIt from "markdown-it";
import markdownItFootnote from "markdown-it-footnote";
import markdownItAnchor from "markdown-it-anchor";
import mdfigcaption from 'markdown-it-image-figures';
import pluginRss from "@11ty/eleventy-plugin-rss";
import pluginSyntaxHighlight from "@11ty/eleventy-plugin-syntaxhighlight";
import pluginBundle from "@11ty/eleventy-plugin-bundle";
import pluginNavigation from "@11ty/eleventy-navigation";
import prettier from "prettier";
import { EleventyHtmlBasePlugin } from "@11ty/eleventy";
import {dateSuffixAdder, monthMap, timeFormatter} from "./public/js/modules/mastodonDateTools.js";
const figoptions = {
figcaption: true
};
module.exports = function(eleventyConfig) {
export default async function(eleventyConfig) {
// Helper Functions
const multiReplace = (text, replacementTable) => {
@ -22,9 +25,29 @@ module.exports = function(eleventyConfig) {
return newText;
};
// Transforms
eleventyConfig.addTransform("prettier", function (content, outputPath) {
if (outputPath && outputPath.endsWith(".html")) {
return prettier.format(content, {parser: "html", bracketSameLine: true, vueIndentScriptAndStyle: true, singleAttributePerLine: true, htmlWhitespaceSensitivity: "ignore"});
} else {
return content;
}
});
eleventyConfig.addWatchTarget("content/**/*.{svg,webp,png,jpeg}");
// Official plugins
/*
eleventyConfig.addPlugin(eleventyImageTransformPlugin, {
extensions: "html",
formats: ["webp"],
widths: [270,540,810,1080],
defaultAttributes: {
loading: "lazy",
decoding: "async",
},
urlPath: "/img/",
});*/
eleventyConfig.addPlugin(pluginRss);
eleventyConfig.addPlugin(pluginSyntaxHighlight, {
preAttributes: { tabindex: 0 }
@ -44,7 +67,13 @@ module.exports = function(eleventyConfig) {
return DateTime.fromJSDate(dateObj, { zone: 'utc' }).toFormat('yyyy-LL-dd');
});
eleventyConfig.addFilter("removeMostRecent", arr => {
return arr.slice(0, arr.length-1);
});
// Shortcodes
// Cowsay
eleventyConfig.addNunjucksFilter("cowsay", cowText => {
const cowCaptionReplacementTable = [
[`
@ -74,12 +103,39 @@ module.exports = function(eleventyConfig) {
`;
});
// Embed a toot
eleventyConfig.addAsyncShortcode("toot", async function(instance, ID) {
const tootData = await fetch(
`https://${instance}/api/v1/statuses/${ID}`
);
const toot = await tootData.json();
const dateObj = new Date(toot.created_at);
const dateTime = `${dateObj.getDate()}${dateSuffixAdder(dateObj.getDate())} of ${monthMap[dateObj.getMonth()]}, ${dateObj.getFullYear()}, at ${timeFormatter(dateObj.getHours(), dateObj.getMinutes())}`;
return `
<wc-toot
author_name="${toot.account.display_name}"
author_url="${toot.url.replace(/\/[0-9]+/, "")}"
author_username="${toot.account.username}"
avatar_url="${toot.account.avatar_static}"
toot_content="${toot.content}"
toot_url="${toot.url}"
publish_date="${dateTime}"
sharp_corner="">
</wc-toot>
`
});
// Passthrough
eleventyConfig.addPassthroughCopy({ 'public/xsl/*': "/xsl/" });
eleventyConfig.addPassthroughCopy({ 'public/img/*': "/img/" });
eleventyConfig.addPassthroughCopy({ 'public/robots.txt': "/" });
eleventyConfig.addPassthroughCopy({ 'public/js/*': "/js/" });
eleventyConfig.addPassthroughCopy({ 'public/js/webComponents/*': "/js/webComponents" });
eleventyConfig.addPassthroughCopy({ 'public/js/modules/*': "/js/modules" });
// Copying so that basic.xsl can use it
eleventyConfig.addPassthroughCopy({ 'public/css/index.css': "/css/index.css" });
eleventyConfig.addPassthroughCopy({ 'public/css/webfonts/*': "/css/webfonts/" });

View File

@ -2,6 +2,7 @@
"name": "nathanupchurch.com",
"version": "8.0.0",
"description": "The personal website and blog of Nathan Upchurch",
"type": "module",
"scripts": {
"build": "npx @11ty/eleventy",
"build-ghpages": "npx @11ty/eleventy --pathprefix=/eleventy-base-blog/",
@ -28,8 +29,8 @@
},
"homepage": "https://upchur.ch/gitea/n_u/nathanupchurch.com",
"devDependencies": {
"@11ty/eleventy": "^2.0.1",
"@11ty/eleventy-img": "^3.1.0",
"@11ty/eleventy": "3.0.0-alpha.13",
"@11ty/eleventy-img": "5.0.0-beta.10",
"@11ty/eleventy-navigation": "^0.3.5",
"@11ty/eleventy-plugin-bundle": "^1.0.4",
"@11ty/eleventy-plugin-rss": "^1.2.0",
@ -41,6 +42,7 @@
},
"dependencies": {
"markdown-it-footnote": "^3.0.3",
"markdown-it-image-figures": "^2.1.1"
"markdown-it-image-figures": "^2.1.1",
"prettier": "^3.2.5"
}
}

89
public/ai.txt Normal file
View File

@ -0,0 +1,89 @@
# Spawning AI
# Prevent datasets from using the following file types
User-Agent: *
Disallow: *.txt
Disallow: *.pdf
Disallow: *.doc
Disallow: *.docx
Disallow: *.odt
Disallow: *.rtf
Disallow: *.tex
Disallow: *.wks
Disallow: *.wpd
Disallow: *.wps
Disallow: *.html
Disallow: *.bmp
Disallow: *.gif
Disallow: *.ico
Disallow: *.jpeg
Disallow: *.jpg
Disallow: *.png
Disallow: *.svg
Disallow: *.avif
Disallow: *.tif
Disallow: *.tiff
Disallow: *.webp
Disallow: *.aac
Disallow: *.aiff
Disallow: *.amr
Disallow: *.flac
Disallow: *.m4a
Disallow: *.mp3
Disallow: *.oga
Disallow: *.opus
Disallow: *.wav
Disallow: *.wma
Disallow: *.mp4
Disallow: *.webm
Disallow: *.ogg
Disallow: *.avi
Disallow: *.mov
Disallow: *.wmv
Disallow: *.flv
Disallow: *.mkv
Disallow: *.py
Disallow: *.js
Disallow: *.java
Disallow: *.c
Disallow: *.cpp
Disallow: *.cs
Disallow: *.h
Disallow: *.css
Disallow: *.php
Disallow: *.swift
Disallow: *.go
Disallow: *.rb
Disallow: *.pl
Disallow: *.sh
Disallow: *.sql
Disallow: /
Disallow: *
# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@( @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ &@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ .@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@% @@@@@@@@@
# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@
# @@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ *@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
# @@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
# @@@@@@@@@@@( @@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
# @@@@@@@@@@@@ %@@@@@/@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
# @@@@@@@@@@@@ %@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
# @@@@@@@@@@@, @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
# @@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@( %@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
# @@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@
# @@@@@@@@@@@/@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@
# @@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
# @@@@@@@@@@@* @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@, @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
# @@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@ *@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
# @@@@@@@@@@@@ %@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
# @@@@@@@@@@@@ %@@@@& @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
# @@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
# @@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
# @@@@@@@@@@@ .@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@
# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@
# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@* @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ spawning.ai

View File

@ -1,5 +1,4 @@
code[class*="language-"],
pre[class*="language-"] {
code[class*="language-"], pre[class*="language-"] {
color: #f8f8f2;
background: none;
text-shadow: 0 1px rgba(0, 0, 0, 0.3);

View File

@ -18,10 +18,10 @@
--font-variation-default: "opsz" 18, "wght" 310, "SOFT" 40, "WONK" 0;
--font-variation-ui: "wght" 500;
--font-family-monospace: Consolas, Menlo, Monaco, Andale Mono WT, Andale Mono, Lucida Console, Lucida Sans Typewriter, DejaVu Sans Mono, Bitstream Vera Sans Mono, Liberation Mono, Nimbus Mono L, Courier New, Courier, monospace;
--meta-font-family: "Fraunces", serif;
--meta-font-size: var(--step--1);
--meta-font-style: italic;
--meta-font-variation-settings: "opsz" 12, "wght" 310, "SOFT" 40, "WONK" 0;
--ui-letter-spacing: var(--space-3xs);
--meta-font-style: normal;
--ui-letter-spacing: calc(var(--space-3xs) * 0.5);
}
/*
@ -57,45 +57,45 @@
--text-color-tag: var(--contrast-color);
/* Font Size Scaling Tokens - https://utopia.fyi/ */
--step--2: clamp(0.7813rem, 0.7747rem + 0.0326vi, 0.8rem);
--step--1: clamp(0.9375rem, 0.9158rem + 0.1087vi, 1rem);
--step-0: clamp(1.125rem, 1.0815rem + 0.2174vi, 1.25rem);
--step-1: clamp(1.35rem, 1.2761rem + 0.3696vi, 1.5625rem);
--step-2: clamp(1.62rem, 1.5041rem + 0.5793vi, 1.9531rem);
--step-3: clamp(1.944rem, 1.771rem + 0.8651vi, 2.4414rem);
--step-4: clamp(2.3328rem, 2.0827rem + 1.2504vi, 3.0518rem);
--step-5: clamp(2.7994rem, 2.4462rem + 1.7658vi, 3.8147rem);
--step-6: clamp(3.3592rem, 2.8691rem + 2.4507vi, 4.7684rem);
--step-7: clamp(4.0311rem, 3.36rem + 3.3555vi, 5.9605rem);
--step-8: clamp(4.8373rem, 3.9283rem + 4.5448vi, 7.4506rem);
--step--2: clamp(0.8681rem, 0.8163rem + 0.259vw, 0.96rem);
--step--1: clamp(1.0417rem, 0.9525rem + 0.446vw, 1.2rem);
--step-0: clamp(1.25rem, 1.1092rem + 0.7042vw, 1.5rem);
--step-1: clamp(1.5rem, 1.2887rem + 1.0563vw, 1.875rem);
--step-2: clamp(1.8rem, 1.4937rem + 1.5317vw, 2.3438rem);
--step-3: clamp(2.16rem, 1.7264rem + 2.1681vw, 2.9297rem);
--step-4: clamp(2.592rem, 1.9891rem + 3.0144vw, 3.6621rem);
--step-5: clamp(3.1104rem, 2.2838rem + 4.1331vw, 4.5776rem);
--step-6: clamp(3.7325rem, 2.6116rem + 5.6044vw, 5.722rem);
--step-7: clamp(4.479rem, 2.9727rem + 7.5312vw, 7.1526rem);
--step-8: clamp(5.3748rem, 3.3658rem + 10.0449vw, 8.9407rem);
/* Space Scaling Tokens - https://utopia.fyi/ */
--space-3xs: clamp(0.3125rem, 0.3125rem + 0vi, 0.3125rem);
--space-2xs: clamp(0.5625rem, 0.5408rem + 0.1087vi, 0.625rem);
--space-xs: clamp(0.875rem, 0.8533rem + 0.1087vi, 0.9375rem);
--space-s: clamp(1.125rem, 1.0815rem + 0.2174vi, 1.25rem);
--space-m: clamp(1.6875rem, 1.6223rem + 0.3261vi, 1.875rem);
--space-l: clamp(2.25rem, 2.163rem + 0.4348vi, 2.5rem);
--space-xl: clamp(3.375rem, 3.2446rem + 0.6522vi, 3.75rem);
--space-2xl: clamp(4.5rem, 4.3261rem + 0.8696vi, 5rem);
--space-3xl: clamp(6.75rem, 6.4891rem + 1.3043vi, 7.5rem);
--space-3xs: clamp(0.3125rem, 0.2773rem + 0.1761vw, 0.375rem);
--space-2xs: clamp(0.625rem, 0.5546rem + 0.3521vw, 0.75rem);
--space-xs: clamp(0.9375rem, 0.8319rem + 0.5282vw, 1.125rem);
--space-s: clamp(1.25rem, 1.1092rem + 0.7042vw, 1.5rem);
--space-m: clamp(1.875rem, 1.6637rem + 1.0563vw, 2.25rem);
--space-l: clamp(2.5rem, 2.2183rem + 1.4085vw, 3rem);
--space-xl: clamp(3.75rem, 3.3275rem + 2.1127vw, 4.5rem);
--space-2xl: clamp(5rem, 4.4366rem + 2.8169vw, 6rem);
--space-3xl: clamp(7.5rem, 6.6549rem + 4.2254vw, 9rem);
/* One-up pairs - https://utopia.fyi/ */
--space-3xs-2xs: clamp(0.3125rem, 0.2038rem + 0.5435vi, 0.625rem);
--space-2xs-xs: clamp(0.5625rem, 0.4321rem + 0.6522vi, 0.9375rem);
--space-xs-s: clamp(0.875rem, 0.7446rem + 0.6522vi, 1.25rem);
--space-s-m: clamp(1.125rem, 0.8641rem + 1.3043vi, 1.875rem);
--space-m-l: clamp(1.6875rem, 1.4049rem + 1.413vi, 2.5rem);
--space-l-xl: clamp(2.25rem, 1.7283rem + 2.6087vi, 3.75rem);
--space-xl-2xl: clamp(3.375rem, 2.8098rem + 2.8261vi, 5rem);
--space-2xl-3xl: clamp(4.5rem, 3.4565rem + 5.2174vi, 7.5rem);
--space-3xs-2xs: clamp(0.3125rem, 0.066rem + 1.2324vw, 0.75rem);
--space-2xs-xs: clamp(0.625rem, 0.3433rem + 1.4085vw, 1.125rem);
--space-xs-s: clamp(0.9375rem, 0.6206rem + 1.5845vw, 1.5rem);
--space-s-m: clamp(1.25rem, 0.6866rem + 2.8169vw, 2.25rem);
--space-m-l: clamp(1.875rem, 1.2412rem + 3.169vw, 3rem);
--space-l-xl: clamp(2.5rem, 1.3732rem + 5.6338vw, 4.5rem);
--space-xl-2xl: clamp(3.75rem, 2.4824rem + 6.338vw, 6rem);
--space-2xl-3xl: clamp(5rem, 2.7465rem + 11.2676vw, 9rem);
/* Custom pairs - https://utopia.fyi/ */
--space-s-l: clamp(1.125rem, 0.6467rem + 2.3913vi, 2.5rem);
--space-s-l: clamp(1.25rem, 0.2641rem + 4.9296vw, 3rem);
/* Fluid Grid Tokens - https://utopia.fyi/ */
--grid-max-width: 43.75rem;
--grid-gutter: var(--space-s-l, clamp(1.125rem, -0.0329rem + 5.7895vw, 2.5rem));
--grid-max-width: 55.50rem;
--grid-gutter: var(--space-s-s, clamp(1.25rem, 1.1092rem + 0.7042vw, 1.5rem));
--grid-columns: 12;
/* Change <img> SVG color with filter */
@ -122,12 +122,13 @@
/* Web Component Tokens */
--wc-card-background-color: var(--card-color);
--wc-card-border-radius: var(--border-radius);
--wc-card-margin: 0 0 var(--space-s) 0;
--wc-card-box-shadow: var(--box-shadow);
--wc-link-color: var(--text-color);
--wc-link-decoration-color: var(--contrast-color);
--wc-link-decoration-thickness: var(--link-decoration-thickness);
--wc-comment-text-margin: auto auto auto 4rem;
--wc-profile-pic-size: 3rem;
--wc-comment-text-margin: var(--space-xs) 0 0 0;
--wc-profile-pic-size: var(--space-l);
--wc-profile-pic-border-radius: 10rem;
}
@ -169,6 +170,17 @@ html {
font-size: 13px;
overflow-y: scroll;
}
blockquote p {
font-style: italic;
}
blockquote:before {
content: "“";
font-size: 10rem;
margin-left: -4rem;
margin-top: -2rem;
position: fixed;
filter: opacity(.15);
}
body {
animation: var(--slide-in-blurred-bottom);
font-size: var(--step-0);
@ -200,10 +212,19 @@ header, footer, main {
nav {
grid-column: 2 / span 12;
}
.now {
display: grid;
grid-column: 1 / span 12;
padding-bottom: var(--space-xl);
}
section {
display: grid;
grid-column: 1 / span 12;
}
::selection {
background: var(--contrast-color);
color: var(--background-color);
}
.page-block {
grid-column: 1 / span 12;
font-size: var(--step-1);
@ -248,18 +269,19 @@ h1, h2, h3 {
h1 {
font-family: var(--font-family-headline);
font-variation-settings: "opsz" 100, "wght" 500, "SOFT" 10, "WONK" 1;
font-size: var(--step-6);
font-size: var(--step-5);
font-style: normal;
line-height: calc(var(--step-6) * 0.25 + var(--step-6));
line-height: calc(var(--step-5) * 0.25 + var(--step-5));
}
h2 {
font-size: var(--step-3);
font-variation-settings: "opsz" 50, "wght" 300, "SOFT" 60, "WONK" 1;
font-size: var(--step-2);
font-variation-settings: "opsz" 50, "wght" 350, "SOFT" 20, "WONK" 1;
padding-bottom: var(--space-l);
padding-top: var(--space-xl);
}
h3 {
font-size: var(--step-2);
font-size: var(--step-1);
}
.logo {
@ -288,6 +310,11 @@ p, li {
font-size: var(--step-0);
line-height: calc(var(--step-0) * 0.5 + var(--step-0));
}
th {
font-variation-settings: "opsz" 25, "wght" 500, "SOFT" 40, "WONK" 0;
padding-bottom: var(--space-2xs);
text-align: left;
}
figure {
margin: 0;
padding: var(--space-m) 0 var(--space-m) 0;
@ -307,9 +334,8 @@ html.barebones, body.barebones {
}
figcaption {
font-size: var(--meta-font-size);
font-style: var(--meta-font-style);
font-variation-settings: var(--meta-font-variation-settings);
font-size: var(--step--1);
font-style: italic;
padding-top: var(--space-s);
text-align: center;
}
@ -375,20 +401,29 @@ table th {
.continue-discussion button {
margin-top: var(--space-xs);
}
wc-comment::part(author-link) {
wc-comment::part(author-link), wc-toot::part(author-link) {
font-size: var(--step-0);
text-decoration: none;
}
wc-comment::part(main) {
margin-bottom: var(--space-l);
padding: var(--space-m);
}
wc-comment::part(publish-date) {
wc-comment::part(publish-date), wc-toot::part(publish-date) {
font-family: var(--meta-font-family);
font-size: var(--meta-font-size);
font-style: var(--meta-font-style);
font-variation-settings: var(--font-variation-settings);
margin-top: -.25rem;
}
wc-toot::part(main) {
color: white;
font-family: var(--meta-font-family);
font-size: var(--step--1);
}
wc-toot::part(author), wc-toot::part(author-link){
color: white;
font-style: var(--meta-font-style);
font-variation-settings: "wght" 600;
}
/* Code Fences */
pre,
code {
@ -508,9 +543,6 @@ nav ul {
}
/* Posts list */
.postlist h3 {
margin-top: 0;
}
.postlist-item-container {
display: flex;
flex-flow: column nowrap;
@ -544,7 +576,7 @@ nav ul {
.postlist-date,
.postlist-item:before {
color: var(--color-gray-90);
font-size: var(--step--1); /* 13px /16 */
font-size: var(--meta-font-size); /* 13px /16 */
}
.postlist-date {
word-spacing: -0.5px;
@ -554,10 +586,7 @@ nav ul {
padding-right: .5em;
text-decoration: none;
}
.postlist-link h3 {
font-size: var(--step-2);
margin-bottom: 0;
}
.postlist-link p {
background-color: var(--color-gray-90);
border-radius: 100px;
@ -565,7 +594,7 @@ nav ul {
font-family: var(--font-family-ui);
font-size: var(--step--2);
font-variation-settings: var(--font-variation-ui);
letter-spacing: var(--space-3xs);
letter-spacing: var(--ui-letter-spacing);
margin-top: calc(var(--space-3xs) * -1);
padding-left: var(--space-xs);
padding-right: var(--space-xs);
@ -645,15 +674,20 @@ a.post-tag:hover {
align-self: center;
}
/* Article / Post */
.post h2 {
font-size: var(--step-2);
}
/* Post Metadata */
.post-metadata {
display: flex;
flex-flow: row nowrap;
padding: var(--space-m) 0 var(--space-l) 0;
}
.post-metadata-copy {
display: flex;
flex-flow: column nowrap;
justify-content: center;
padding-left: var(--space-s);
}
.post-metadata p, .post-metadata ul, .post-metadata ul li, time, .metadata {
display: flex;
flex-flow: row wrap;
@ -670,6 +704,11 @@ a.post-tag:hover {
padding-left: .15rem;
}
.profilePic:not(.links-container > img.profilePic) {
width: var(--space-xl);
border-radius: 100%;
}
/* Direct Links / Markdown Headers */
a.header-anchor {
font-style: normal;
@ -698,6 +737,12 @@ article.post {
container: article / inline-size;
}
/* Adds fleuron to article end */
article.post > p:not(blockquote > p):last-child:after {
content: "\2766";
display: inline;
font-size: var(--step-1);
}
/* Utilities */
.grid-container {
max-width: var(--grid-max-width);

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 447 KiB

BIN
public/img/cedar_frank.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 231 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 283 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 275 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 163 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

View File

@ -1,3 +1,4 @@
import './webComponents/card.js';
import './webComponents/profilePic.js';
import './webComponents/comment.js';
import './webComponents/toot.js';

View File

@ -0,0 +1,22 @@
const dateSuffixAdder = (date) => {
if (date > 9 && date < 20) {
return "th";
} else {
let dateString = date < 10 ? "0" + date : "" + date;
if (dateString[1] < 4 && dateString[1] > 0) {
return dateString[1] == 1 ? "st" :
dateString[1] == 2 ? "nd" :
dateString[1] == 3 ? "rd" : null;
} else {
return "th"
}
}
}
const monthMap = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
const timeFormatter = (hours, minutes) => {
return `${hours < 12 ? hours : hours - 12}:${minutes < 10 ? "0" : ""}${minutes} ${hours < 12 ? "AM" : "PM"}`
}
export {dateSuffixAdder, monthMap, timeFormatter};

View File

@ -10,7 +10,7 @@ template.innerHTML = `
display: flex;
flex-flow: row nowrap;
justify-content: flex-start;
margin-bottom: 1em;
margin: var(--wc-card-margin);
padding: var(--single-gap) 1.1rem var(--single-gap) 1.1rem;
width: 100%;
}

View File

@ -3,9 +3,9 @@ const template = document.createElement('template');
template.innerHTML = `
<style>
#profilePic {
border-radius: var(--wc-profile-pic-border-radius);
width: var(--wc-profile-pic-size);
height: var(--wc-profile-pic-size);
border-radius: var(--wc-profile-pic-border-radius);
width: var(--wc-profile-pic-size);
height: var(--wc-profile-pic-size);
}
</style>

File diff suppressed because one or more lines are too long

View File

@ -1,23 +1,102 @@
User-agent: CCBot
user-agent: AdsBot-Google
Disallow: /
User-agent: ChatGPT-User
User-agent: Amazonbot
Disallow: /
User-agent: GPTBot
Disallow: /
User-agent: Google-Extended
Disallow: /
User-agent: anthropic-ai
Disallow: /
User-agent: Omgilibot
User-agent: Applebot
Disallow: /
User-agent: Omgili
User-agent: AwarioRssBot
Disallow: /
User-agent: AwarioSmartBot
Disallow: /
User-agent: Bytespider
Disallow: /
User-agent: CCBot
Disallow: /
User-agent: ChatGPT-User
Disallow: /
User-agent: ClaudeBot
Disallow: /
User-agent: Claude-Web
Disallow: /
User-agent: cohere-ai
Disallow: /
User-agent: DataForSeoBot
Disallow: /
User-agent: Diffbot
Disallow: /
User-agent: FacebookBot
Disallow: /
User-agent: Google-Extended
Disallow: /
User-agent: GoogleOther
Disallow: /
User-agent: GPTBot
Disallow: /
User-agent: ImagesiftBot
Disallow: /
User-agent: magpie-crawler
Disallow: /
User-agent: omgili
Disallow: /
User-agent: omgilibot
Disallow: /
User-agent: peer39_crawler
Disallow: /
User-agent: peer39_crawler/1.0
Disallow: /
User-agent: PerplexityBot
Disallow: /
User-agent: YouBot
Disallow: /