<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet href="/theme/xls/feed_stylesheet.xls" type="text/xsl"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>Pearbosc - projects</title><link href="https://pearbosc.com/" rel="alternate"></link><id>https://pearbosc.com/</id><updated>2026-07-22T22:59:02.338163-05:00</updated><subtitle>Hello! I make digital art and blog about stuff I'm into.</subtitle><entry><title>Site Updates: Post categories, GitLab CI/CD</title><link href="https://pearbosc.com/blog/2026/07/18/site-updates-post-categories-gitlab-cicd" rel="alternate"></link><published>2026-07-18T00:00:00-05:00</published><updated>2026-07-22T22:59:02.338163-05:00</updated><author><name>Pear</name></author><id>tag:pearbosc.com,2026-07-18:/blog/2026/07/18/site-updates-post-categories-gitlab-cicd</id><summary type="html">&lt;p&gt;Hello and happy Saturday!! I wanted to share some exciting site
updates.&lt;/p&gt;</summary><content type="html">&lt;p&gt;Hello and happy Saturday!! I wanted to share some exciting site
updates.&lt;/p&gt;
&lt;p&gt;First, I’ve made a new blog category: “projects”! This is a category
for talking about any of my creative projects—including this website!
I’m still not quite sure how I’m going to end up using categories vs
tags on here, but right now I’m trying to use categories for types of
posts I’ll make and tags for topics. For example, I might talk about
comics in a variety of posts, but I will only talk about comics I’m
trying to make under the “projects” category.&lt;/p&gt;
&lt;p&gt;Second, and speaking of categories and tags, I added a fancy new
tag/category filter to my &lt;a href="/blog"&gt;blog page&lt;/a&gt;! Out of the box,
most Pelican themes have separate templates for listing all of your
categories and tags, so the structure is usually like this:&lt;/p&gt;
&lt;div class="sourceCode" id="cb1"&gt;&lt;pre class="sourceCode txt"&gt;&lt;code class="sourceCode default"&gt;&lt;span id="cb1-1"&gt;&lt;a aria-hidden="true" href="#cb1-1" tabindex="-1"&gt;&lt;/a&gt;templates/&lt;/span&gt;
&lt;span id="cb1-2"&gt;&lt;a aria-hidden="true" href="#cb1-2" tabindex="-1"&gt;&lt;/a&gt;    base.html              # My main template (contains most of my actual theme styling)&lt;/span&gt;
&lt;span id="cb1-3"&gt;&lt;a aria-hidden="true" href="#cb1-3" tabindex="-1"&gt;&lt;/a&gt;        ↪blog.html         # Template for viewing all posts (note if you're familiar with Pelican's&lt;/span&gt;
&lt;span id="cb1-4"&gt;&lt;a aria-hidden="true" href="#cb1-4" tabindex="-1"&gt;&lt;/a&gt;                           # default templates: I basically swapped articles.html for blog.html)&lt;/span&gt;
&lt;span id="cb1-5"&gt;&lt;a aria-hidden="true" href="#cb1-5" tabindex="-1"&gt;&lt;/a&gt;        ↪tags.html         # Template for viewing all tags&lt;/span&gt;
&lt;span id="cb1-6"&gt;&lt;a aria-hidden="true" href="#cb1-6" tabindex="-1"&gt;&lt;/a&gt;        ↪tag.html          # Template for viewing all posts under a tag&lt;/span&gt;
&lt;span id="cb1-7"&gt;&lt;a aria-hidden="true" href="#cb1-7" tabindex="-1"&gt;&lt;/a&gt;        ↪categories.html   # Template for viewing all categories&lt;/span&gt;
&lt;span id="cb1-8"&gt;&lt;a aria-hidden="true" href="#cb1-8" tabindex="-1"&gt;&lt;/a&gt;        ↪category.html     # Template for viewing all posts under a category&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;But I didn’t have an intuitive way of navigating to those
&lt;code&gt;categories.html&lt;/code&gt; and &lt;code&gt;tags.html&lt;/code&gt; pages on my
blog, so I decided to remove them completely (this is done by setting
some values in the &lt;a href="https://docs.getpelican.com/en/latest/settings.html"&gt;config&lt;/a&gt;).
Then, I removed &lt;em&gt;everything&lt;/em&gt; from &lt;code&gt;category.html&lt;/code&gt; and
&lt;code&gt;tag.html&lt;/code&gt; and made them &lt;a href="https://jinja.palletsprojects.com/en/stable/templates/#child-template"&gt;extend&lt;/a&gt;
my &lt;code&gt;blog.html&lt;/code&gt; page, so I had this structure instead:&lt;/p&gt;
&lt;div class="sourceCode" id="cb2"&gt;&lt;pre class="sourceCode txt"&gt;&lt;code class="sourceCode default"&gt;&lt;span id="cb2-1"&gt;&lt;a aria-hidden="true" href="#cb2-1" tabindex="-1"&gt;&lt;/a&gt;templates/&lt;/span&gt;
&lt;span id="cb2-2"&gt;&lt;a aria-hidden="true" href="#cb2-2" tabindex="-1"&gt;&lt;/a&gt;    base.html&lt;/span&gt;
&lt;span id="cb2-3"&gt;&lt;a aria-hidden="true" href="#cb2-3" tabindex="-1"&gt;&lt;/a&gt;        ↪blog.html&lt;/span&gt;
&lt;span id="cb2-4"&gt;&lt;a aria-hidden="true" href="#cb2-4" tabindex="-1"&gt;&lt;/a&gt;            ↪tag.html&lt;/span&gt;
&lt;span id="cb2-5"&gt;&lt;a aria-hidden="true" href="#cb2-5" tabindex="-1"&gt;&lt;/a&gt;            ↪category.html&lt;/span&gt;
&lt;span id="cb2-6"&gt;&lt;a aria-hidden="true" href="#cb2-6" tabindex="-1"&gt;&lt;/a&gt;    # No more categories.html or tags.html&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And &lt;code&gt;category.html&lt;/code&gt; and &lt;code&gt;tag.html&lt;/code&gt; now just
consist of &lt;code&gt;{% extends "blog.html" %}&lt;/code&gt;, and that
&lt;code&gt;blog.html&lt;/code&gt; template does all the heavy lifting for listing
the categories/tags. The post filters are hidden in a toggleable section
(which, by the way, is CSS only!!! I’m not allergic to JavaScript, but I
think trying to use only HTML and CSS is a fun challenge) and this
section has some conditional styling to improve the user experience
while browsing tags and categories. For example, when you first visit
the blog page, the filters section will be closed, but if you’re looking
at one of the tag pages (&lt;a href="/blog/tag/meta"&gt;example&lt;/a&gt;) the
section will be open when the page renders, since you had it open when
you selected the tag on the previous page! The tag or category you’re
looking at will also be highlighted in a different color.&lt;/p&gt;
&lt;p&gt;(This code is a little messy ^^’ but I wanted to share)&lt;/p&gt;
&lt;div class="sourceCode" id="cb3"&gt;&lt;pre class="sourceCode html"&gt;&lt;code class="sourceCode html"&gt;&lt;span id="cb3-1"&gt;&lt;a aria-hidden="true" href="#cb3-1" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="dt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kw"&gt;details&lt;/span&gt;&lt;span class="ot"&gt; &lt;/span&gt;&lt;span class="er"&gt;{%&lt;/span&gt;&lt;span class="ot"&gt; if category or tag &lt;/span&gt;&lt;span class="er"&gt;%}&lt;/span&gt;&lt;span class="ot"&gt;open&lt;/span&gt;&lt;span class="er"&gt;{%&lt;/span&gt;&lt;span class="ot"&gt; endif &lt;/span&gt;&lt;span class="er"&gt;%}&lt;/span&gt;&lt;span class="dt"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-2"&gt;&lt;a aria-hidden="true" href="#cb3-2" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kw"&gt;summary&lt;/span&gt;&lt;span class="dt"&gt;&amp;gt;&lt;/span&gt;View post filters&lt;span class="dt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="kw"&gt;summary&lt;/span&gt;&lt;span class="dt"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-3"&gt;&lt;a aria-hidden="true" href="#cb3-3" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb3-4"&gt;&lt;a aria-hidden="true" href="#cb3-4" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kw"&gt;div&lt;/span&gt;&lt;span class="ot"&gt; class&lt;/span&gt;&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"category-label"&lt;/span&gt;&lt;span class="dt"&gt;&amp;gt;&lt;/span&gt;Category&lt;span class="dt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="kw"&gt;div&lt;/span&gt;&lt;span class="dt"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-5"&gt;&lt;a aria-hidden="true" href="#cb3-5" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kw"&gt;div&lt;/span&gt;&lt;span class="ot"&gt; class&lt;/span&gt;&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"category-list"&lt;/span&gt;&lt;span class="dt"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-6"&gt;&lt;a aria-hidden="true" href="#cb3-6" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="dt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kw"&gt;ul&lt;/span&gt;&lt;span class="dt"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-7"&gt;&lt;a aria-hidden="true" href="#cb3-7" tabindex="-1"&gt;&lt;/a&gt;        {% for category_item, articles in categories|sort %}&lt;/span&gt;
&lt;span id="cb3-8"&gt;&lt;a aria-hidden="true" href="#cb3-8" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="dt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kw"&gt;li&lt;/span&gt;&lt;span class="dt"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="kw"&gt;a&lt;/span&gt;&lt;span class="ot"&gt; &lt;/span&gt;&lt;span class="er"&gt;{%&lt;/span&gt;&lt;span class="ot"&gt; if category_item&lt;/span&gt;&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="er"&gt;=&lt;/span&gt;&lt;span class="st"&gt;category&lt;/span&gt;&lt;span class="ot"&gt; &lt;/span&gt;&lt;span class="er"&gt;%}&lt;/span&gt;&lt;span class="ot"&gt;class&lt;/span&gt;&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"selected"&lt;/span&gt;&lt;span class="er"&gt;{%&lt;/span&gt;&lt;span class="ot"&gt; endif &lt;/span&gt;&lt;span class="er"&gt;%}&lt;/span&gt;&lt;span class="ot"&gt; href&lt;/span&gt;&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"{{ SITEURL }}/{% if category_item==category %}blog{% else %}{{ category_item.url }}{% endif %}"&lt;/span&gt;&lt;span class="dt"&gt;&amp;gt;&lt;/span&gt;{{ category_item|lower }}&lt;span class="dt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="kw"&gt;a&lt;/span&gt;&lt;span class="dt"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="kw"&gt;li&lt;/span&gt;&lt;span class="dt"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-9"&gt;&lt;a aria-hidden="true" href="#cb3-9" tabindex="-1"&gt;&lt;/a&gt;        {% endfor %}&lt;/span&gt;
&lt;span id="cb3-10"&gt;&lt;a aria-hidden="true" href="#cb3-10" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="dt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="kw"&gt;ul&lt;/span&gt;&lt;span class="dt"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-11"&gt;&lt;a aria-hidden="true" href="#cb3-11" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="kw"&gt;div&lt;/span&gt;&lt;span class="dt"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-12"&gt;&lt;a aria-hidden="true" href="#cb3-12" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb3-13"&gt;&lt;a aria-hidden="true" href="#cb3-13" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kw"&gt;div&lt;/span&gt;&lt;span class="ot"&gt; class&lt;/span&gt;&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"tag-label"&lt;/span&gt;&lt;span class="dt"&gt;&amp;gt;&lt;/span&gt;Tag&lt;span class="dt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="kw"&gt;div&lt;/span&gt;&lt;span class="dt"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-14"&gt;&lt;a aria-hidden="true" href="#cb3-14" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kw"&gt;div&lt;/span&gt;&lt;span class="ot"&gt; class&lt;/span&gt;&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"tag-list"&lt;/span&gt;&lt;span class="dt"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-15"&gt;&lt;a aria-hidden="true" href="#cb3-15" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="dt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kw"&gt;ul&lt;/span&gt;&lt;span class="dt"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-16"&gt;&lt;a aria-hidden="true" href="#cb3-16" tabindex="-1"&gt;&lt;/a&gt;        {% for tag_item, articles in tags|sort %}&lt;/span&gt;
&lt;span id="cb3-17"&gt;&lt;a aria-hidden="true" href="#cb3-17" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="dt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kw"&gt;li&lt;/span&gt;&lt;span class="dt"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="kw"&gt;a&lt;/span&gt;&lt;span class="ot"&gt; &lt;/span&gt;&lt;span class="er"&gt;{%&lt;/span&gt;&lt;span class="ot"&gt; if tag_item&lt;/span&gt;&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="er"&gt;=&lt;/span&gt;&lt;span class="st"&gt;tag&lt;/span&gt;&lt;span class="ot"&gt; &lt;/span&gt;&lt;span class="er"&gt;%}&lt;/span&gt;&lt;span class="ot"&gt;class&lt;/span&gt;&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"selected"&lt;/span&gt;&lt;span class="er"&gt;{%&lt;/span&gt;&lt;span class="ot"&gt; endif &lt;/span&gt;&lt;span class="er"&gt;%}&lt;/span&gt;&lt;span class="ot"&gt; href&lt;/span&gt;&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"{{ SITEURL }}/{% if tag_item==tag %}blog{% else %}{{ tag_item.url }}{% endif %}"&lt;/span&gt;&lt;span class="dt"&gt;&amp;gt;&lt;/span&gt;{{ tag_item|lower }}&lt;span class="dt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="kw"&gt;a&lt;/span&gt;&lt;span class="dt"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="kw"&gt;li&lt;/span&gt;&lt;span class="dt"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-18"&gt;&lt;a aria-hidden="true" href="#cb3-18" tabindex="-1"&gt;&lt;/a&gt;        {% endfor %}&lt;/span&gt;
&lt;span id="cb3-19"&gt;&lt;a aria-hidden="true" href="#cb3-19" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="dt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="kw"&gt;ul&lt;/span&gt;&lt;span class="dt"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-20"&gt;&lt;a aria-hidden="true" href="#cb3-20" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="kw"&gt;div&lt;/span&gt;&lt;span class="dt"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb3-21"&gt;&lt;a aria-hidden="true" href="#cb3-21" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="dt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="kw"&gt;details&lt;/span&gt;&lt;span class="dt"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;img alt="A screenshot of the blog page demoing the feature described above" src="/images/articles/example-filter.png"/&gt;&lt;br/&gt;
&lt;/p&gt;
&lt;p&gt;There are some minor things I need to fix, but I’m really happy with
how it turned out!!&lt;/p&gt;
&lt;p&gt;And last but not least, I can now update this site via &lt;a href="https://docs.gitlab.com/ci/"&gt;GitLab CI/CD&lt;/a&gt;!!! This is kinda
overkill, but I thought it would be fun to learn and it’s free. This is
my &lt;code&gt;.gitlab-ci.yml&lt;/code&gt; file:&lt;/p&gt;
&lt;div class="sourceCode" id="cb4"&gt;&lt;pre class="sourceCode yml"&gt;&lt;code class="sourceCode yaml"&gt;&lt;span id="cb4-1"&gt;&lt;a aria-hidden="true" href="#cb4-1" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="fu"&gt;variables&lt;/span&gt;&lt;span class="kw"&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-2"&gt;&lt;a aria-hidden="true" href="#cb4-2" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;  # https://docs.astral.sh/uv/guides/integration/gitlab/&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-3"&gt;&lt;a aria-hidden="true" href="#cb4-3" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="at"&gt;  &lt;/span&gt;&lt;span class="fu"&gt;UV_VERSION&lt;/span&gt;&lt;span class="kw"&gt;:&lt;/span&gt;&lt;span class="at"&gt; &lt;/span&gt;&lt;span class="st"&gt;"0.11.29"&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-4"&gt;&lt;a aria-hidden="true" href="#cb4-4" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="at"&gt;  &lt;/span&gt;&lt;span class="fu"&gt;PYTHON_VERSION&lt;/span&gt;&lt;span class="kw"&gt;:&lt;/span&gt;&lt;span class="at"&gt; &lt;/span&gt;&lt;span class="st"&gt;"3.12"&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-5"&gt;&lt;a aria-hidden="true" href="#cb4-5" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="at"&gt;  &lt;/span&gt;&lt;span class="fu"&gt;BASE_LAYER&lt;/span&gt;&lt;span class="kw"&gt;:&lt;/span&gt;&lt;span class="at"&gt; trixie&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-6"&gt;&lt;a aria-hidden="true" href="#cb4-6" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;  # GitLab CI creates a separate mountpoint for the build directory,&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-7"&gt;&lt;a aria-hidden="true" href="#cb4-7" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;  # so we need to copy instead of using hard links.&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-8"&gt;&lt;a aria-hidden="true" href="#cb4-8" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="at"&gt;  &lt;/span&gt;&lt;span class="fu"&gt;UV_LINK_MODE&lt;/span&gt;&lt;span class="kw"&gt;:&lt;/span&gt;&lt;span class="at"&gt; copy&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-9"&gt;&lt;a aria-hidden="true" href="#cb4-9" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb4-10"&gt;&lt;a aria-hidden="true" href="#cb4-10" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="fu"&gt;build-site&lt;/span&gt;&lt;span class="kw"&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-11"&gt;&lt;a aria-hidden="true" href="#cb4-11" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="at"&gt;  &lt;/span&gt;&lt;span class="fu"&gt;stage&lt;/span&gt;&lt;span class="kw"&gt;:&lt;/span&gt;&lt;span class="at"&gt; build&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-12"&gt;&lt;a aria-hidden="true" href="#cb4-12" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="at"&gt;  &lt;/span&gt;&lt;span class="fu"&gt;image&lt;/span&gt;&lt;span class="kw"&gt;:&lt;/span&gt;&lt;span class="at"&gt; ghcr.io/astral-sh/uv:$UV_VERSION-python$PYTHON_VERSION-$BASE_LAYER&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-13"&gt;&lt;a aria-hidden="true" href="#cb4-13" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="at"&gt;  &lt;/span&gt;&lt;span class="fu"&gt;before_script&lt;/span&gt;&lt;span class="kw"&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-14"&gt;&lt;a aria-hidden="true" href="#cb4-14" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="at"&gt;    &lt;/span&gt;&lt;span class="kw"&gt;-&lt;/span&gt;&lt;span class="at"&gt; apt-get update -y&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-15"&gt;&lt;a aria-hidden="true" href="#cb4-15" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="at"&gt;    &lt;/span&gt;&lt;span class="kw"&gt;-&lt;/span&gt;&lt;span class="at"&gt; apt-get install pandoc -y&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-16"&gt;&lt;a aria-hidden="true" href="#cb4-16" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="at"&gt;    &lt;/span&gt;&lt;span class="kw"&gt;-&lt;/span&gt;&lt;span class="at"&gt; pandoc --version&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-17"&gt;&lt;a aria-hidden="true" href="#cb4-17" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="at"&gt;    &lt;/span&gt;&lt;span class="kw"&gt;-&lt;/span&gt;&lt;span class="at"&gt; uv sync&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-18"&gt;&lt;a aria-hidden="true" href="#cb4-18" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="at"&gt;  &lt;/span&gt;&lt;span class="fu"&gt;script&lt;/span&gt;&lt;span class="kw"&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-19"&gt;&lt;a aria-hidden="true" href="#cb4-19" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="at"&gt;    &lt;/span&gt;&lt;span class="kw"&gt;-&lt;/span&gt;&lt;span class="at"&gt; echo "Building the $CI_COMMIT_SHORT_SHA commit SHA (started $CI_JOB_STARTED_AT)."&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-20"&gt;&lt;a aria-hidden="true" href="#cb4-20" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="at"&gt;    &lt;/span&gt;&lt;span class="kw"&gt;-&lt;/span&gt;&lt;span class="at"&gt; uv run pelican -s publishconf.py&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-21"&gt;&lt;a aria-hidden="true" href="#cb4-21" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="at"&gt;    &lt;/span&gt;&lt;span class="kw"&gt;-&lt;/span&gt;&lt;span class="at"&gt; find output -type f -name "*.html" -exec sed -i 's/—/&amp;lt;span class="emdash"&amp;gt;—&amp;lt;\/span&amp;gt;/g' {} \;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-22"&gt;&lt;a aria-hidden="true" href="#cb4-22" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="at"&gt;  &lt;/span&gt;&lt;span class="fu"&gt;artifacts&lt;/span&gt;&lt;span class="kw"&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-23"&gt;&lt;a aria-hidden="true" href="#cb4-23" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="at"&gt;    &lt;/span&gt;&lt;span class="fu"&gt;paths&lt;/span&gt;&lt;span class="kw"&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-24"&gt;&lt;a aria-hidden="true" href="#cb4-24" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="at"&gt;      &lt;/span&gt;&lt;span class="kw"&gt;-&lt;/span&gt;&lt;span class="at"&gt; output/&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-25"&gt;&lt;a aria-hidden="true" href="#cb4-25" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb4-26"&gt;&lt;a aria-hidden="true" href="#cb4-26" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="fu"&gt;publish-to-neocities&lt;/span&gt;&lt;span class="kw"&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-27"&gt;&lt;a aria-hidden="true" href="#cb4-27" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="at"&gt;  &lt;/span&gt;&lt;span class="fu"&gt;stage&lt;/span&gt;&lt;span class="kw"&gt;:&lt;/span&gt;&lt;span class="at"&gt; deploy&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-28"&gt;&lt;a aria-hidden="true" href="#cb4-28" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="at"&gt;  &lt;/span&gt;&lt;span class="fu"&gt;rules&lt;/span&gt;&lt;span class="kw"&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-29"&gt;&lt;a aria-hidden="true" href="#cb4-29" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="at"&gt;    &lt;/span&gt;&lt;span class="kw"&gt;-&lt;/span&gt;&lt;span class="at"&gt; &lt;/span&gt;&lt;span class="fu"&gt;if&lt;/span&gt;&lt;span class="kw"&gt;:&lt;/span&gt;&lt;span class="at"&gt; $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-30"&gt;&lt;a aria-hidden="true" href="#cb4-30" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="at"&gt;  &lt;/span&gt;&lt;span class="fu"&gt;before_script&lt;/span&gt;&lt;span class="kw"&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-31"&gt;&lt;a aria-hidden="true" href="#cb4-31" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="at"&gt;    &lt;/span&gt;&lt;span class="kw"&gt;-&lt;/span&gt;&lt;span class="at"&gt; gem install neocities&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-32"&gt;&lt;a aria-hidden="true" href="#cb4-32" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="at"&gt;  &lt;/span&gt;&lt;span class="fu"&gt;script&lt;/span&gt;&lt;span class="kw"&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-33"&gt;&lt;a aria-hidden="true" href="#cb4-33" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="at"&gt;    &lt;/span&gt;&lt;span class="kw"&gt;-&lt;/span&gt;&lt;span class="at"&gt; echo "Deploying the $CI_COMMIT_SHORT_SHA commit SHA (started $CI_JOB_STARTED_AT)."&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-34"&gt;&lt;a aria-hidden="true" href="#cb4-34" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="at"&gt;    &lt;/span&gt;&lt;span class="kw"&gt;-&lt;/span&gt;&lt;span class="at"&gt; neocities push output&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-35"&gt;&lt;a aria-hidden="true" href="#cb4-35" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="at"&gt;  &lt;/span&gt;&lt;span class="fu"&gt;environment&lt;/span&gt;&lt;span class="kw"&gt;:&lt;/span&gt;&lt;span class="at"&gt; production&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;build-site&lt;/code&gt; uses &lt;a href="https://docs.astral.sh/uv/"&gt;uv&lt;/a&gt; to install the dependencies and
generate the site (this stage also has to install Pandoc for converting
my Markdown files to HTML). The generated &lt;code&gt;output/&lt;/code&gt; directory
is carried over to the &lt;code&gt;publish-to-neocities&lt;/code&gt; stage, which
just uses the regular &lt;a href="https://neocities.org/cli"&gt;Neocities
CLI&lt;/a&gt; to publish to Neocities! This stage only runs on my
&lt;code&gt;main&lt;/code&gt; branch, so if I’m experimenting with changes on other
Git branches, those changes won’t be publishes to Neocities if they’re
accidentally pushed. To use the Neocities CLI in your pipeline, you’ll
want to add your Neocities API key
(&lt;code&gt;/settings/$YOUR_SITE_NAME#api_key&lt;/code&gt; on the Neocities
website) to your project variables under the key
&lt;code&gt;NEOCITIES_API_KEY&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;(Quick sidebar on the
&lt;code&gt;find output -type f -name "*.html" -exec sed -i 's/—/&amp;lt;span class="emdash"&amp;gt;—&amp;lt;\/span&amp;gt;/g' {} \;&lt;/code&gt;
script in that file: I use this to wrap &lt;em&gt;every&lt;/em&gt; em dash on my
site with a span element that changes it to a different font. I do this
because I hate the way em dashes look in a monospace font lmao. It’s
kind of silly but it works! And look—here’s one now—and another one—and
another one)&lt;/p&gt;
&lt;p&gt;And that’s all for now!! I’m running late for something so I gotta
end this post immediately BYE&lt;/p&gt;
&lt;p&gt;(EDIT: Okay I take back GitLab CI/CD being overkill because I just
realized I can now make changes to my website FROM MY PHONE, which is
how I made this edit. It’s a little clunky so I won’t use it for major
updates, but I can use it for quick updates or corrections when I’m away
from my desktop PC. Cool!!)&lt;/p&gt;</content><category term="projects"></category><category term="meta"></category><category term="tech"></category></entry></feed>