Add new post - 2026-01-12
This commit is contained in:
parent
dc4a5654ab
commit
c05e54f009
|
|
@ -1,147 +1,146 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en" class="bg-base-bg">
|
<html lang="en" class="bg-base-bg">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<meta name="description" content="">
|
<meta name="description" content="">
|
||||||
<meta property="og:title" content=""Aesthetic Meets Ergonomics: My Deep Dive into the Glove80 Keyboard"">
|
<meta property="og:title" content="Blog Post">
|
||||||
<meta property="og:description" content="">
|
<meta property="og:description" content="">
|
||||||
<meta property="og:url" content="https://glenneth.orgcontent/posts/2024-04-08-glove80-review">
|
<meta property="og:url" content="https://glenneth.orgcontent/posts/2024-04-08-glove80-review">
|
||||||
<title>"Aesthetic Meets Ergonomics: My Deep Dive into the Glove80 Keyboard" - Glenn Thompson</title>
|
<title>Blog Post - Glenn Thompson</title>
|
||||||
<link rel="alternate" type="application/rss+xml" title="Glenn Thompson's Blog" href="/feed.xml" />
|
<link rel="alternate" type="application/rss+xml" title="Glenn Thompson's Blog" href="/feed.xml" />
|
||||||
<link href="../../dist/styles.css" rel="stylesheet">
|
<link href="/dist/styles.css" rel="stylesheet">
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Merriweather:wght@400;700&family=JetBrains+Mono:wght@400;700&display=swap" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Merriweather:wght@400;700&family=JetBrains+Mono:wght@400;700&display=swap" rel="stylesheet">
|
||||||
<style>
|
<style>
|
||||||
.prose-palenight {
|
.prose-palenight {
|
||||||
--tw-prose-body: #bfc7d5;
|
--tw-prose-body: #bfc7d5;
|
||||||
--tw-prose-headings: #ffd580;
|
--tw-prose-headings: #ffd580;
|
||||||
--tw-prose-links: #82aaff;
|
--tw-prose-links: #82aaff;
|
||||||
--tw-prose-code: #c792ea;
|
--tw-prose-code: #c792ea;
|
||||||
--tw-prose-pre-bg: #1b1e2b;
|
--tw-prose-pre-bg: #1b1e2b;
|
||||||
}
|
}
|
||||||
.prose h2 {
|
.prose h2 {
|
||||||
color: var(--tw-prose-headings);
|
color: var(--tw-prose-headings);
|
||||||
font-family: Merriweather, serif;
|
font-family: Merriweather, serif;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
font-size: 1.5rem;
|
font-size: 1.5rem;
|
||||||
margin-top: 2rem;
|
margin-top: 2rem;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
}
|
}
|
||||||
.prose p {
|
.prose p {
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
line-height: 1.625;
|
line-height: 1.625;
|
||||||
}
|
}
|
||||||
.prose a {
|
.prose a {
|
||||||
color: var(--tw-prose-links);
|
color: var(--tw-prose-links);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
.prose a:hover {
|
.prose a:hover {
|
||||||
color: #89ddff;
|
color: #89ddff;
|
||||||
}
|
}
|
||||||
.prose code {
|
.prose code {
|
||||||
color: var(--tw-prose-code);
|
color: var(--tw-prose-code);
|
||||||
font-family: 'JetBrains Mono', monospace;
|
font-family: 'JetBrains Mono', monospace;
|
||||||
}
|
}
|
||||||
.prose pre {
|
.prose pre {
|
||||||
background-color: var(--tw-prose-pre-bg);
|
background-color: var(--tw-prose-pre-bg);
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
}
|
}
|
||||||
.prose ul, .prose ol {
|
.prose ul, .prose ol {
|
||||||
margin-top: 0.5rem;
|
margin-top: 0.5rem;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
padding-left: 1.5rem;
|
padding-left: 1.5rem;
|
||||||
}
|
}
|
||||||
.prose ul {
|
.prose ul {
|
||||||
list-style-type: disc;
|
list-style-type: disc;
|
||||||
}
|
}
|
||||||
.prose ol {
|
.prose ol {
|
||||||
list-style-type: decimal;
|
list-style-type: decimal;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body class="bg-base-bg text-palenight-50">
|
<body class="bg-base-bg text-palenight-50">
|
||||||
<nav class="bg-base-darker/80 backdrop-blur-sm shadow-sm border-b border-palenight-400/20 mb-8">
|
<nav class="bg-base-darker/80 backdrop-blur-sm shadow-sm border-b border-palenight-400/20 mb-8">
|
||||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<div class="flex items-center justify-between h-16">
|
<div class="flex items-center justify-between h-16">
|
||||||
<a href="/" class="text-accent-yellow font-serif text-xl font-bold">Glenn Thompson</a>
|
<a href="/" class="text-accent-yellow font-serif text-xl font-bold">Glenn Thompson</a>
|
||||||
<div class="flex items-center gap-2 text-accent-yellow text-sm font-bold">
|
<div class="flex items-center gap-2 text-accent-yellow text-sm font-bold">
|
||||||
<span>["personal", "tech", "keyboards", "glove80"]</span>
|
<span>Tech</span>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<time datetime=""2024-04-08 16:50"">Invalid Date</time>
|
<time datetime="undefined">Invalid Date</time>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<span>5 min read</span>
|
<span>5 min read</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<main class="pt-24 pb-16 px-4">
|
<main class="pt-24 pb-16 px-4">
|
||||||
<div class="max-w-4xl mx-auto">
|
<div class="max-w-4xl mx-auto">
|
||||||
<div class="content text-palenight-100 space-y-6">
|
<div class="content text-palenight-100 space-y-6">
|
||||||
<header class="mb-8">
|
<header class="mb-8">
|
||||||
<h1 class="text-4xl font-serif font-bold text-accent-yellow">"Aesthetic Meets Ergonomics: My Deep Dive into the Glove80 Keyboard"</h1>
|
<h1 class="text-4xl font-serif font-bold text-accent-yellow">Blog Post</h1>
|
||||||
<div class="flex items-center gap-4 text-palenight-300 mt-4">
|
<div class="flex items-center gap-4 text-palenight-300 mt-4">
|
||||||
<time datetime=""2024-04-08 16:50"">"2024-04-08 16:50"</time>
|
<time datetime=""></time>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<span>5 min read</span>
|
<span>5 min read</span>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<span>By "Glenn Thompson"</span>
|
<span>By Glenn Thompson</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-wrap gap-2 mt-4">
|
</header>
|
||||||
<span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">["personal"</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">"tech"</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">"keyboards"</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">"glove80"]</span>
|
|
||||||
</div>
|
<article class="prose prose-palenight max-w-none">
|
||||||
</header>
|
<hr>
|
||||||
|
<h2>title: "Aesthetic Meets Ergonomics: My Deep Dive into the Glove80 Keyboard"<br>author: "Glenn Thompson"<br>date: "2024-04-08 16:50"<br>tags: ["personal", "tech", "keyboards", "glove80"]</h2>
|
||||||
<article class="prose prose-palenight max-w-none">
|
<h2>In the quest for the ultimate ergonomic keyboard, aesthetics often take a backseat to functionality. Yet, when I first laid eyes on the Glove80, I was struck by its elegant design—a refreshing departure from the utilitarian look typical of many ergonomic keyboards. Unlike the retro vibes of the Kinesis Advantage or the DIY aesthetics of most Dactyls, the Glove80 boasts a modern, sleek appearance that complements the contemporary design language of Apple, Google, and LG devices. With its clean lines and visually appealing legends, the Glove80 not only promises ergonomic comfort but does so with style, standing out amidst a sea of competitors.</h2>
|
||||||
<h2>In the quest for the ultimate ergonomic keyboard, aesthetics often take a backseat to functionality. Yet, when I first laid eyes on the Glove80, I was struck by its elegant design—a refreshing departure from the utilitarian look typical of many ergonomic keyboards. Unlike the retro vibes of the Kinesis Advantage or the DIY aesthetics of most Dactyls, the Glove80 boasts a modern, sleek appearance that complements the contemporary design language of Apple, Google, and LG devices. With its clean lines and visually appealing legends, the Glove80 not only promises ergonomic comfort but does so with style, standing out amidst a sea of competitors.</h2>
|
<p>As my career trajectory veered from being an integral member of an electrical engineering team to assuming the role of Deputy Project Manager, the nature of my daily activities underwent a significant transformation. The hands-on tasks of yesteryears were gradually replaced by a deluge of documentations—writing, reviewing, and endless typing. This shift brought with it an unwelcome companion: discomfort in my hands and wrists, a stark reminder of the ergonomic pitfalls of conventional keyboards. It was in this context that my quest for a more ergonomic typing solution began, leading me towards the world of ALICE layout keyboards, with the <a href="https://www.keychron.com/products/keychron-q10-pro-alice-layout-qmk-via-wireless-custom-mechanical-keyboard"><strong>Q10 Pro</strong> by Keychron</a> being my initial foray into this new realm.</p>
|
||||||
<p>As my career trajectory veered from being an integral member of an electrical engineering team to assuming the role of Deputy Project Manager, the nature of my daily activities underwent a significant transformation. The hands-on tasks of yesteryears were gradually replaced by a deluge of documentations—writing, reviewing, and endless typing. This shift brought with it an unwelcome companion: discomfort in my hands and wrists, a stark reminder of the ergonomic pitfalls of conventional keyboards. It was in this context that my quest for a more ergonomic typing solution began, leading me towards the world of ALICE layout keyboards, with the <a href="https://www.keychron.com/products/keychron-q10-pro-alice-layout-qmk-via-wireless-custom-mechanical-keyboard"><strong>Q10 Pro</strong> by Keychron</a> being my initial foray into this new realm.</p>
|
<p>However, the relief was partial, and the shadow of wrist strain persisted, urging me to delve deeper into the ergonomic keyboard universe. My search for a truly ergonomic solution brought me to the doorstep of the <a href="https://www.moergo.com"><strong>Glove80</strong> by MoErgo</a>. Boasting a unique split design, concave key wells, and a commitment to ergonomics that seemed almost tailor-made for my situation, the Glove80 held the promise of being the oasis I was desperately seeking in the desert of my wrist discomfort.</p>
|
||||||
<p>However, the relief was partial, and the shadow of wrist strain persisted, urging me to delve deeper into the ergonomic keyboard universe. My search for a truly ergonomic solution brought me to the doorstep of the <a href="https://www.moergo.com"><strong>Glove80</strong> by MoErgo</a>. Boasting a unique split design, concave key wells, and a commitment to ergonomics that seemed almost tailor-made for my situation, the Glove80 held the promise of being the oasis I was desperately seeking in the desert of my wrist discomfort.</p>
|
<p>This journey from an ALICE layout keyboard user to a Glove80 enthusiast was not just about finding a better typing tool; it was about embracing a healthier typing posture and redefining my interaction with computers. After a month of integrating the Glove80 into my workflow, I'm ready to share my insights and experiences. This review will explore the initial adaptation period, the impact on my wrist health, and whether the Glove80 lives up to its promise as an ergonomic game-changer.</p>
|
||||||
<p>This journey from an ALICE layout keyboard user to a Glove80 enthusiast was not just about finding a better typing tool; it was about embracing a healthier typing posture and redefining my interaction with computers. After a month of integrating the Glove80 into my workflow, I'm ready to share my insights and experiences. This review will explore the initial adaptation period, the impact on my wrist health, and whether the Glove80 lives up to its promise as an ergonomic game-changer.</p>
|
<h3>First Impressions: Feel and Experience</h3>
|
||||||
<h3>First Impressions: Feel and Experience</h3>
|
<p>Upon beginning my typing journey with the Glove80, two aspects immediately stood out. The unique choc spacing, combined with finger-specific curves for each key column, facilitated effortless access to the bottom and number rows, as well as several function keys—without the need to move my hands. This ease of reach extended to the thumb keys, thoughtfully laid out in an arc to match the natural movement of my thumbs. Additionally, the keyboard's low profile on the desk encouraged a neutral wrist position, enhancing comfort during long typing sessions. These features converged to create a typing experience that was not just comfortable but intuitively aligned with natural hand movements.</p>
|
||||||
<p>Upon beginning my typing journey with the Glove80, two aspects immediately stood out. The unique choc spacing, combined with finger-specific curves for each key column, facilitated effortless access to the bottom and number rows, as well as several function keys—without the need to move my hands. This ease of reach extended to the thumb keys, thoughtfully laid out in an arc to match the natural movement of my thumbs. Additionally, the keyboard's low profile on the desk encouraged a neutral wrist position, enhancing comfort during long typing sessions. These features converged to create a typing experience that was not just comfortable but intuitively aligned with natural hand movements.</p>
|
<h4>The Details That Matter</h4>
|
||||||
<h4>The Details That Matter</h4>
|
<h5>Ergonomics at Its Core</h5>
|
||||||
<h5>Ergonomics at Its Core</h5>
|
<p>The hallmark of the Glove80 is its ergonomics, designed to seamlessly integrate with the user's hand movements. After fine-tuning the tenting and tilting angles—made possible by the adjustable feet on each half of the keyboard—my hands naturally fell into the optimal typing position. The thoughtfully designed key layout meant that reaching for higher rows required merely straightening or curling my fingers, aided by the keyboard's choc spacing. Each column's unique height and curve catered to the different lengths of my fingers, further minimizing strain.</p>
|
||||||
<p>The hallmark of the Glove80 is its ergonomics, designed to seamlessly integrate with the user's hand movements. After fine-tuning the tenting and tilting angles—made possible by the adjustable feet on each half of the keyboard—my hands naturally fell into the optimal typing position. The thoughtfully designed key layout meant that reaching for higher rows required merely straightening or curling my fingers, aided by the keyboard's choc spacing. Each column's unique height and curve catered to the different lengths of my fingers, further minimizing strain.</p>
|
<h5>Key Innovations</h5>
|
||||||
<h5>Key Innovations</h5>
|
<p>The Glove80 introduces keycaps with a novel MCC profile, featuring raised sides and a central cylindrical channel, made from a slick POM material. This design supports the natural sliding of fingers across keys, reducing the need to lift hands while typing. The keyboard's thumb clusters are another highlight, offering six easily accessible keys per hand. This ergonomic layout ensures that most keys are within reach without stretching, a testament to the keyboard's user-centric design.</p>
|
||||||
<p>The Glove80 introduces keycaps with a novel MCC profile, featuring raised sides and a central cylindrical channel, made from a slick POM material. This design supports the natural sliding of fingers across keys, reducing the need to lift hands while typing. The keyboard's thumb clusters are another highlight, offering six easily accessible keys per hand. This ergonomic layout ensures that most keys are within reach without stretching, a testament to the keyboard's user-centric design.</p>
|
<h5>Beyond Typing: Features and Flexibility</h5>
|
||||||
<h5>Beyond Typing: Features and Flexibility</h5>
|
<ul>
|
||||||
<ul>
|
<li><strong>Tenting and Adjustability:</strong> The Glove80's customizable tenting angles, enhanced by sturdy locking nuts, ensure a tailored typing experience that can be finely adjusted to individual preferences.</li>
|
||||||
<li><strong>Tenting and Adjustability:</strong> The Glove80's customizable tenting angles, enhanced by sturdy locking nuts, ensure a tailored typing experience that can be finely adjusted to individual preferences.</li>
|
<li><strong>Comfortable Palm Rest:</strong> The integrated, detachable palm rest offers additional comfort, catering to different typing styles with ease.</li>
|
||||||
<li><strong>Comfortable Palm Rest:</strong> The integrated, detachable palm rest offers additional comfort, catering to different typing styles with ease.</li>
|
<li><strong>Switch Selection:</strong> While the standard Kailh choc switches are adequate, enthusiasts might prefer customizing their keyboard with preferred switches for an optimized typing feel. I opted for the lighter Kailh Choc V1, Red Pro Linear 35gf switches.</li>
|
||||||
<li><strong>Switch Selection:</strong> While the standard Kailh choc switches are adequate, enthusiasts might prefer customizing their keyboard with preferred switches for an optimized typing feel. I opted for the lighter Kailh Choc V1, Red Pro Linear 35gf switches.</li>
|
<li><strong>Keycaps:</strong> The high-quality POM keycaps, combined with attractive and durable legends, enhance the keyboard's tactile and visual appeal.</li>
|
||||||
<li><strong>Keycaps:</strong> The high-quality POM keycaps, combined with attractive and durable legends, enhance the keyboard's tactile and visual appeal.</li>
|
<li><strong>Tech-Savvy Features:</strong> From its easy-to-use firmware updates via a web interface to seamless Bluetooth connectivity and impressive battery life, the Glove80 is designed for a modern, wireless world.</li>
|
||||||
<li><strong>Tech-Savvy Features:</strong> From its easy-to-use firmware updates via a web interface to seamless Bluetooth connectivity and impressive battery life, the Glove80 is designed for a modern, wireless world.</li>
|
<li><strong>RGB Lighting:</strong> While currently limited in customization, the RGB LEDs offer aesthetic versatility to match any setup.</li>
|
||||||
<li><strong>RGB Lighting:</strong> While currently limited in customization, the RGB LEDs offer aesthetic versatility to match any setup.</li>
|
</ul>
|
||||||
</ul>
|
<h3>Concluding Thoughts</h3>
|
||||||
<h3>Concluding Thoughts</h3>
|
<p>The Glove80 keyboard represents a significant leap forward in ergonomic design, marrying aesthetics with unmatched comfort and functionality. Its thoughtful features—from the infinitely adjustable tenting to the innovative keycap design—set a new standard for what ergonomic keyboards can be. While there's room for improvement in switch selection and RGB customization, these are minor quibbles in an otherwise outstanding product. For those in search of ergonomic excellence without compromising on style or performance, the Glove80 is an investment worth making, promising a typing experience that's not just comfortable but truly enjoyable.</p>
|
||||||
<p>The Glove80 keyboard represents a significant leap forward in ergonomic design, marrying aesthetics with unmatched comfort and functionality. Its thoughtful features—from the infinitely adjustable tenting to the innovative keycap design—set a new standard for what ergonomic keyboards can be. While there's room for improvement in switch selection and RGB customization, these are minor quibbles in an otherwise outstanding product. For those in search of ergonomic excellence without compromising on style or performance, the Glove80 is an investment worth making, promising a typing experience that's not just comfortable but truly enjoyable.</p>
|
|
||||||
|
</article>
|
||||||
</article>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</main>
|
||||||
</main>
|
<footer class="bg-base-darker text-palenight-200 py-12 border-t border-palenight-400/20">
|
||||||
<footer class="bg-base-darker text-palenight-200 py-12 border-t border-palenight-400/20">
|
<div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
<div class="text-center">
|
||||||
<div class="text-center">
|
<p class="text-palenight-300">© 2026 Glenn Thompson. All rights reserved.</p>
|
||||||
<p class="text-palenight-300">© 2024 Glenn Thompson. All rights reserved.</p>
|
<div class="webring-text mt-6">
|
||||||
<div class="webring-text mt-6">
|
<p class="text-palenight-300">I am part of the <a href="https://systemcrafters.net" target="_blank" class="text-accent-blue hover:text-accent-cyan">System Crafters</a> webring:</p>
|
||||||
<p class="text-palenight-300">I am part of the <a href="https://systemcrafters.net" target="_blank" class="text-accent-blue hover:text-accent-cyan">System Crafters</a> webring:</p>
|
</div>
|
||||||
</div>
|
<div class="craftering mt-2 flex items-center justify-center gap-4 text-accent-blue">
|
||||||
<div class="craftering mt-2 flex items-center justify-center gap-4 text-accent-blue">
|
<a href="https://craftering.systemcrafters.net/@glenneth/previous" class="hover:text-accent-cyan">Previous</a>
|
||||||
<a href="https://craftering.systemcrafters.net/@glenneth/previous" class="hover:text-accent-cyan">Previous</a>
|
<a href="https://craftering.systemcrafters.net/@glenneth" class="hover:text-accent-cyan">Random</a>
|
||||||
<a href="https://craftering.systemcrafters.net/@glenneth" class="hover:text-accent-cyan">Random</a>
|
<a href="https://craftering.systemcrafters.net/@glenneth/next" class="hover:text-accent-cyan">Next</a>
|
||||||
<a href="https://craftering.systemcrafters.net/@glenneth/next" class="hover:text-accent-cyan">Next</a>
|
</div>
|
||||||
</div>
|
<p class="text-palenight-300 mt-2">
|
||||||
<p class="text-palenight-300 mt-2">
|
<a href="mailto:glenn@glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenn@glenneth.org</a> |
|
||||||
<a href="mailto:glenn@glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenn@glenneth.org</a> |
|
<a href="https://glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenneth.org</a>
|
||||||
<a href="https://glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenneth.org</a>
|
</p>
|
||||||
</p>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</footer>
|
||||||
</footer>
|
</body>
|
||||||
</body>
|
|
||||||
</html>
|
</html>
|
||||||
|
|
@ -1,140 +1,139 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en" class="bg-base-bg">
|
<html lang="en" class="bg-base-bg">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<meta name="description" content="">
|
<meta name="description" content="">
|
||||||
<meta property="og:title" content="A Rollercoaster Week: From Amman to Newcastle, and back again">
|
<meta property="og:title" content="Blog Post">
|
||||||
<meta property="og:description" content="">
|
<meta property="og:description" content="">
|
||||||
<meta property="og:url" content="https://glenneth.orgcontent/posts/2024-05-01-amman-newcastle-journey">
|
<meta property="og:url" content="https://glenneth.orgcontent/posts/2024-05-01-amman-newcastle-journey">
|
||||||
<title>A Rollercoaster Week: From Amman to Newcastle, and back again - Glenn Thompson</title>
|
<title>Blog Post - Glenn Thompson</title>
|
||||||
<link rel="alternate" type="application/rss+xml" title="Glenn Thompson's Blog" href="/feed.xml" />
|
<link rel="alternate" type="application/rss+xml" title="Glenn Thompson's Blog" href="/feed.xml" />
|
||||||
<link href="../../dist/styles.css" rel="stylesheet">
|
<link href="/dist/styles.css" rel="stylesheet">
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Merriweather:wght@400;700&family=JetBrains+Mono:wght@400;700&display=swap" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Merriweather:wght@400;700&family=JetBrains+Mono:wght@400;700&display=swap" rel="stylesheet">
|
||||||
<style>
|
<style>
|
||||||
.prose-palenight {
|
.prose-palenight {
|
||||||
--tw-prose-body: #bfc7d5;
|
--tw-prose-body: #bfc7d5;
|
||||||
--tw-prose-headings: #ffd580;
|
--tw-prose-headings: #ffd580;
|
||||||
--tw-prose-links: #82aaff;
|
--tw-prose-links: #82aaff;
|
||||||
--tw-prose-code: #c792ea;
|
--tw-prose-code: #c792ea;
|
||||||
--tw-prose-pre-bg: #1b1e2b;
|
--tw-prose-pre-bg: #1b1e2b;
|
||||||
}
|
}
|
||||||
.prose h2 {
|
.prose h2 {
|
||||||
color: var(--tw-prose-headings);
|
color: var(--tw-prose-headings);
|
||||||
font-family: Merriweather, serif;
|
font-family: Merriweather, serif;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
font-size: 1.5rem;
|
font-size: 1.5rem;
|
||||||
margin-top: 2rem;
|
margin-top: 2rem;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
}
|
}
|
||||||
.prose p {
|
.prose p {
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
line-height: 1.625;
|
line-height: 1.625;
|
||||||
}
|
}
|
||||||
.prose a {
|
.prose a {
|
||||||
color: var(--tw-prose-links);
|
color: var(--tw-prose-links);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
.prose a:hover {
|
.prose a:hover {
|
||||||
color: #89ddff;
|
color: #89ddff;
|
||||||
}
|
}
|
||||||
.prose code {
|
.prose code {
|
||||||
color: var(--tw-prose-code);
|
color: var(--tw-prose-code);
|
||||||
font-family: 'JetBrains Mono', monospace;
|
font-family: 'JetBrains Mono', monospace;
|
||||||
}
|
}
|
||||||
.prose pre {
|
.prose pre {
|
||||||
background-color: var(--tw-prose-pre-bg);
|
background-color: var(--tw-prose-pre-bg);
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
}
|
}
|
||||||
.prose ul, .prose ol {
|
.prose ul, .prose ol {
|
||||||
margin-top: 0.5rem;
|
margin-top: 0.5rem;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
padding-left: 1.5rem;
|
padding-left: 1.5rem;
|
||||||
}
|
}
|
||||||
.prose ul {
|
.prose ul {
|
||||||
list-style-type: disc;
|
list-style-type: disc;
|
||||||
}
|
}
|
||||||
.prose ol {
|
.prose ol {
|
||||||
list-style-type: decimal;
|
list-style-type: decimal;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body class="bg-base-bg text-palenight-50">
|
<body class="bg-base-bg text-palenight-50">
|
||||||
<nav class="bg-base-darker/80 backdrop-blur-sm shadow-sm border-b border-palenight-400/20 mb-8">
|
<nav class="bg-base-darker/80 backdrop-blur-sm shadow-sm border-b border-palenight-400/20 mb-8">
|
||||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<div class="flex items-center justify-between h-16">
|
<div class="flex items-center justify-between h-16">
|
||||||
<a href="/" class="text-accent-yellow font-serif text-xl font-bold">Glenn Thompson</a>
|
<a href="/" class="text-accent-yellow font-serif text-xl font-bold">Glenn Thompson</a>
|
||||||
<div class="flex items-center gap-2 text-accent-yellow text-sm font-bold">
|
<div class="flex items-center gap-2 text-accent-yellow text-sm font-bold">
|
||||||
<span>work, travel</span>
|
<span>Tech</span>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<time datetime="2024-05-01 17:40:58+03:00">May 1, 2024</time>
|
<time datetime="undefined">Invalid Date</time>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<span>3 min read</span>
|
<span>3 min read</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<main class="pt-24 pb-16 px-4">
|
<main class="pt-24 pb-16 px-4">
|
||||||
<div class="max-w-4xl mx-auto">
|
<div class="max-w-4xl mx-auto">
|
||||||
<div class="content text-palenight-100 space-y-6">
|
<div class="content text-palenight-100 space-y-6">
|
||||||
<header class="mb-8">
|
<header class="mb-8">
|
||||||
<h1 class="text-4xl font-serif font-bold text-accent-yellow">A Rollercoaster Week: From Amman to Newcastle, and back again</h1>
|
<h1 class="text-4xl font-serif font-bold text-accent-yellow">Blog Post</h1>
|
||||||
<div class="flex items-center gap-4 text-palenight-300 mt-4">
|
<div class="flex items-center gap-4 text-palenight-300 mt-4">
|
||||||
<time datetime="2024-05-01 17:40:58+03:00">2024-05-01 17:40:58+03:00</time>
|
<time datetime=""></time>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<span>3 min read</span>
|
<span>3 min read</span>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<span>By Glenn Thompson</span>
|
<span>By Glenn Thompson</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-wrap gap-2 mt-4">
|
</header>
|
||||||
<span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">work</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">travel</span>
|
|
||||||
</div>
|
<article class="prose prose-palenight max-w-none">
|
||||||
</header>
|
<hr>
|
||||||
|
<h2>title: A Rollercoaster Week: From Amman to Newcastle, and back again<br>author: Glenn Thompson<br>date: 2024-05-01 17:40:58+03:00<br>tags: work, travel</h2>
|
||||||
<article class="prose prose-palenight max-w-none">
|
<p>Two weeks ago was a whirlwind of events, taking me from the conforting embrace of Amman, Jordan to the vibrant streets of Newcastle, England. It was a journey filled with highs and lows, professional achievements, and personal challenges.</p>
|
||||||
<p>Two weeks ago was a whirlwind of events, taking me from the conforting embrace of Amman, Jordan to the vibrant streets of Newcastle, England. It was a journey filled with highs and lows, professional achievements, and personal challenges.</p>
|
<h2>The Journey Begins</h2>
|
||||||
<h2>The Journey Begins</h2>
|
<p>It all started on a Monday morning in Amman as I embarked on a journey to attend a Quality Control (QC) conference in Newcastle. The anticipation of presenting my work at an international forum filled me with excitement and nerves. The conference was scheduled for just one day, but the impact it had on me would last much longer.</p>
|
||||||
<p>It all started on a Monday morning in Amman as I embarked on a journey to attend a Quality Control (QC) conference in Newcastle. The anticipation of presenting my work at an international forum filled me with excitement and nerves. The conference was scheduled for just one day, but the impact it had on me would last much longer.</p>
|
<h2>A Successful Presentation</h2>
|
||||||
<h2>A Successful Presentation</h2>
|
<p>Tuesday arrived, and with it came the day of the conference. Armed with a PowerPoint presentation comprising over 130 slides, I delved into four hours of intense presenting. Despite the pressure, the conference was a resounding success. My project received positive feedback, and I felt a sense of accomplishment as I shared my work with colleagues from around the world.</p>
|
||||||
<p>Tuesday arrived, and with it came the day of the conference. Armed with a PowerPoint presentation comprising over 130 slides, I delved into four hours of intense presenting. Despite the pressure, the conference was a resounding success. My project received positive feedback, and I felt a sense of accomplishment as I shared my work with colleagues from around the world.</p>
|
<h2>The Toll of Travel</h2>
|
||||||
<h2>The Toll of Travel</h2>
|
<p>However, as I returned to Amman on Wednesday, I couldn't shake off a sense of exhaustion. Little did I know that the toll of travel would soon manifest itself in a most unexpected manner. </p>
|
||||||
<p>However, as I returned to Amman on Wednesday, I couldn't shake off a sense of exhaustion. Little did I know that the toll of travel would soon manifest itself in a most unexpected manner. </p>
|
<p>Thursday morning greeted me with heavy flu-like symptoms. It hit me like a ton of bricks. The combination of jet lag, long hours of presenting, and exposure to new environments had taken its toll on my immune system. I was bedridden, grappling with a chesty cough that seemed relentless.</p>
|
||||||
<p>Thursday morning greeted me with heavy flu-like symptoms. It hit me like a ton of bricks. The combination of jet lag, long hours of presenting, and exposure to new environments had taken its toll on my immune system. I was bedridden, grappling with a chesty cough that seemed relentless.</p>
|
<h2>The Show Must Go On</h2>
|
||||||
<h2>The Show Must Go On</h2>
|
<p>Despite my illness, there was no time for rest. The following week demanded my presence at a site meeting where I was tasked with condensing my extensive slide deck into a concise presentation of just 12 slides. The challenge was daunting, but I tackled it with determination.</p>
|
||||||
<p>Despite my illness, there was no time for rest. The following week demanded my presence at a site meeting where I was tasked with condensing my extensive slide deck into a concise presentation of just 12 slides. The challenge was daunting, but I tackled it with determination.</p>
|
<h2>Reflecting on the Journey</h2>
|
||||||
<h2>Reflecting on the Journey</h2>
|
<p>As I look back on the rollercoaster week that was, I'm struck by the juxtaposition of success and struggle. From the heights of presenting at an international conference to the lows of battling illness, it was a journey that tested my resilience and resolve.</p>
|
||||||
<p>As I look back on the rollercoaster week that was, I'm struck by the juxtaposition of success and struggle. From the heights of presenting at an international conference to the lows of battling illness, it was a journey that tested my resilience and resolve.</p>
|
<p>But through it all, one thing remains clear: adversity only serves to make us stronger. Each obstacle we overcome, whether professional or personal, contributes to our growth and development.</p>
|
||||||
<p>But through it all, one thing remains clear: adversity only serves to make us stronger. Each obstacle we overcome, whether professional or personal, contributes to our growth and development.</p>
|
<p>So here's to the rollercoaster weeks, the ones filled with ups and downs, twists and turns. For it is in those moments of challenge that we discover the true extent of our capabilities.</p>
|
||||||
<p>So here's to the rollercoaster weeks, the ones filled with ups and downs, twists and turns. For it is in those moments of challenge that we discover the true extent of our capabilities.</p>
|
<p>As I upload this blog post using Hugo, I do so with a renewed sense of gratitude for the journey and all it has taught me. Here's to embracing the ride, wherever it may take us.</p>
|
||||||
<p>As I upload this blog post using Hugo, I do so with a renewed sense of gratitude for the journey and all it has taught me. Here's to embracing the ride, wherever it may take us.</p>
|
|
||||||
|
</article>
|
||||||
</article>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</main>
|
||||||
</main>
|
<footer class="bg-base-darker text-palenight-200 py-12 border-t border-palenight-400/20">
|
||||||
<footer class="bg-base-darker text-palenight-200 py-12 border-t border-palenight-400/20">
|
<div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
<div class="text-center">
|
||||||
<div class="text-center">
|
<p class="text-palenight-300">© 2026 Glenn Thompson. All rights reserved.</p>
|
||||||
<p class="text-palenight-300">© 2024 Glenn Thompson. All rights reserved.</p>
|
<div class="webring-text mt-6">
|
||||||
<div class="webring-text mt-6">
|
<p class="text-palenight-300">I am part of the <a href="https://systemcrafters.net" target="_blank" class="text-accent-blue hover:text-accent-cyan">System Crafters</a> webring:</p>
|
||||||
<p class="text-palenight-300">I am part of the <a href="https://systemcrafters.net" target="_blank" class="text-accent-blue hover:text-accent-cyan">System Crafters</a> webring:</p>
|
</div>
|
||||||
</div>
|
<div class="craftering mt-2 flex items-center justify-center gap-4 text-accent-blue">
|
||||||
<div class="craftering mt-2 flex items-center justify-center gap-4 text-accent-blue">
|
<a href="https://craftering.systemcrafters.net/@glenneth/previous" class="hover:text-accent-cyan">Previous</a>
|
||||||
<a href="https://craftering.systemcrafters.net/@glenneth/previous" class="hover:text-accent-cyan">Previous</a>
|
<a href="https://craftering.systemcrafters.net/@glenneth" class="hover:text-accent-cyan">Random</a>
|
||||||
<a href="https://craftering.systemcrafters.net/@glenneth" class="hover:text-accent-cyan">Random</a>
|
<a href="https://craftering.systemcrafters.net/@glenneth/next" class="hover:text-accent-cyan">Next</a>
|
||||||
<a href="https://craftering.systemcrafters.net/@glenneth/next" class="hover:text-accent-cyan">Next</a>
|
</div>
|
||||||
</div>
|
<p class="text-palenight-300 mt-2">
|
||||||
<p class="text-palenight-300 mt-2">
|
<a href="mailto:glenn@glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenn@glenneth.org</a> |
|
||||||
<a href="mailto:glenn@glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenn@glenneth.org</a> |
|
<a href="https://glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenneth.org</a>
|
||||||
<a href="https://glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenneth.org</a>
|
</p>
|
||||||
</p>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</footer>
|
||||||
</footer>
|
</body>
|
||||||
</body>
|
|
||||||
</html>
|
</html>
|
||||||
|
|
@ -1,362 +1,361 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en" class="bg-base-bg">
|
<html lang="en" class="bg-base-bg">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<meta name="description" content="">
|
<meta name="description" content="">
|
||||||
<meta property="og:title" content="Transitioning from Hugo to Haunt: Embracing Scheme and GNU Guix">
|
<meta property="og:title" content="Blog Post">
|
||||||
<meta property="og:description" content="">
|
<meta property="og:description" content="">
|
||||||
<meta property="og:url" content="https://glenneth.orgcontent/posts/2024-05-15-hugo-to-haunt">
|
<meta property="og:url" content="https://glenneth.orgcontent/posts/2024-05-15-hugo-to-haunt">
|
||||||
<title>Transitioning from Hugo to Haunt: Embracing Scheme and GNU Guix - Glenn Thompson</title>
|
<title>Blog Post - Glenn Thompson</title>
|
||||||
<link rel="alternate" type="application/rss+xml" title="Glenn Thompson's Blog" href="/feed.xml" />
|
<link rel="alternate" type="application/rss+xml" title="Glenn Thompson's Blog" href="/feed.xml" />
|
||||||
<link href="../../dist/styles.css" rel="stylesheet">
|
<link href="/dist/styles.css" rel="stylesheet">
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Merriweather:wght@400;700&family=JetBrains+Mono:wght@400;700&display=swap" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Merriweather:wght@400;700&family=JetBrains+Mono:wght@400;700&display=swap" rel="stylesheet">
|
||||||
<style>
|
<style>
|
||||||
.prose-palenight {
|
.prose-palenight {
|
||||||
--tw-prose-body: #bfc7d5;
|
--tw-prose-body: #bfc7d5;
|
||||||
--tw-prose-headings: #ffd580;
|
--tw-prose-headings: #ffd580;
|
||||||
--tw-prose-links: #82aaff;
|
--tw-prose-links: #82aaff;
|
||||||
--tw-prose-code: #c792ea;
|
--tw-prose-code: #c792ea;
|
||||||
--tw-prose-pre-bg: #1b1e2b;
|
--tw-prose-pre-bg: #1b1e2b;
|
||||||
}
|
}
|
||||||
.prose h2 {
|
.prose h2 {
|
||||||
color: var(--tw-prose-headings);
|
color: var(--tw-prose-headings);
|
||||||
font-family: Merriweather, serif;
|
font-family: Merriweather, serif;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
font-size: 1.5rem;
|
font-size: 1.5rem;
|
||||||
margin-top: 2rem;
|
margin-top: 2rem;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
}
|
}
|
||||||
.prose p {
|
.prose p {
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
line-height: 1.625;
|
line-height: 1.625;
|
||||||
}
|
}
|
||||||
.prose a {
|
.prose a {
|
||||||
color: var(--tw-prose-links);
|
color: var(--tw-prose-links);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
.prose a:hover {
|
.prose a:hover {
|
||||||
color: #89ddff;
|
color: #89ddff;
|
||||||
}
|
}
|
||||||
.prose code {
|
.prose code {
|
||||||
color: var(--tw-prose-code);
|
color: var(--tw-prose-code);
|
||||||
font-family: 'JetBrains Mono', monospace;
|
font-family: 'JetBrains Mono', monospace;
|
||||||
}
|
}
|
||||||
.prose pre {
|
.prose pre {
|
||||||
background-color: var(--tw-prose-pre-bg);
|
background-color: var(--tw-prose-pre-bg);
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
}
|
}
|
||||||
.prose ul, .prose ol {
|
.prose ul, .prose ol {
|
||||||
margin-top: 0.5rem;
|
margin-top: 0.5rem;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
padding-left: 1.5rem;
|
padding-left: 1.5rem;
|
||||||
}
|
}
|
||||||
.prose ul {
|
.prose ul {
|
||||||
list-style-type: disc;
|
list-style-type: disc;
|
||||||
}
|
}
|
||||||
.prose ol {
|
.prose ol {
|
||||||
list-style-type: decimal;
|
list-style-type: decimal;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body class="bg-base-bg text-palenight-50">
|
<body class="bg-base-bg text-palenight-50">
|
||||||
<nav class="bg-base-darker/80 backdrop-blur-sm shadow-sm border-b border-palenight-400/20 mb-8">
|
<nav class="bg-base-darker/80 backdrop-blur-sm shadow-sm border-b border-palenight-400/20 mb-8">
|
||||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<div class="flex items-center justify-between h-16">
|
<div class="flex items-center justify-between h-16">
|
||||||
<a href="/" class="text-accent-yellow font-serif text-xl font-bold">Glenn Thompson</a>
|
<a href="/" class="text-accent-yellow font-serif text-xl font-bold">Glenn Thompson</a>
|
||||||
<div class="flex items-center gap-2 text-accent-yellow text-sm font-bold">
|
<div class="flex items-center gap-2 text-accent-yellow text-sm font-bold">
|
||||||
<span>personal, tech, keyboards, glove80</span>
|
<span>Tech</span>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<time datetime="2024-05-15 10:30">May 15, 2024</time>
|
<time datetime="undefined">Invalid Date</time>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<span>7 min read</span>
|
<span>7 min read</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<main class="pt-24 pb-16 px-4">
|
<main class="pt-24 pb-16 px-4">
|
||||||
<div class="max-w-4xl mx-auto">
|
<div class="max-w-4xl mx-auto">
|
||||||
<div class="content text-palenight-100 space-y-6">
|
<div class="content text-palenight-100 space-y-6">
|
||||||
<header class="mb-8">
|
<header class="mb-8">
|
||||||
<h1 class="text-4xl font-serif font-bold text-accent-yellow">Transitioning from Hugo to Haunt: Embracing Scheme and GNU Guix</h1>
|
<h1 class="text-4xl font-serif font-bold text-accent-yellow">Blog Post</h1>
|
||||||
<div class="flex items-center gap-4 text-palenight-300 mt-4">
|
<div class="flex items-center gap-4 text-palenight-300 mt-4">
|
||||||
<time datetime="2024-05-15 10:30">2024-05-15 10:30</time>
|
<time datetime=""></time>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<span>7 min read</span>
|
<span>7 min read</span>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<span>By Glenn Thompson</span>
|
<span>By Glenn Thompson</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-wrap gap-2 mt-4">
|
</header>
|
||||||
<span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">personal</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">tech</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">keyboards</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">glove80</span>
|
|
||||||
</div>
|
<article class="prose prose-palenight max-w-none">
|
||||||
</header>
|
<hr>
|
||||||
|
<h2>title: Transitioning from Hugo to Haunt: Embracing Scheme and GNU Guix<br>author: Glenn Thompson<br>date: 2024-05-15 10:30<br>tags: personal, tech, keyboards, glove80</h2>
|
||||||
<article class="prose prose-palenight max-w-none">
|
<h1>Transitioning from Hugo to Haunt: Embracing Scheme and GNU Guix</h1>
|
||||||
<h1>Transitioning from Hugo to Haunt: Embracing Scheme and GNU Guix</h1>
|
<p>Hello there! I'm Glenn Thompson, and today, I want to share a significant part of my recent journey into the world of Scheme, GNU Guix, and static site generation.</p>
|
||||||
<p>Hello there! I'm Glenn Thompson, and today, I want to share a significant part of my recent journey into the world of Scheme, GNU Guix, and static site generation.</p>
|
<h2>Discovering Scheme with System Crafters</h2>
|
||||||
<h2>Discovering Scheme with System Crafters</h2>
|
<p>My journey began with a desire to dive deeper into programming languages and their ecosystems. I am a member of the <a href="https://systemcrafters.net/community/">System Crafters Community</a>, and its founder, David Wilson, announced a short four week course as an introduction to Guile Scheme. The course, <a href="https://systemcrafters.net/courses/hands-on-guile-scheme-beginners/">Hands-On Guile Scheme for Beginners</a>, provided me with a robust introduction to Guile Scheme, a language that emphasizes simplicity and elegance. David's clear explanations and practical examples made learning Scheme both engaging and approachable.</p>
|
||||||
<p>My journey began with a desire to dive deeper into programming languages and their ecosystems. I am a member of the <a href="https://systemcrafters.net/community/">System Crafters Community</a>, and its founder, David Wilson, announced a short four week course as an introduction to Guile Scheme. The course, <a href="https://systemcrafters.net/courses/hands-on-guile-scheme-beginners/">Hands-On Guile Scheme for Beginners</a>, provided me with a robust introduction to Guile Scheme, a language that emphasizes simplicity and elegance. David's clear explanations and practical examples made learning Scheme both engaging and approachable.</p>
|
<h2>The Move to GNU Guix</h2>
|
||||||
<h2>The Move to GNU Guix</h2>
|
<p>Inspired by the principles of Scheme, I decided to take a leap further into the open-source world by transitioning from Arch Linux to GNU Guix. The Guix community, particularly the folks in the <code>#systemcrafters</code> channel on <code>irc.libera.chat</code>, were incredibly supportive and instrumental in helping me navigate this new environment. Their guidance made the switch smooth and rewarding, reinforcing the power and flexibility of GNU Guix as a functional package manager and operating system. More about that experience in another post.</p>
|
||||||
<p>Inspired by the principles of Scheme, I decided to take a leap further into the open-source world by transitioning from Arch Linux to GNU Guix. The Guix community, particularly the folks in the <code>#systemcrafters</code> channel on <code>irc.libera.chat</code>, were incredibly supportive and instrumental in helping me navigate this new environment. Their guidance made the switch smooth and rewarding, reinforcing the power and flexibility of GNU Guix as a functional package manager and operating system. More about that experience in another post.</p>
|
<p>There are too many individuals to name here that have helped with the installation and configuration on Gnu guix to mention here. You all have been an incredible help for which I am extremely grateful. Thank you all , for enduring my ignorance, and for your patience and your help.</p>
|
||||||
<p>There are too many individuals to name here that have helped with the installation and configuration on Gnu guix to mention here. You all have been an incredible help for which I am extremely grateful. Thank you all , for enduring my ignorance, and for your patience and your help.</p>
|
<h2>From Hugo to Haunt</h2>
|
||||||
<h2>From Hugo to Haunt</h2>
|
<p>As I settled into Guix, I faced a challenge: Hugo, the static site generator I previously used, was not available as a Guix package. This led me to explore alternatives and eventually discover <a href="https://dthompson.us/projects/haunt.html">Haunt</a>, a Scheme-based static site generator that aligns perfectly with my newfound appreciation for Scheme and Guix.</p>
|
||||||
<p>As I settled into Guix, I faced a challenge: Hugo, the static site generator I previously used, was not available as a Guix package. This led me to explore alternatives and eventually discover <a href="https://dthompson.us/projects/haunt.html">Haunt</a>, a Scheme-based static site generator that aligns perfectly with my newfound appreciation for Scheme and Guix.</p>
|
<h2>Overcoming Challenges with Haunt</h2>
|
||||||
<h2>Overcoming Challenges with Haunt</h2>
|
<p>Transitioning to Haunt wasn't without its challenges. There are no readily available templating systems available for haunt like there are for hugo, but there are plenty of examples <a href="https://awesome.haunt.page/">here</a>. One of my own primary difficulties was creating a custom template that matched my site's aesthetic requirements and functionality needs. Initially, I struggled with configuring the theme layout and ensuring the CSS was applied correctly. Another hurdle was generating the correct URLs for posts and ensuring that summaries appeared as intended on the front page.</p>
|
||||||
<p>Transitioning to Haunt wasn't without its challenges. There are no readily available templating systems available for haunt like there are for hugo, but there are plenty of examples <a href="https://awesome.haunt.page/">here</a>. One of my own primary difficulties was creating a custom template that matched my site's aesthetic requirements and functionality needs. Initially, I struggled with configuring the theme layout and ensuring the CSS was applied correctly. Another hurdle was generating the correct URLs for posts and ensuring that summaries appeared as intended on the front page.</p>
|
<p>Thankfully, the Haunt manual proved to be an invaluable resource throughout this process. The comprehensive documentation provided clear guidance on using various modules, functions, and procedures. By carefully studying the examples and explanations, I was able to overcome the obstacles and achieve the desired results for my site. The manual's detailed descriptions of Haunt's inner workings were particularly helpful in understanding how to leverage the flexibility of Scheme to customize my blog.</p>
|
||||||
<p>Thankfully, the Haunt manual proved to be an invaluable resource throughout this process. The comprehensive documentation provided clear guidance on using various modules, functions, and procedures. By carefully studying the examples and explanations, I was able to overcome the obstacles and achieve the desired results for my site. The manual's detailed descriptions of Haunt's inner workings were particularly helpful in understanding how to leverage the flexibility of Scheme to customize my blog.</p>
|
<h2>Crafting My Own Template</h2>
|
||||||
<h2>Crafting My Own Template</h2>
|
<p>Moving from Hugo to Haunt required me to create my own template and customize my site's appearance. This was an exciting opportunity to apply the skills I had learned from David's course and experiment with Scheme in a practical context.</p>
|
||||||
<p>Moving from Hugo to Haunt required me to create my own template and customize my site's appearance. This was an exciting opportunity to apply the skills I had learned from David's course and experiment with Scheme in a practical context.</p>
|
<h4>Creating the Template</h4>
|
||||||
<h4>Creating the Template</h4>
|
<p>Haunt's flexibility allowed me to define my own theme layout and structure. Here's a snippet of my <code>haunt.scm</code> file, where I defined the theme layout and added custom footer content:</p>
|
||||||
<p>Haunt's flexibility allowed me to define my own theme layout and structure. Here's a snippet of my <code>haunt.scm</code> file, where I defined the theme layout and added custom footer content:</p>
|
<pre><code class="language-scheme">(use-modules (haunt asset)
|
||||||
<pre><code class="language-scheme">(use-modules (haunt asset)
|
(haunt builder blog)
|
||||||
(haunt builder blog)
|
(haunt builder atom)
|
||||||
(haunt builder atom)
|
(haunt builder assets)
|
||||||
(haunt builder assets)
|
(haunt reader commonmark)
|
||||||
(haunt reader commonmark)
|
(haunt site)
|
||||||
(haunt site)
|
(haunt post)
|
||||||
(haunt post)
|
(sxml simple) ; For HTML generation
|
||||||
(sxml simple) ; For HTML generation
|
(srfi srfi-1)
|
||||||
(srfi srfi-1)
|
(srfi srfi-19)) ; For date and time procedures
|
||||||
(srfi srfi-19)) ; For date and time procedures
|
|
||||||
|
;; Load custom templates
|
||||||
;; Load custom templates
|
(load "templates/post.scm")
|
||||||
(load "templates/post.scm")
|
|
||||||
|
(define (format-date date)
|
||||||
(define (format-date date)
|
(date->string date "~Y-~m-~d"))
|
||||||
(date->string date "~Y-~m-~d"))
|
|
||||||
|
;; Define a function to generate the URL for a post
|
||||||
;; Define a function to generate the URL for a post
|
(define (post-url post)
|
||||||
(define (post-url post)
|
(string-append "/" (post-slug post) ".html"))
|
||||||
(string-append "/" (post-slug post) ".html"))
|
|
||||||
|
;; Define a function to extract a summary from the post content
|
||||||
;; Define a function to extract a summary from the post content
|
(define (post-summary post)
|
||||||
(define (post-summary post)
|
(let ((content (post-sxml post)))
|
||||||
(let ((content (post-sxml post)))
|
(if (null? content)
|
||||||
(if (null? content)
|
""
|
||||||
""
|
(let ((first-paragraph (car content)))
|
||||||
(let ((first-paragraph (car content)))
|
(if (string? first-paragraph)
|
||||||
(if (string? first-paragraph)
|
(substring first-paragraph 0 (min 200 (string-length first-paragraph)))
|
||||||
(substring first-paragraph 0 (min 200 (string-length first-paragraph)))
|
(sxml->string first-paragraph))))))
|
||||||
(sxml->string first-paragraph))))))
|
|
||||||
|
;; Define the theme layout
|
||||||
;; Define the theme layout
|
(define (theme-layout site title content)
|
||||||
(define (theme-layout site title content)
|
(let ((current-year (number->string (date-year (current-date)))))
|
||||||
(let ((current-year (number->string (date-year (current-date)))))
|
`(html
|
||||||
`(html
|
(head
|
||||||
(head
|
(meta (@ (charset "utf-8")))
|
||||||
(meta (@ (charset "utf-8")))
|
(meta (@ (name "viewport") (content "width=device-width, initial-scale=1.0, shrink-to-fit=no")))
|
||||||
(meta (@ (name "viewport") (content "width=device-width, initial-scale=1.0, shrink-to-fit=no")))
|
(link (@ (rel "stylesheet") (href "/assets/palenight.css")))
|
||||||
(link (@ (rel "stylesheet") (href "/assets/palenight.css")))
|
(style
|
||||||
(style
|
" .craftering {
|
||||||
" .craftering {
|
margin: auto;
|
||||||
margin: auto;
|
width: 50%;
|
||||||
width: 50%;
|
text-align: center;
|
||||||
text-align: center;
|
}
|
||||||
}
|
.webring-text {
|
||||||
.webring-text {
|
text-align: center;
|
||||||
text-align: center;
|
margin-bottom: 20px;
|
||||||
margin-bottom: 20px;
|
color: white;
|
||||||
color: white;
|
}
|
||||||
}
|
.craftering a {
|
||||||
.craftering a {
|
color: #dddddd;
|
||||||
color: #dddddd;
|
}
|
||||||
}
|
.webring-text a {
|
||||||
.webring-text a {
|
color: #dddddd;
|
||||||
color: #dddddd;
|
}")
|
||||||
}")
|
(title ,title))
|
||||||
(title ,title))
|
(body
|
||||||
(body
|
(header (h1 ,(site-title site)))
|
||||||
(header (h1 ,(site-title site)))
|
(main ,content)
|
||||||
(main ,content)
|
(footer (@ (class "bg-black bottom-0 w-100 pa3") (role "contentinfo"))
|
||||||
(footer (@ (class "bg-black bottom-0 w-100 pa3") (role "contentinfo"))
|
(div (@ (class "flex justify-between"))
|
||||||
(div (@ (class "flex justify-between"))
|
(div (@ (class "webring-text"))
|
||||||
(div (@ (class "webring-text"))
|
(p "I am part of the " (a (@ (href "https://systemcrafters.net") (target "_blank")) "System Crafters") " webring:"))
|
||||||
(p "I am part of the " (a (@ (href "https://systemcrafters.net") (target "_blank")) "System Crafters") " webring:"))
|
(div (@ (class "craftering"))
|
||||||
(div (@ (class "craftering"))
|
(a (@ (href "https://craftering.systemcrafters.net/@glenneth/previous")) "←")
|
||||||
(a (@ (href "https://craftering.systemcrafters.net/@glenneth/previous")) "←")
|
(a (@ (href "https://craftering.systemcrafters.net/")) "craftering")
|
||||||
(a (@ (href "https://craftering.systemcrafters.net/")) "craftering")
|
(a (@ (href "https://craftering.systemcrafters.net/@glenneth/next")) "→"))))))))
|
||||||
(a (@ (href "https://craftering.systemcrafters.net/@glenneth/next")) "→"))))))))
|
|
||||||
|
;; Define the custom theme with a consistent layout for index
|
||||||
;; Define the custom theme with a consistent layout for index
|
(define my-theme
|
||||||
(define my-theme
|
(theme #:name "My Custom Theme"
|
||||||
(theme #:name "My Custom Theme"
|
#:layout theme-layout
|
||||||
#:layout theme-layout
|
#:post-template post-template
|
||||||
#:post-template post-template
|
#:collection-template
|
||||||
#:collection-template
|
(lambda (site title posts prefix)
|
||||||
(lambda (site title posts prefix)
|
`(div (@ (class "content"))
|
||||||
`(div (@ (class "content"))
|
(h2 ,title)
|
||||||
(h2 ,title)
|
(ul
|
||||||
(ul
|
,@(map (lambda (post)
|
||||||
,@(map (lambda (post)
|
`(li
|
||||||
`(li
|
(article
|
||||||
(article
|
(header
|
||||||
(header
|
(h3 (a (@ (href ,(post-url post))) ,(post-title post))))
|
||||||
(h3 (a (@ (href ,(post-url post))) ,(post-title post))))
|
(p ,(format-date (post-date post)))
|
||||||
(p ,(format-date (post-date post)))
|
(p ,(post-summary post))
|
||||||
(p ,(post-summary post))
|
(p (a (@ (href ,(post-url post))) "Read more...")))))
|
||||||
(p (a (@ (href ,(post-url post))) "Read more...")))))
|
posts))))))
|
||||||
posts))))))
|
|
||||||
|
;; Site configuration
|
||||||
;; Site configuration
|
(site #:title "Just Another Personal Blog"
|
||||||
(site #:title "Just Another Personal Blog"
|
#:domain "glenneth.srht.site"
|
||||||
#:domain "glenneth.srht.site"
|
#:default-metadata
|
||||||
#:default-metadata
|
'((author . "Glenn Thompson")
|
||||||
'((author . "Glenn Thompson")
|
(email . "glenn@kirstol.org"))
|
||||||
(email . "glenn@kirstol.org"))
|
#:readers (list commonmark-reader)
|
||||||
#:readers (list commonmark-reader)
|
#:builders (list
|
||||||
#:builders (list
|
(blog #:theme my-theme)
|
||||||
(blog #:theme my-theme)
|
(atom-feed)
|
||||||
(atom-feed)
|
(atom-feeds-by-tag)
|
||||||
(atom-feeds-by-tag)
|
(static-directory "images")
|
||||||
(static-directory "images")
|
(static-directory "assets")))
|
||||||
(static-directory "assets")))
|
</code></pre>
|
||||||
</code></pre>
|
<h3>Customizing the CSS</h3>
|
||||||
<h3>Customizing the CSS</h3>
|
<p>To give my site a personalized touch, I crafted a CSS stylesheet that matched my aesthetic preferences. Here’s an excerpt from my <code>palenight.css</code> file:</p>
|
||||||
<p>To give my site a personalized touch, I crafted a CSS stylesheet that matched my aesthetic preferences. Here’s an excerpt from my <code>palenight.css</code> file:</p>
|
<pre><code class="language-css">body {
|
||||||
<pre><code class="language-css">body {
|
display: flex;
|
||||||
display: flex;
|
justify-content: center;
|
||||||
justify-content: center;
|
padding: 10px;
|
||||||
padding: 10px;
|
}
|
||||||
}
|
|
||||||
|
.content, header, footer, main {
|
||||||
.content, header, footer, main {
|
max-width: 90%;
|
||||||
max-width: 90%;
|
padding: 0 5%;
|
||||||
padding: 0 5%;
|
}
|
||||||
}
|
|
||||||
|
header {
|
||||||
header {
|
text-align: center;
|
||||||
text-align: center;
|
margin-bottom: 20px;
|
||||||
margin-bottom: 20px;
|
}
|
||||||
}
|
|
||||||
|
footer {
|
||||||
footer {
|
text-align: center;
|
||||||
text-align: center;
|
margin-top: 20px;
|
||||||
margin-top: 20px;
|
}
|
||||||
}
|
|
||||||
|
ul {
|
||||||
ul {
|
list-style-type: none;
|
||||||
list-style-type: none;
|
padding: 0;
|
||||||
padding: 0;
|
}
|
||||||
}
|
|
||||||
|
li {
|
||||||
li {
|
margin-bottom: 20px;
|
||||||
margin-bottom: 20px;
|
}
|
||||||
}
|
|
||||||
|
a {
|
||||||
a {
|
text-decoration: none;
|
||||||
text-decoration: none;
|
}
|
||||||
}
|
|
||||||
|
a:hover {
|
||||||
a:hover {
|
text-decoration: underline;
|
||||||
text-decoration: underline;
|
}
|
||||||
}
|
|
||||||
|
body {
|
||||||
body {
|
background-color: #292d3e;
|
||||||
background-color: #292d3e;
|
color: #d0d0d0;
|
||||||
color: #d0d0d0;
|
}
|
||||||
}
|
|
||||||
|
a {
|
||||||
a {
|
color: #82aaff;
|
||||||
color: #82aaff;
|
}
|
||||||
}
|
|
||||||
|
h1, h2, h3, h4, h5, h6 {
|
||||||
h1, h2, h3, h4, h5, h6 {
|
color: #c792ea;
|
||||||
color: #c792ea;
|
}
|
||||||
}
|
|
||||||
|
.content {
|
||||||
.content {
|
background-color: #1e1e2e;
|
||||||
background-color: #1e1e2e;
|
padding: 20px;
|
||||||
padding: 20px;
|
border-radius: 5px;
|
||||||
border-radius: 5px;
|
}
|
||||||
}
|
|
||||||
|
article {
|
||||||
article {
|
background-color: #282a36;
|
||||||
background-color: #282a36;
|
padding: 15px;
|
||||||
padding: 15px;
|
border-radius: 8px;
|
||||||
border-radius: 8px;
|
margin-bottom: 20px;
|
||||||
margin-bottom: 20px;
|
}
|
||||||
}
|
|
||||||
|
article header {
|
||||||
article header {
|
margin-bottom: 10px;
|
||||||
margin-bottom: 10px;
|
}
|
||||||
}
|
|
||||||
|
.date {
|
||||||
.date {
|
color: #6272a4;
|
||||||
color: #6272a4;
|
font-size: 0.9em;
|
||||||
font-size: 0.9em;
|
}
|
||||||
}
|
|
||||||
|
/* Additional styles for the craftering */
|
||||||
/* Additional styles for the craftering */
|
.craftering {
|
||||||
.craftering {
|
margin: auto;
|
||||||
margin: auto;
|
width: 50%;
|
||||||
width: 50%;
|
text-align: center;
|
||||||
text-align: center;
|
}
|
||||||
}
|
|
||||||
|
.webring-text {
|
||||||
.webring-text {
|
text-align: center;
|
||||||
text-align: center;
|
margin-bottom: 20px;
|
||||||
margin-bottom: 20px;
|
color: white;
|
||||||
color: white;
|
}
|
||||||
}
|
|
||||||
|
.craftering a {
|
||||||
.craftering a {
|
color: #dddddd;
|
||||||
color: #dddddd;
|
}
|
||||||
}
|
|
||||||
|
.webring-text a {
|
||||||
.webring-text a {
|
color: #dddddd;
|
||||||
color: #dddddd;
|
}
|
||||||
}
|
|
||||||
|
/* Additions for mobile device readability */
|
||||||
/* Additions for mobile device readability */
|
|
||||||
|
meta {
|
||||||
meta {
|
name: viewport;
|
||||||
name: viewport;
|
content: width=device-width, initial-scale=1, shrink-to-fit=no;
|
||||||
content: width=device-width, initial-scale=1, shrink-to-fit=no;
|
}
|
||||||
}
|
|
||||||
|
@media screen and (max-width: 767px) {
|
||||||
@media screen and (max-width: 767px) {
|
/* Customize styles for smaller screens */
|
||||||
/* Customize styles for smaller screens */
|
.logo {
|
||||||
.logo {
|
max-width: 200px;
|
||||||
max-width: 200px;
|
}
|
||||||
}
|
|
||||||
|
}
|
||||||
}
|
</code></pre>
|
||||||
</code></pre>
|
<p>I use the <code>doom-palenight</code> theme in Emacs, my preferred text editor, and I wanted my site to match that aesthetic.</p>
|
||||||
<p>I use the <code>doom-palenight</code> theme in Emacs, my preferred text editor, and I wanted my site to match that aesthetic.</p>
|
<h3>Publishing with Haunt and Hut</h3>
|
||||||
<h3>Publishing with Haunt and Hut</h3>
|
<p>In addition to using Haunt, I adopted hut, a set of command-line tools for interacting with SourceHut, to publish my blog. This streamlined my workflow, making it easier to manage and deploy my site directly from my local environment.</p>
|
||||||
<p>In addition to using Haunt, I adopted hut, a set of command-line tools for interacting with SourceHut, to publish my blog. This streamlined my workflow, making it easier to manage and deploy my site directly from my local environment.</p>
|
<h3>Conclusion</h3>
|
||||||
<h3>Conclusion</h3>
|
<p>Transitioning from Hugo to Haunt, learning Scheme, and embracing GNU Guix has been an enriching experience. It's not just about using new tools; it's about joining a community that values simplicity, transparency, and collaboration. If you're curious about Scheme or GNU Guix, I highly recommend checking out David Wilson's course on System Crafters and joining the discussions on IRC.</p>
|
||||||
<p>Transitioning from Hugo to Haunt, learning Scheme, and embracing GNU Guix has been an enriching experience. It's not just about using new tools; it's about joining a community that values simplicity, transparency, and collaboration. If you're curious about Scheme or GNU Guix, I highly recommend checking out David Wilson's course on System Crafters and joining the discussions on IRC.</p>
|
<p>I am not a developer of any kind, and learning Scheme has opened my eyes as to how I can craft an environment that I want to work in, and not endure a working environment that the computer is forcing upon me.</p>
|
||||||
<p>I am not a developer of any kind, and learning Scheme has opened my eyes as to how I can craft an environment that I want to work in, and not endure a working environment that the computer is forcing upon me.</p>
|
<p>Thank you for reading, and stay tuned for more updates on my journey!</p>
|
||||||
<p>Thank you for reading, and stay tuned for more updates on my journey!</p>
|
|
||||||
|
</article>
|
||||||
</article>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</main>
|
||||||
</main>
|
<footer class="bg-base-darker text-palenight-200 py-12 border-t border-palenight-400/20">
|
||||||
<footer class="bg-base-darker text-palenight-200 py-12 border-t border-palenight-400/20">
|
<div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
<div class="text-center">
|
||||||
<div class="text-center">
|
<p class="text-palenight-300">© 2026 Glenn Thompson. All rights reserved.</p>
|
||||||
<p class="text-palenight-300">© 2024 Glenn Thompson. All rights reserved.</p>
|
<div class="webring-text mt-6">
|
||||||
<div class="webring-text mt-6">
|
<p class="text-palenight-300">I am part of the <a href="https://systemcrafters.net" target="_blank" class="text-accent-blue hover:text-accent-cyan">System Crafters</a> webring:</p>
|
||||||
<p class="text-palenight-300">I am part of the <a href="https://systemcrafters.net" target="_blank" class="text-accent-blue hover:text-accent-cyan">System Crafters</a> webring:</p>
|
</div>
|
||||||
</div>
|
<div class="craftering mt-2 flex items-center justify-center gap-4 text-accent-blue">
|
||||||
<div class="craftering mt-2 flex items-center justify-center gap-4 text-accent-blue">
|
<a href="https://craftering.systemcrafters.net/@glenneth/previous" class="hover:text-accent-cyan">Previous</a>
|
||||||
<a href="https://craftering.systemcrafters.net/@glenneth/previous" class="hover:text-accent-cyan">Previous</a>
|
<a href="https://craftering.systemcrafters.net/@glenneth" class="hover:text-accent-cyan">Random</a>
|
||||||
<a href="https://craftering.systemcrafters.net/@glenneth" class="hover:text-accent-cyan">Random</a>
|
<a href="https://craftering.systemcrafters.net/@glenneth/next" class="hover:text-accent-cyan">Next</a>
|
||||||
<a href="https://craftering.systemcrafters.net/@glenneth/next" class="hover:text-accent-cyan">Next</a>
|
</div>
|
||||||
</div>
|
<p class="text-palenight-300 mt-2">
|
||||||
<p class="text-palenight-300 mt-2">
|
<a href="mailto:glenn@glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenn@glenneth.org</a> |
|
||||||
<a href="mailto:glenn@glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenn@glenneth.org</a> |
|
<a href="https://glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenneth.org</a>
|
||||||
<a href="https://glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenneth.org</a>
|
</p>
|
||||||
</p>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</footer>
|
||||||
</footer>
|
</body>
|
||||||
</body>
|
|
||||||
</html>
|
</html>
|
||||||
|
|
@ -1,190 +1,189 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en" class="bg-base-bg">
|
<html lang="en" class="bg-base-bg">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<meta name="description" content="">
|
<meta name="description" content="">
|
||||||
<meta property="og:title" content="A Journey Through GNU Guix: From Installation to Returning to Arch Linux">
|
<meta property="og:title" content="Blog Post">
|
||||||
<meta property="og:description" content="">
|
<meta property="og:description" content="">
|
||||||
<meta property="og:url" content="https://glenneth.orgcontent/posts/2024-07-26-gnu-guix-journey">
|
<meta property="og:url" content="https://glenneth.orgcontent/posts/2024-07-26-gnu-guix-journey">
|
||||||
<title>A Journey Through GNU Guix: From Installation to Returning to Arch Linux - Glenn Thompson</title>
|
<title>Blog Post - Glenn Thompson</title>
|
||||||
<link rel="alternate" type="application/rss+xml" title="Glenn Thompson's Blog" href="/feed.xml" />
|
<link rel="alternate" type="application/rss+xml" title="Glenn Thompson's Blog" href="/feed.xml" />
|
||||||
<link href="../../dist/styles.css" rel="stylesheet">
|
<link href="/dist/styles.css" rel="stylesheet">
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Merriweather:wght@400;700&family=JetBrains+Mono:wght@400;700&display=swap" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Merriweather:wght@400;700&family=JetBrains+Mono:wght@400;700&display=swap" rel="stylesheet">
|
||||||
<style>
|
<style>
|
||||||
.prose-palenight {
|
.prose-palenight {
|
||||||
--tw-prose-body: #bfc7d5;
|
--tw-prose-body: #bfc7d5;
|
||||||
--tw-prose-headings: #ffd580;
|
--tw-prose-headings: #ffd580;
|
||||||
--tw-prose-links: #82aaff;
|
--tw-prose-links: #82aaff;
|
||||||
--tw-prose-code: #c792ea;
|
--tw-prose-code: #c792ea;
|
||||||
--tw-prose-pre-bg: #1b1e2b;
|
--tw-prose-pre-bg: #1b1e2b;
|
||||||
}
|
}
|
||||||
.prose h2 {
|
.prose h2 {
|
||||||
color: var(--tw-prose-headings);
|
color: var(--tw-prose-headings);
|
||||||
font-family: Merriweather, serif;
|
font-family: Merriweather, serif;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
font-size: 1.5rem;
|
font-size: 1.5rem;
|
||||||
margin-top: 2rem;
|
margin-top: 2rem;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
}
|
}
|
||||||
.prose p {
|
.prose p {
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
line-height: 1.625;
|
line-height: 1.625;
|
||||||
}
|
}
|
||||||
.prose a {
|
.prose a {
|
||||||
color: var(--tw-prose-links);
|
color: var(--tw-prose-links);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
.prose a:hover {
|
.prose a:hover {
|
||||||
color: #89ddff;
|
color: #89ddff;
|
||||||
}
|
}
|
||||||
.prose code {
|
.prose code {
|
||||||
color: var(--tw-prose-code);
|
color: var(--tw-prose-code);
|
||||||
font-family: 'JetBrains Mono', monospace;
|
font-family: 'JetBrains Mono', monospace;
|
||||||
}
|
}
|
||||||
.prose pre {
|
.prose pre {
|
||||||
background-color: var(--tw-prose-pre-bg);
|
background-color: var(--tw-prose-pre-bg);
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
}
|
}
|
||||||
.prose ul, .prose ol {
|
.prose ul, .prose ol {
|
||||||
margin-top: 0.5rem;
|
margin-top: 0.5rem;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
padding-left: 1.5rem;
|
padding-left: 1.5rem;
|
||||||
}
|
}
|
||||||
.prose ul {
|
.prose ul {
|
||||||
list-style-type: disc;
|
list-style-type: disc;
|
||||||
}
|
}
|
||||||
.prose ol {
|
.prose ol {
|
||||||
list-style-type: decimal;
|
list-style-type: decimal;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body class="bg-base-bg text-palenight-50">
|
<body class="bg-base-bg text-palenight-50">
|
||||||
<nav class="bg-base-darker/80 backdrop-blur-sm shadow-sm border-b border-palenight-400/20 mb-8">
|
<nav class="bg-base-darker/80 backdrop-blur-sm shadow-sm border-b border-palenight-400/20 mb-8">
|
||||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<div class="flex items-center justify-between h-16">
|
<div class="flex items-center justify-between h-16">
|
||||||
<a href="/" class="text-accent-yellow font-serif text-xl font-bold">Glenn Thompson</a>
|
<a href="/" class="text-accent-yellow font-serif text-xl font-bold">Glenn Thompson</a>
|
||||||
<div class="flex items-center gap-2 text-accent-yellow text-sm font-bold">
|
<div class="flex items-center gap-2 text-accent-yellow text-sm font-bold">
|
||||||
<span>personal, tech, gnu, guix, swaywm, nvidia</span>
|
<span>Tech</span>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<time datetime="2024-07-26 10:30">July 26, 2024</time>
|
<time datetime="undefined">Invalid Date</time>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<span>7 min read</span>
|
<span>7 min read</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<main class="pt-24 pb-16 px-4">
|
<main class="pt-24 pb-16 px-4">
|
||||||
<div class="max-w-4xl mx-auto">
|
<div class="max-w-4xl mx-auto">
|
||||||
<div class="content text-palenight-100 space-y-6">
|
<div class="content text-palenight-100 space-y-6">
|
||||||
<header class="mb-8">
|
<header class="mb-8">
|
||||||
<h1 class="text-4xl font-serif font-bold text-accent-yellow">A Journey Through GNU Guix: From Installation to Returning to Arch Linux</h1>
|
<h1 class="text-4xl font-serif font-bold text-accent-yellow">Blog Post</h1>
|
||||||
<div class="flex items-center gap-4 text-palenight-300 mt-4">
|
<div class="flex items-center gap-4 text-palenight-300 mt-4">
|
||||||
<time datetime="2024-07-26 10:30">2024-07-26 10:30</time>
|
<time datetime=""></time>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<span>7 min read</span>
|
<span>7 min read</span>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<span>By Glenn Thompson</span>
|
<span>By Glenn Thompson</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-wrap gap-2 mt-4">
|
</header>
|
||||||
<span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">personal</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">tech</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">gnu</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">guix</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">swaywm</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">nvidia</span>
|
|
||||||
</div>
|
<article class="prose prose-palenight max-w-none">
|
||||||
</header>
|
<hr>
|
||||||
|
<h2>title: A Journey Through GNU Guix: From Installation to Returning to Arch Linux<br>author: Glenn Thompson<br>date: 2024-07-26 10:30<br>tags: personal, tech, gnu, guix, swaywm, nvidia</h2>
|
||||||
<article class="prose prose-palenight max-w-none">
|
<h1>A Journey Through GNU Guix: From Installation to Returning to Arch Linux</h1>
|
||||||
<h1>A Journey Through GNU Guix: From Installation to Returning to Arch Linux</h1>
|
<p>As a long-time user of Arch Linux, I decided to explore the world of GNU Guix to see if it could better suit my needs, especially with my growing interest in functional package management. The journey was insightful, filled with learning experiences, but ultimately led me back to the reliable shores of Arch. Here's a detailed account of my venture into GNU Guix, adding non-GNU channels, dealing with Nvidia drivers, running SwayWM, and the eventual retreat to Arch.</p>
|
||||||
<p>As a long-time user of Arch Linux, I decided to explore the world of GNU Guix to see if it could better suit my needs, especially with my growing interest in functional package management. The journey was insightful, filled with learning experiences, but ultimately led me back to the reliable shores of Arch. Here's a detailed account of my venture into GNU Guix, adding non-GNU channels, dealing with Nvidia drivers, running SwayWM, and the eventual retreat to Arch.</p>
|
<h2>Installation of GNU Guix</h2>
|
||||||
<h2>Installation of GNU Guix</h2>
|
<p>The installation process of GNU Guix was straightforward, thanks to the well-documented guide provided on their official website. Here's a quick rundown of the steps I followed:</p>
|
||||||
<p>The installation process of GNU Guix was straightforward, thanks to the well-documented guide provided on their official website. Here's a quick rundown of the steps I followed:</p>
|
<ol>
|
||||||
<ol>
|
<li><strong>Downloading the Installation Image</strong>: I started by downloading the latest ISO image from the <a href="https://guix.gnu.org/">GNU Guix website</a>.</li>
|
||||||
<li><strong>Downloading the Installation Image</strong>: I started by downloading the latest ISO image from the <a href="https://guix.gnu.org/">GNU Guix website</a>.</li>
|
<li><strong>Creating a Bootable USB</strong>: Using <code>dd</code>, I created a bootable USB stick to install GNU Guix on my system.</li>
|
||||||
<li><strong>Creating a Bootable USB</strong>: Using <code>dd</code>, I created a bootable USB stick to install GNU Guix on my system.</li>
|
<li><strong>Booting into the Installer</strong>: Booting from the USB was smooth, and I was greeted with the GNU Guix installer. The installer's simplicity reminded me of early days with Arch, where a minimalistic approach is preferred.</li>
|
||||||
<li><strong>Booting into the Installer</strong>: Booting from the USB was smooth, and I was greeted with the GNU Guix installer. The installer's simplicity reminded me of early days with Arch, where a minimalistic approach is preferred.</li>
|
<li><strong>Partitioning and Setting Up File Systems</strong>: I partitioned my drive using <code>fdisk</code> and set up my file systems. I opted for ext4 for simplicity.</li>
|
||||||
<li><strong>Partitioning and Setting Up File Systems</strong>: I partitioned my drive using <code>fdisk</code> and set up my file systems. I opted for ext4 for simplicity.</li>
|
<li><strong>Configuring the System</strong>: Following the partition setup, I proceeded to configure my system by selecting the required packages and services. I decided to go with the Sway window manager as it's my preferred choice on Arch.</li>
|
||||||
<li><strong>Configuring the System</strong>: Following the partition setup, I proceeded to configure my system by selecting the required packages and services. I decided to go with the Sway window manager as it's my preferred choice on Arch.</li>
|
</ol>
|
||||||
</ol>
|
<h2>System Configuration</h2>
|
||||||
<h2>System Configuration</h2>
|
<p>During the installation process a window appears informing you that the <code>config.scm</code> file is located at <code>/etc/config.scm</code>. The first time I installed gnu guix on my work laptop I missed this message (pilot error) and I had to ask in the <a href="https://systemcrafters.net">System Crafters</a> IRC channel at <code>irc.libera.chat</code>, <code>#systemcrafters</code>. Come and join. It's a great place to be and the community there are an absolute treasure. Use your favourite IRC client or join through the webchat <a href="https://web.libera.chat/?channel=#systemcrafters">here</a>. We would be glad to see you. Tell them glenneth sent you :).</p>
|
||||||
<p>During the installation process a window appears informing you that the <code>config.scm</code> file is located at <code>/etc/config.scm</code>. The first time I installed gnu guix on my work laptop I missed this message (pilot error) and I had to ask in the <a href="https://systemcrafters.net">System Crafters</a> IRC channel at <code>irc.libera.chat</code>, <code>#systemcrafters</code>. Come and join. It's a great place to be and the community there are an absolute treasure. Use your favourite IRC client or join through the webchat <a href="https://web.libera.chat/?channel=#systemcrafters">here</a>. We would be glad to see you. Tell them glenneth sent you :).</p>
|
<p>My point is, I missed some vital information, so to the guix manual online it was. This can be found <a href="https://guix.gnu.org/manual/devel/en/guix.html">here</a>. This link will take you to the dev version of the manual. Something else they don't tell you. This version has a little more detail than the standard manual, and I believe details extra features and may even be a little more up to date.</p>
|
||||||
<p>My point is, I missed some vital information, so to the guix manual online it was. This can be found <a href="https://guix.gnu.org/manual/devel/en/guix.html">here</a>. This link will take you to the dev version of the manual. Something else they don't tell you. This version has a little more detail than the standard manual, and I believe details extra features and may even be a little more up to date.</p>
|
<h2>Adding Non-GNU Channels</h2>
|
||||||
<h2>Adding Non-GNU Channels</h2>
|
<p>One of the standout features of GNU Guix is the ability to add non-GNU channels to access a wider array of software packages. Here's how I did it:</p>
|
||||||
<p>One of the standout features of GNU Guix is the ability to add non-GNU channels to access a wider array of software packages. Here's how I did it:</p>
|
<ol>
|
||||||
<ol>
|
<li><strong>Editing Channels</strong>: I edited the <code>~/.config/guix/channels.scm</code> file to include non-GNU channels.<pre><code class="language-scheme">(cons* (channel
|
||||||
<li><strong>Editing Channels</strong>: I edited the <code>~/.config/guix/channels.scm</code> file to include non-GNU channels.<pre><code class="language-scheme">(cons* (channel
|
(name 'non-gnu)
|
||||||
(name 'non-gnu)
|
(url "https://example.com/non-gnu-channel.git"))
|
||||||
(url "https://example.com/non-gnu-channel.git"))
|
%default-channels)
|
||||||
%default-channels)
|
</code></pre>
|
||||||
</code></pre>
|
</li>
|
||||||
</li>
|
<li><strong>Updating Channels</strong>: Running <code>guix pull</code> updated my system to include packages from the non-GNU channel.</li>
|
||||||
<li><strong>Updating Channels</strong>: Running <code>guix pull</code> updated my system to include packages from the non-GNU channel.</li>
|
</ol>
|
||||||
</ol>
|
<h2>Installing Nvidia Drivers</h2>
|
||||||
<h2>Installing Nvidia Drivers</h2>
|
<p>Being a gamer and someone who requires GPU acceleration for certain tasks, Nvidia drivers were a must. Here's the process I followed:</p>
|
||||||
<p>Being a gamer and someone who requires GPU acceleration for certain tasks, Nvidia drivers were a must. Here's the process I followed:</p>
|
<ol>
|
||||||
<ol>
|
<li><strong>Adding Nvidia Channel</strong>: Added a channel that includes Nvidia drivers.</li>
|
||||||
<li><strong>Adding Nvidia Channel</strong>: Added a channel that includes Nvidia drivers.</li>
|
<li><strong>Installing Drivers</strong>: Installed the drivers using <code>guix package -i nvidia-driver</code>.</li>
|
||||||
<li><strong>Installing Drivers</strong>: Installed the drivers using <code>guix package -i nvidia-driver</code>.</li>
|
<li><strong>Configuring the System</strong>: I had to manually configure Xorg to use the Nvidia drivers, which involved editing the Xorg configuration files.</li>
|
||||||
<li><strong>Configuring the System</strong>: I had to manually configure Xorg to use the Nvidia drivers, which involved editing the Xorg configuration files.</li>
|
</ol>
|
||||||
</ol>
|
<h2>Creating My Home Environment</h2>
|
||||||
<h2>Creating My Home Environment</h2>
|
<p>To personalize my setup further, I used <code>guix home import</code> to create my own home environment and add packages. This allowed me to have a consistent environment across different machines. I also edited the <code>config.scm</code> file to include the latest Linux kernels and Nvidia drivers.</p>
|
||||||
<p>To personalize my setup further, I used <code>guix home import</code> to create my own home environment and add packages. This allowed me to have a consistent environment across different machines. I also edited the <code>config.scm</code> file to include the latest Linux kernels and Nvidia drivers.</p>
|
<p>Additionally, I used the <code>syncthing home-service-type</code> in my <code>home-configuration.scm</code> file to install and configure Syncthing. This setup ensured my files were always in sync across devices, which is crucial for my workflow.</p>
|
||||||
<p>Additionally, I used the <code>syncthing home-service-type</code> in my <code>home-configuration.scm</code> file to install and configure Syncthing. This setup ensured my files were always in sync across devices, which is crucial for my workflow.</p>
|
<h2>GNOME</h2>
|
||||||
<h2>GNOME</h2>
|
<p>All was good and I had a solid desktop environment running, even though it was gnome desktop. I had never used gnome, and I am more at home with a keyboard driven workflow. I had come from hyprland on Arch and wanted to get back to that workflow. The option I was presented with, in order to continue using wayland, pipewire etc. was SwayWM.</p>
|
||||||
<p>All was good and I had a solid desktop environment running, even though it was gnome desktop. I had never used gnome, and I am more at home with a keyboard driven workflow. I had come from hyprland on Arch and wanted to get back to that workflow. The option I was presented with, in order to continue using wayland, pipewire etc. was SwayWM.</p>
|
<h2>Sway</h2>
|
||||||
<h2>Sway</h2>
|
<p>Installing SwayWM and it's dependencies and nice to haves was relatively straightforward. add the required packages, sway, swaybg, swayidle, swaylock, to my home-configuration.scm gile and run <code>guix home reconfigure</code> easy! The packages were installed and we were good to go.</p>
|
||||||
<p>Installing SwayWM and it's dependencies and nice to haves was relatively straightforward. add the required packages, sway, swaybg, swayidle, swaylock, to my home-configuration.scm gile and run <code>guix home reconfigure</code> easy! The packages were installed and we were good to go.</p>
|
<p>The first issue I encountered was that sway does not run with the proprietary nvidia drivers, this was on the work laptop. I could get it to run but only after adding the <code>--unsupported-gpu</code> flag to <code>exec sway</code>. Lo and behold, we had a default sway window manager running.</p>
|
||||||
<p>The first issue I encountered was that sway does not run with the proprietary nvidia drivers, this was on the work laptop. I could get it to run but only after adding the <code>--unsupported-gpu</code> flag to <code>exec sway</code>. Lo and behold, we had a default sway window manager running.</p>
|
<h2>Challenges with SwayWM and SMB Shares</h2>
|
||||||
<h2>Challenges with SwayWM and SMB Shares</h2>
|
<p>With the system set up, I ran into a major roadblock: accessing SMB shares in a file manager while running SwayWM.</p>
|
||||||
<p>With the system set up, I ran into a major roadblock: accessing SMB shares in a file manager while running SwayWM.</p>
|
<ol>
|
||||||
<ol>
|
<li><strong>Thunar and GNOME Files</strong>: Neither Thunar nor the GNOME Files application could access SMB shares. This was crucial for my workflow as I frequently access network shares.</li>
|
||||||
<li><strong>Thunar and GNOME Files</strong>: Neither Thunar nor the GNOME Files application could access SMB shares. This was crucial for my workflow as I frequently access network shares.</li>
|
<li><strong>Troubleshooting</strong>: I tried various solutions, including installing additional packages and tweaking configurations, but nothing seemed to work.</li>
|
||||||
<li><strong>Troubleshooting</strong>: I tried various solutions, including installing additional packages and tweaking configurations, but nothing seemed to work.</li>
|
<li><strong>Community Support</strong>: I reached out to the GNU Guix community for help. While they were supportive, the solutions provided didn't resolve my issues.</li>
|
||||||
<li><strong>Community Support</strong>: I reached out to the GNU Guix community for help. While they were supportive, the solutions provided didn't resolve my issues.</li>
|
</ol>
|
||||||
</ol>
|
<p>To ensure that the problem was not hardware-related, I went out and purchased a Lenovo ThinkPad E16 Gen 1. I upgraded the RAM to 48GB and installed a Lenovo 2TB SSD to make it my personal laptop. However, even on this new setup, I faced the same issues accessing SMB shares and some networking services just wouldn't work.</p>
|
||||||
<p>To ensure that the problem was not hardware-related, I went out and purchased a Lenovo ThinkPad E16 Gen 1. I upgraded the RAM to 48GB and installed a Lenovo 2TB SSD to make it my personal laptop. However, even on this new setup, I faced the same issues accessing SMB shares and some networking services just wouldn't work.</p>
|
<p>I tried deleting the <code>gdm</code> login manager in my system configuration file, but after rebooting it was still showing the gnome login window. This was after reading somewhere online that sway was not on friendly terms with the gdm login manager.</p>
|
||||||
<p>I tried deleting the <code>gdm</code> login manager in my system configuration file, but after rebooting it was still showing the gnome login window. This was after reading somewhere online that sway was not on friendly terms with the gdm login manager.</p>
|
<h2>Returning to Arch Linux</h2>
|
||||||
<h2>Returning to Arch Linux</h2>
|
<p>After several days of troubleshooting and not being able to access my SMB shares reliably, I made the difficult decision to revert to Arch Linux. The steps were:</p>
|
||||||
<p>After several days of troubleshooting and not being able to access my SMB shares reliably, I made the difficult decision to revert to Arch Linux. The steps were:</p>
|
<ol>
|
||||||
<ol>
|
<li><strong>Reinstalling Arch</strong>: I reinstalled Arch Linux using my tried-and-tested setup process.</li>
|
||||||
<li><strong>Reinstalling Arch</strong>: I reinstalled Arch Linux using my tried-and-tested setup process.</li>
|
<li><strong>Configuring SwayWM</strong>: Set up SwayWM and ensured all my applications were running smoothly.</li>
|
||||||
<li><strong>Configuring SwayWM</strong>: Set up SwayWM and ensured all my applications were running smoothly.</li>
|
<li><strong>Accessing SMB Shares</strong>: Accessing SMB shares was seamless, just as it was before my experiment with GNU Guix.</li>
|
||||||
<li><strong>Accessing SMB Shares</strong>: Accessing SMB shares was seamless, just as it was before my experiment with GNU Guix.</li>
|
</ol>
|
||||||
</ol>
|
<h2>Conclusion</h2>
|
||||||
<h2>Conclusion</h2>
|
<p>I am still running GNU guix on the work laptop, I had to cave on my personal laptop and revert to Arch. My journey with GNU Guix was both enlightening and challenging. While I appreciate the functional package management and the philosophy behind GNU Guix, certain practical issues, like accessing SMB shares, were deal-breakers for my workflow. Arch Linux continues to be my go-to distribution, providing the flexibility and reliability I need for my daily tasks. So, at the moment I am using my personal laptop for work and still trying to figure out the issues I am having on my work laptop. But, to be honest, I prefer working on the thinkpad over working on the MSI laptop that work handed out :).</p>
|
||||||
<p>I am still running GNU guix on the work laptop, I had to cave on my personal laptop and revert to Arch. My journey with GNU Guix was both enlightening and challenging. While I appreciate the functional package management and the philosophy behind GNU Guix, certain practical issues, like accessing SMB shares, were deal-breakers for my workflow. Arch Linux continues to be my go-to distribution, providing the flexibility and reliability I need for my daily tasks. So, at the moment I am using my personal laptop for work and still trying to figure out the issues I am having on my work laptop. But, to be honest, I prefer working on the thinkpad over working on the MSI laptop that work handed out :).</p>
|
<p>If you're an enthusiast looking to explore new package management paradigms, I highly recommend giving GNU Guix a try. Just be prepared for a few hiccups along the way, and always have a backup plan!</p>
|
||||||
<p>If you're an enthusiast looking to explore new package management paradigms, I highly recommend giving GNU Guix a try. Just be prepared for a few hiccups along the way, and always have a backup plan!</p>
|
<hr>
|
||||||
<hr>
|
<p>Feel free to share your thoughts and experiences with GNU Guix or any other distributions you've tried. Let's keep the conversation going!</p>
|
||||||
<p>Feel free to share your thoughts and experiences with GNU Guix or any other distributions you've tried. Let's keep the conversation going!</p>
|
<h2>Shameless plug</h2>
|
||||||
<h2>Shameless plug</h2>
|
<p>Go <a href="https://systemcrafters.net/community/">here</a> to find all the ways you can engage with the SystemCrafters community. It's a great place to hang out and discuss all thing craftery. You will also notice the Craftering ring that I am a part of. Click the links and see blogs by some of the community members. Always interesting to read what other Crafters are up to.</p>
|
||||||
<p>Go <a href="https://systemcrafters.net/community/">here</a> to find all the ways you can engage with the SystemCrafters community. It's a great place to hang out and discuss all thing craftery. You will also notice the Craftering ring that I am a part of. Click the links and see blogs by some of the community members. Always interesting to read what other Crafters are up to.</p>
|
<p>Thanks for taking the time to read my blog post. It is greatly appreciated, and I hope you come back.</p>
|
||||||
<p>Thanks for taking the time to read my blog post. It is greatly appreciated, and I hope you come back.</p>
|
<p>Happy Hacking!!</p>
|
||||||
<p>Happy Hacking!!</p>
|
|
||||||
|
</article>
|
||||||
</article>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</main>
|
||||||
</main>
|
<footer class="bg-base-darker text-palenight-200 py-12 border-t border-palenight-400/20">
|
||||||
<footer class="bg-base-darker text-palenight-200 py-12 border-t border-palenight-400/20">
|
<div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
<div class="text-center">
|
||||||
<div class="text-center">
|
<p class="text-palenight-300">© 2026 Glenn Thompson. All rights reserved.</p>
|
||||||
<p class="text-palenight-300">© 2024 Glenn Thompson. All rights reserved.</p>
|
<div class="webring-text mt-6">
|
||||||
<div class="webring-text mt-6">
|
<p class="text-palenight-300">I am part of the <a href="https://systemcrafters.net" target="_blank" class="text-accent-blue hover:text-accent-cyan">System Crafters</a> webring:</p>
|
||||||
<p class="text-palenight-300">I am part of the <a href="https://systemcrafters.net" target="_blank" class="text-accent-blue hover:text-accent-cyan">System Crafters</a> webring:</p>
|
</div>
|
||||||
</div>
|
<div class="craftering mt-2 flex items-center justify-center gap-4 text-accent-blue">
|
||||||
<div class="craftering mt-2 flex items-center justify-center gap-4 text-accent-blue">
|
<a href="https://craftering.systemcrafters.net/@glenneth/previous" class="hover:text-accent-cyan">Previous</a>
|
||||||
<a href="https://craftering.systemcrafters.net/@glenneth/previous" class="hover:text-accent-cyan">Previous</a>
|
<a href="https://craftering.systemcrafters.net/@glenneth" class="hover:text-accent-cyan">Random</a>
|
||||||
<a href="https://craftering.systemcrafters.net/@glenneth" class="hover:text-accent-cyan">Random</a>
|
<a href="https://craftering.systemcrafters.net/@glenneth/next" class="hover:text-accent-cyan">Next</a>
|
||||||
<a href="https://craftering.systemcrafters.net/@glenneth/next" class="hover:text-accent-cyan">Next</a>
|
</div>
|
||||||
</div>
|
<p class="text-palenight-300 mt-2">
|
||||||
<p class="text-palenight-300 mt-2">
|
<a href="mailto:glenn@glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenn@glenneth.org</a> |
|
||||||
<a href="mailto:glenn@glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenn@glenneth.org</a> |
|
<a href="https://glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenneth.org</a>
|
||||||
<a href="https://glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenneth.org</a>
|
</p>
|
||||||
</p>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</footer>
|
||||||
</footer>
|
</body>
|
||||||
</body>
|
|
||||||
</html>
|
</html>
|
||||||
|
|
@ -1,188 +1,187 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en" class="bg-base-bg">
|
<html lang="en" class="bg-base-bg">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<meta name="description" content="">
|
<meta name="description" content="">
|
||||||
<meta property="og:title" content="A Journey into Scheme">
|
<meta property="og:title" content="Blog Post">
|
||||||
<meta property="og:description" content="">
|
<meta property="og:description" content="">
|
||||||
<meta property="og:url" content="https://glenneth.orgcontent/posts/2024-09-24-scheme-journey">
|
<meta property="og:url" content="https://glenneth.orgcontent/posts/2024-09-24-scheme-journey">
|
||||||
<title>A Journey into Scheme - Glenn Thompson</title>
|
<title>Blog Post - Glenn Thompson</title>
|
||||||
<link rel="alternate" type="application/rss+xml" title="Glenn Thompson's Blog" href="/feed.xml" />
|
<link rel="alternate" type="application/rss+xml" title="Glenn Thompson's Blog" href="/feed.xml" />
|
||||||
<link href="../../dist/styles.css" rel="stylesheet">
|
<link href="/dist/styles.css" rel="stylesheet">
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Merriweather:wght@400;700&family=JetBrains+Mono:wght@400;700&display=swap" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Merriweather:wght@400;700&family=JetBrains+Mono:wght@400;700&display=swap" rel="stylesheet">
|
||||||
<style>
|
<style>
|
||||||
.prose-palenight {
|
.prose-palenight {
|
||||||
--tw-prose-body: #bfc7d5;
|
--tw-prose-body: #bfc7d5;
|
||||||
--tw-prose-headings: #ffd580;
|
--tw-prose-headings: #ffd580;
|
||||||
--tw-prose-links: #82aaff;
|
--tw-prose-links: #82aaff;
|
||||||
--tw-prose-code: #c792ea;
|
--tw-prose-code: #c792ea;
|
||||||
--tw-prose-pre-bg: #1b1e2b;
|
--tw-prose-pre-bg: #1b1e2b;
|
||||||
}
|
}
|
||||||
.prose h2 {
|
.prose h2 {
|
||||||
color: var(--tw-prose-headings);
|
color: var(--tw-prose-headings);
|
||||||
font-family: Merriweather, serif;
|
font-family: Merriweather, serif;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
font-size: 1.5rem;
|
font-size: 1.5rem;
|
||||||
margin-top: 2rem;
|
margin-top: 2rem;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
}
|
}
|
||||||
.prose p {
|
.prose p {
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
line-height: 1.625;
|
line-height: 1.625;
|
||||||
}
|
}
|
||||||
.prose a {
|
.prose a {
|
||||||
color: var(--tw-prose-links);
|
color: var(--tw-prose-links);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
.prose a:hover {
|
.prose a:hover {
|
||||||
color: #89ddff;
|
color: #89ddff;
|
||||||
}
|
}
|
||||||
.prose code {
|
.prose code {
|
||||||
color: var(--tw-prose-code);
|
color: var(--tw-prose-code);
|
||||||
font-family: 'JetBrains Mono', monospace;
|
font-family: 'JetBrains Mono', monospace;
|
||||||
}
|
}
|
||||||
.prose pre {
|
.prose pre {
|
||||||
background-color: var(--tw-prose-pre-bg);
|
background-color: var(--tw-prose-pre-bg);
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
}
|
}
|
||||||
.prose ul, .prose ol {
|
.prose ul, .prose ol {
|
||||||
margin-top: 0.5rem;
|
margin-top: 0.5rem;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
padding-left: 1.5rem;
|
padding-left: 1.5rem;
|
||||||
}
|
}
|
||||||
.prose ul {
|
.prose ul {
|
||||||
list-style-type: disc;
|
list-style-type: disc;
|
||||||
}
|
}
|
||||||
.prose ol {
|
.prose ol {
|
||||||
list-style-type: decimal;
|
list-style-type: decimal;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body class="bg-base-bg text-palenight-50">
|
<body class="bg-base-bg text-palenight-50">
|
||||||
<nav class="bg-base-darker/80 backdrop-blur-sm shadow-sm border-b border-palenight-400/20 mb-8">
|
<nav class="bg-base-darker/80 backdrop-blur-sm shadow-sm border-b border-palenight-400/20 mb-8">
|
||||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<div class="flex items-center justify-between h-16">
|
<div class="flex items-center justify-between h-16">
|
||||||
<a href="/" class="text-accent-yellow font-serif text-xl font-bold">Glenn Thompson</a>
|
<a href="/" class="text-accent-yellow font-serif text-xl font-bold">Glenn Thompson</a>
|
||||||
<div class="flex items-center gap-2 text-accent-yellow text-sm font-bold">
|
<div class="flex items-center gap-2 text-accent-yellow text-sm font-bold">
|
||||||
<span>personal, tech, guile, scheme, gnu, development</span>
|
<span>Tech</span>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<time datetime="2024-09-24 09:30">September 24, 2024</time>
|
<time datetime="undefined">Invalid Date</time>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<span>5 min read</span>
|
<span>5 min read</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<main class="pt-24 pb-16 px-4">
|
<main class="pt-24 pb-16 px-4">
|
||||||
<div class="max-w-4xl mx-auto">
|
<div class="max-w-4xl mx-auto">
|
||||||
<div class="content text-palenight-100 space-y-6">
|
<div class="content text-palenight-100 space-y-6">
|
||||||
<header class="mb-8">
|
<header class="mb-8">
|
||||||
<h1 class="text-4xl font-serif font-bold text-accent-yellow">A Journey into Scheme</h1>
|
<h1 class="text-4xl font-serif font-bold text-accent-yellow">Blog Post</h1>
|
||||||
<div class="flex items-center gap-4 text-palenight-300 mt-4">
|
<div class="flex items-center gap-4 text-palenight-300 mt-4">
|
||||||
<time datetime="2024-09-24 09:30">2024-09-24 09:30</time>
|
<time datetime=""></time>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<span>5 min read</span>
|
<span>5 min read</span>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<span>By Glenn Thompson</span>
|
<span>By Glenn Thompson</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-wrap gap-2 mt-4">
|
</header>
|
||||||
<span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">personal</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">tech</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">guile</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">scheme</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">gnu</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">development</span>
|
|
||||||
</div>
|
<article class="prose prose-palenight max-w-none">
|
||||||
</header>
|
<hr>
|
||||||
|
<h2>title: A Journey into Scheme<br>author: Glenn Thompson<br>date: 2024-09-24 09:30<br>tags: personal, tech, guile, scheme, gnu, development</h2>
|
||||||
<article class="prose prose-palenight max-w-none">
|
<h1>My Journey into Scheme: Building a Simple Symlink Manager with Guile Scheme</h1>
|
||||||
<h1>My Journey into Scheme: Building a Simple Symlink Manager with Guile Scheme</h1>
|
<h2>Introduction</h2>
|
||||||
<h2>Introduction</h2>
|
<p>I've spent my career as an electrical engineer, not a software developer. However, my recent journey in to GNU/Liniux required a tool for managing symlinks, and that's how I began learning Scheme—specifically Guile Scheme. I'm writing this post to share how I built <code>stash</code>, a utility that mimics GNU Stow's functionality, and how my learning journey was shaped by David Wilson's "Hands-On Guile Scheme for Beginners" course from System Crafters, more about this below.</p>
|
||||||
<p>I've spent my career as an electrical engineer, not a software developer. However, my recent journey in to GNU/Liniux required a tool for managing symlinks, and that's how I began learning Scheme—specifically Guile Scheme. I'm writing this post to share how I built <code>stash</code>, a utility that mimics GNU Stow's functionality, and how my learning journey was shaped by David Wilson's "Hands-On Guile Scheme for Beginners" course from System Crafters, more about this below.</p>
|
<h2>How I Started with Scheme</h2>
|
||||||
<h2>How I Started with Scheme</h2>
|
<p>My programming background was <em>VERY</em> limited, I produce documents in (La)Tex but I decided to take the plunge into learning Scheme, thanks to a course led by David Wilson from System Crafters. The course, <a href="https://systemcrafters.net/courses/hands-on-guile-scheme-beginners/">"Hands-On Guile Scheme for Beginners"</a>, was incredibly helpful in making Scheme accessible even for someone like me, without a traditional programming background. I know (La)Tex isn't a programming language, it's typesetting. But how hard can it be? Right?</p>
|
||||||
<p>My programming background was <em>VERY</em> limited, I produce documents in (La)Tex but I decided to take the plunge into learning Scheme, thanks to a course led by David Wilson from System Crafters. The course, <a href="https://systemcrafters.net/courses/hands-on-guile-scheme-beginners/">"Hands-On Guile Scheme for Beginners"</a>, was incredibly helpful in making Scheme accessible even for someone like me, without a traditional programming background. I know (La)Tex isn't a programming language, it's typesetting. But how hard can it be? Right?</p>
|
<p>The course took me through the basics of Scheme, from simple expressions to more complex concepts like functions, recursion, and working with files. This structured learning environment gave me the confidence to start building <code>stash</code>.</p>
|
||||||
<p>The course took me through the basics of Scheme, from simple expressions to more complex concepts like functions, recursion, and working with files. This structured learning environment gave me the confidence to start building <code>stash</code>.</p>
|
<p>The course was "instructor-led" with live meet-up sessions weekly. David has since made this course on-demand, and will be, if not already, available at the above link. Highly recommended if you are interested in taking your first steps with scheme.</p>
|
||||||
<p>The course was "instructor-led" with live meet-up sessions weekly. David has since made this course on-demand, and will be, if not already, available at the above link. Highly recommended if you are interested in taking your first steps with scheme.</p>
|
<h2>Why Build Stash?</h2>
|
||||||
<h2>Why Build Stash?</h2>
|
<p>After completing David Wilson's course, I wanted to put my newly found Guile Scheme skills into practice with a real project. It wasn't enough just to understand the language conceptually—I needed to build something tangible that solved a problem I encountered regularly in my workflow. Writing <code>stash</code> gave me that opportunity. It allowed me to apply what I'd learned while also deepening my understanding of file manipulation, command-line tools, and conflict resolution—all within the Guile Scheme environment.</p>
|
||||||
<p>After completing David Wilson's course, I wanted to put my newly found Guile Scheme skills into practice with a real project. It wasn't enough just to understand the language conceptually—I needed to build something tangible that solved a problem I encountered regularly in my workflow. Writing <code>stash</code> gave me that opportunity. It allowed me to apply what I'd learned while also deepening my understanding of file manipulation, command-line tools, and conflict resolution—all within the Guile Scheme environment.</p>
|
<p>After migrating to GNU/Linux and speaking with other <a href="https://systemcrafters.net/community">System Crafters Community</a> members, I found I needed a way to manage symbolic links and organize directories. Existing tools like GNU Stow helped, but I wanted to learn how such tools are built. I decided to write my own version using Guile Scheme to enhance my understanding of the language and to have more control over the functionality.</p>
|
||||||
<p>After migrating to GNU/Linux and speaking with other <a href="https://systemcrafters.net/community">System Crafters Community</a> members, I found I needed a way to manage symbolic links and organize directories. Existing tools like GNU Stow helped, but I wanted to learn how such tools are built. I decided to write my own version using Guile Scheme to enhance my understanding of the language and to have more control over the functionality.</p>
|
<p>The goal of <code>stash</code> is simple: allow users to move directories and create symlinks with conflict resolution, offering options to overwrite, back up, skip, or cancel the operation.</p>
|
||||||
<p>The goal of <code>stash</code> is simple: allow users to move directories and create symlinks with conflict resolution, offering options to overwrite, back up, skip, or cancel the operation.</p>
|
<h2>Breaking Down Stash</h2>
|
||||||
<h2>Breaking Down Stash</h2>
|
<p>The core of <code>stash</code> revolves around:</p>
|
||||||
<p>The core of <code>stash</code> revolves around:</p>
|
<ol>
|
||||||
<ol>
|
<li><strong>Moving Directories</strong>: Using Scheme's file manipulation functions, I learned how to move directories and files around. </li>
|
||||||
<li><strong>Moving Directories</strong>: Using Scheme's file manipulation functions, I learned how to move directories and files around. </li>
|
<li><strong>Creating Symlinks</strong>: I implemented functions to create symlinks to the moved directories, ensuring that the original structure remains accessible.</li>
|
||||||
<li><strong>Creating Symlinks</strong>: I implemented functions to create symlinks to the moved directories, ensuring that the original structure remains accessible.</li>
|
<li><strong>Conflict Resolution</strong>: One of the key features I wanted was handling conflicts when a file or symlink already exists at the target location. This required prompting the user for input and responding accordingly (backup, overwrite, skip, or cancel).</li>
|
||||||
<li><strong>Conflict Resolution</strong>: One of the key features I wanted was handling conflicts when a file or symlink already exists at the target location. This required prompting the user for input and responding accordingly (backup, overwrite, skip, or cancel).</li>
|
</ol>
|
||||||
</ol>
|
<p>Here's an excerpt of the core functionality that handles moving a source directory and creating a symlink:</p>
|
||||||
<p>Here's an excerpt of the core functionality that handles moving a source directory and creating a symlink:</p>
|
<pre><code class="language-scheme">;;; Helper function to move source to target
|
||||||
<pre><code class="language-scheme">;;; Helper function to move source to target
|
(define (move-source-to-target source-dir target-dir)
|
||||||
(define (move-source-to-target source-dir target-dir)
|
"Move the entire source directory to the target directory."
|
||||||
"Move the entire source directory to the target directory."
|
(let* ((source-dir (expand-home source-dir))
|
||||||
(let* ((source-dir (expand-home source-dir))
|
(target-dir (expand-home target-dir))
|
||||||
(target-dir (expand-home target-dir))
|
(source-name (basename source-dir))
|
||||||
(source-name (basename source-dir))
|
(target-source-dir (string-append target-dir "/" source-name)))
|
||||||
(target-source-dir (string-append target-dir "/" source-name)))
|
(if (file-exists? target-source-dir)
|
||||||
(if (file-exists? target-source-dir)
|
;; Conflict handling here...
|
||||||
;; Conflict handling here...
|
...)
|
||||||
...)
|
(rename-file source-dir target-source-dir)
|
||||||
(rename-file source-dir target-source-dir)
|
(display (format #f "Moved ~a to ~a\n" source-dir target-source-dir))))
|
||||||
(display (format #f "Moved ~a to ~a\n" source-dir target-source-dir))))
|
</code></pre>
|
||||||
</code></pre>
|
<h2>What I Learned</h2>
|
||||||
<h2>What I Learned</h2>
|
<p>This project taught me a lot about not just Scheme, but programming in general:</p>
|
||||||
<p>This project taught me a lot about not just Scheme, but programming in general:</p>
|
<ul>
|
||||||
<ul>
|
<li><strong>File and Directory Manipulation</strong>: Scheme's file handling functions were different from what I had experienced before, but they allowed for powerful manipulation of file systems.</li>
|
||||||
<li><strong>File and Directory Manipulation</strong>: Scheme's file handling functions were different from what I had experienced before, but they allowed for powerful manipulation of file systems.</li>
|
<li><strong>Command-Line Utilities</strong>: Scheme isn't just a language for academic exercises; you can write real, useful command-line tools with it.</li>
|
||||||
<li><strong>Command-Line Utilities</strong>: Scheme isn't just a language for academic exercises; you can write real, useful command-line tools with it.</li>
|
<li><strong>Problem Solving</strong>: From parsing command-line arguments to resolving conflicts with existing files, every part of the program required careful thought and consideration of edge cases.</li>
|
||||||
<li><strong>Problem Solving</strong>: From parsing command-line arguments to resolving conflicts with existing files, every part of the program required careful thought and consideration of edge cases.</li>
|
</ul>
|
||||||
</ul>
|
<h2>Guile Scheme Support Resources</h2>
|
||||||
<h2>Guile Scheme Support Resources</h2>
|
<ol>
|
||||||
<ol>
|
<li><p><strong><a href="https://www.gnu.org/software/guile/docs/">Guile Scheme Documentation</a></strong><br>The official documentation for Guile Scheme, which includes tutorials, references, and the Guile Manual.</p>
|
||||||
<li><p><strong><a href="https://www.gnu.org/software/guile/docs/">Guile Scheme Documentation</a></strong><br>The official documentation for Guile Scheme, which includes tutorials, references, and the Guile Manual.</p>
|
</li>
|
||||||
</li>
|
<li><p><strong><a href="https://www.gnu.org/software/guile/manual/html_node/">Guile Reference Manual</a></strong><br>A comprehensive manual covering core language concepts, libraries, and functions available in Guile Scheme.</p>
|
||||||
<li><p><strong><a href="https://www.gnu.org/software/guile/manual/html_node/">Guile Reference Manual</a></strong><br>A comprehensive manual covering core language concepts, libraries, and functions available in Guile Scheme.</p>
|
</li>
|
||||||
</li>
|
<li><p><strong><a href="http://community.schemewiki.org/">Scheme Wiki</a></strong><br>A community-maintained wiki that covers various Scheme dialects, including Guile Scheme, with tutorials, guides, and general information on Scheme programming.</p>
|
||||||
<li><p><strong><a href="http://community.schemewiki.org/">Scheme Wiki</a></strong><br>A community-maintained wiki that covers various Scheme dialects, including Guile Scheme, with tutorials, guides, and general information on Scheme programming.</p>
|
</li>
|
||||||
</li>
|
<li><p><strong><a href="http://schemers.org/">Guile at Schemers.org</a></strong><br>A site dedicated to Scheme with resources, libraries, tools, and documentation for Scheme and its implementations, including Guile.</p>
|
||||||
<li><p><strong><a href="http://schemers.org/">Guile at Schemers.org</a></strong><br>A site dedicated to Scheme with resources, libraries, tools, and documentation for Scheme and its implementations, including Guile.</p>
|
</li>
|
||||||
</li>
|
<li><p><strong><a href="https://systemcrafters.net/">System Crafters</a></strong><br>Led by David Wilson, System Crafters provides tutorials and blog posts on Guile Scheme and other GNU tools.</p>
|
||||||
<li><p><strong><a href="https://systemcrafters.net/">System Crafters</a></strong><br>Led by David Wilson, System Crafters provides tutorials and blog posts on Guile Scheme and other GNU tools.</p>
|
</li>
|
||||||
</li>
|
<li><p><strong><a href="https://lists.gnu.org/mailman/listinfo/guile-user">Guile Users Mailing List</a></strong><br>Join the Guile mailing list to ask questions and engage with the Guile Scheme community.</p>
|
||||||
<li><p><strong><a href="https://lists.gnu.org/mailman/listinfo/guile-user">Guile Users Mailing List</a></strong><br>Join the Guile mailing list to ask questions and engage with the Guile Scheme community.</p>
|
</li>
|
||||||
</li>
|
<li><p><strong><a href="https://github.com/artyom-poptsov/guile-cookbook">Guile Cookbook</a></strong><br>An unofficial GitHub repository with practical code snippets and tips for Guile Scheme, covering various common use cases and tasks.</p>
|
||||||
<li><p><strong><a href="https://github.com/artyom-poptsov/guile-cookbook">Guile Cookbook</a></strong><br>An unofficial GitHub repository with practical code snippets and tips for Guile Scheme, covering various common use cases and tasks.</p>
|
</li>
|
||||||
</li>
|
<li><p><strong><a href="https://libera.chat/">#guile and #scheme on Libera Chat IRC</a></strong><br>A helpful IRC channel where you can connect with other Guile users for real-time support and advice.</p>
|
||||||
<li><p><strong><a href="https://libera.chat/">#guile and #scheme on Libera Chat IRC</a></strong><br>A helpful IRC channel where you can connect with other Guile users for real-time support and advice.</p>
|
</li>
|
||||||
</li>
|
<li><p><strong><a href="https://Libera.chat/">#systemcrafters on Libera Chat IRC</a></strong><br>A <em>SUPER</em> helpful IRC channel not only for guile and scheme, there are a huge variety of different people here. Tell them glenneth sent you.</p>
|
||||||
<li><p><strong><a href="https://Libera.chat/">#systemcrafters on Libera Chat IRC</a></strong><br>A <em>SUPER</em> helpful IRC channel not only for guile and scheme, there are a huge variety of different people here. Tell them glenneth sent you.</p>
|
</li>
|
||||||
</li>
|
</ol>
|
||||||
</ol>
|
<h2>Next Steps</h2>
|
||||||
<h2>Next Steps</h2>
|
<p>I am still refining <code>stash</code>, especially around its conflict resolution system and the way it handles symbolic links. But it's in a usable state, and I'm excited to continue iterating on it. You can check out the code <a href="https://codeberg.org/glenneth/stash">on Codeberg</a>.</p>
|
||||||
<p>I am still refining <code>stash</code>, especially around its conflict resolution system and the way it handles symbolic links. But it's in a usable state, and I'm excited to continue iterating on it. You can check out the code <a href="https://codeberg.org/glenneth/stash">on Codeberg</a>.</p>
|
<p>If you're curious about Scheme and how it can be used practically, I highly recommend checking out David Wilson's course. It's been instrumental in helping me grasp the concepts I needed to build this tool. Here's the link, again :) <a href="https://systemcrafters.net/courses/hands-on-guile-scheme-beginners/">"Hands-On Guile Scheme for Beginners"</a></p>
|
||||||
<p>If you're curious about Scheme and how it can be used practically, I highly recommend checking out David Wilson's course. It's been instrumental in helping me grasp the concepts I needed to build this tool. Here's the link, again :) <a href="https://systemcrafters.net/courses/hands-on-guile-scheme-beginners/">"Hands-On Guile Scheme for Beginners"</a></p>
|
|
||||||
|
</article>
|
||||||
</article>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</main>
|
||||||
</main>
|
<footer class="bg-base-darker text-palenight-200 py-12 border-t border-palenight-400/20">
|
||||||
<footer class="bg-base-darker text-palenight-200 py-12 border-t border-palenight-400/20">
|
<div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
<div class="text-center">
|
||||||
<div class="text-center">
|
<p class="text-palenight-300">© 2026 Glenn Thompson. All rights reserved.</p>
|
||||||
<p class="text-palenight-300">© 2024 Glenn Thompson. All rights reserved.</p>
|
<div class="webring-text mt-6">
|
||||||
<div class="webring-text mt-6">
|
<p class="text-palenight-300">I am part of the <a href="https://systemcrafters.net" target="_blank" class="text-accent-blue hover:text-accent-cyan">System Crafters</a> webring:</p>
|
||||||
<p class="text-palenight-300">I am part of the <a href="https://systemcrafters.net" target="_blank" class="text-accent-blue hover:text-accent-cyan">System Crafters</a> webring:</p>
|
</div>
|
||||||
</div>
|
<div class="craftering mt-2 flex items-center justify-center gap-4 text-accent-blue">
|
||||||
<div class="craftering mt-2 flex items-center justify-center gap-4 text-accent-blue">
|
<a href="https://craftering.systemcrafters.net/@glenneth/previous" class="hover:text-accent-cyan">Previous</a>
|
||||||
<a href="https://craftering.systemcrafters.net/@glenneth/previous" class="hover:text-accent-cyan">Previous</a>
|
<a href="https://craftering.systemcrafters.net/@glenneth" class="hover:text-accent-cyan">Random</a>
|
||||||
<a href="https://craftering.systemcrafters.net/@glenneth" class="hover:text-accent-cyan">Random</a>
|
<a href="https://craftering.systemcrafters.net/@glenneth/next" class="hover:text-accent-cyan">Next</a>
|
||||||
<a href="https://craftering.systemcrafters.net/@glenneth/next" class="hover:text-accent-cyan">Next</a>
|
</div>
|
||||||
</div>
|
<p class="text-palenight-300 mt-2">
|
||||||
<p class="text-palenight-300 mt-2">
|
<a href="mailto:glenn@glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenn@glenneth.org</a> |
|
||||||
<a href="mailto:glenn@glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenn@glenneth.org</a> |
|
<a href="https://glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenneth.org</a>
|
||||||
<a href="https://glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenneth.org</a>
|
</p>
|
||||||
</p>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</footer>
|
||||||
</footer>
|
</body>
|
||||||
</body>
|
|
||||||
</html>
|
</html>
|
||||||
|
|
@ -1,268 +1,267 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en" class="bg-base-bg">
|
<html lang="en" class="bg-base-bg">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<meta name="description" content="">
|
<meta name="description" content="">
|
||||||
<meta property="og:title" content="Beyond Theory: Building Practical Tools with Guile Scheme">
|
<meta property="og:title" content="Blog Post">
|
||||||
<meta property="og:description" content="">
|
<meta property="og:description" content="">
|
||||||
<meta property="og:url" content="https://glenneth.orgcontent/posts/2024-12-03-practical-scheme">
|
<meta property="og:url" content="https://glenneth.orgcontent/posts/2024-12-03-practical-scheme">
|
||||||
<title>Beyond Theory: Building Practical Tools with Guile Scheme - Glenn Thompson</title>
|
<title>Blog Post - Glenn Thompson</title>
|
||||||
<link rel="alternate" type="application/rss+xml" title="Glenn Thompson's Blog" href="/feed.xml" />
|
<link rel="alternate" type="application/rss+xml" title="Glenn Thompson's Blog" href="/feed.xml" />
|
||||||
<link href="../../dist/styles.css" rel="stylesheet">
|
<link href="/dist/styles.css" rel="stylesheet">
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Merriweather:wght@400;700&family=JetBrains+Mono:wght@400;700&display=swap" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Merriweather:wght@400;700&family=JetBrains+Mono:wght@400;700&display=swap" rel="stylesheet">
|
||||||
<style>
|
<style>
|
||||||
.prose-palenight {
|
.prose-palenight {
|
||||||
--tw-prose-body: #bfc7d5;
|
--tw-prose-body: #bfc7d5;
|
||||||
--tw-prose-headings: #ffd580;
|
--tw-prose-headings: #ffd580;
|
||||||
--tw-prose-links: #82aaff;
|
--tw-prose-links: #82aaff;
|
||||||
--tw-prose-code: #c792ea;
|
--tw-prose-code: #c792ea;
|
||||||
--tw-prose-pre-bg: #1b1e2b;
|
--tw-prose-pre-bg: #1b1e2b;
|
||||||
}
|
}
|
||||||
.prose h2 {
|
.prose h2 {
|
||||||
color: var(--tw-prose-headings);
|
color: var(--tw-prose-headings);
|
||||||
font-family: Merriweather, serif;
|
font-family: Merriweather, serif;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
font-size: 1.5rem;
|
font-size: 1.5rem;
|
||||||
margin-top: 2rem;
|
margin-top: 2rem;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
}
|
}
|
||||||
.prose p {
|
.prose p {
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
line-height: 1.625;
|
line-height: 1.625;
|
||||||
}
|
}
|
||||||
.prose a {
|
.prose a {
|
||||||
color: var(--tw-prose-links);
|
color: var(--tw-prose-links);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
.prose a:hover {
|
.prose a:hover {
|
||||||
color: #89ddff;
|
color: #89ddff;
|
||||||
}
|
}
|
||||||
.prose code {
|
.prose code {
|
||||||
color: var(--tw-prose-code);
|
color: var(--tw-prose-code);
|
||||||
font-family: 'JetBrains Mono', monospace;
|
font-family: 'JetBrains Mono', monospace;
|
||||||
}
|
}
|
||||||
.prose pre {
|
.prose pre {
|
||||||
background-color: var(--tw-prose-pre-bg);
|
background-color: var(--tw-prose-pre-bg);
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
}
|
}
|
||||||
.prose ul, .prose ol {
|
.prose ul, .prose ol {
|
||||||
margin-top: 0.5rem;
|
margin-top: 0.5rem;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
padding-left: 1.5rem;
|
padding-left: 1.5rem;
|
||||||
}
|
}
|
||||||
.prose ul {
|
.prose ul {
|
||||||
list-style-type: disc;
|
list-style-type: disc;
|
||||||
}
|
}
|
||||||
.prose ol {
|
.prose ol {
|
||||||
list-style-type: decimal;
|
list-style-type: decimal;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body class="bg-base-bg text-palenight-50">
|
<body class="bg-base-bg text-palenight-50">
|
||||||
<nav class="bg-base-darker/80 backdrop-blur-sm shadow-sm border-b border-palenight-400/20 mb-8">
|
<nav class="bg-base-darker/80 backdrop-blur-sm shadow-sm border-b border-palenight-400/20 mb-8">
|
||||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<div class="flex items-center justify-between h-16">
|
<div class="flex items-center justify-between h-16">
|
||||||
<a href="/" class="text-accent-yellow font-serif text-xl font-bold">Glenn Thompson</a>
|
<a href="/" class="text-accent-yellow font-serif text-xl font-bold">Glenn Thompson</a>
|
||||||
<div class="flex items-center gap-2 text-accent-yellow text-sm font-bold">
|
<div class="flex items-center gap-2 text-accent-yellow text-sm font-bold">
|
||||||
<span>tech, guile, scheme, development, functional-programming</span>
|
<span>Tech</span>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<time datetime="2024-12-03 10:00">December 3, 2024</time>
|
<time datetime="undefined">Invalid Date</time>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<span>5 min read</span>
|
<span>5 min read</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<main class="pt-24 pb-16 px-4">
|
<main class="pt-24 pb-16 px-4">
|
||||||
<div class="max-w-4xl mx-auto">
|
<div class="max-w-4xl mx-auto">
|
||||||
<div class="content text-palenight-100 space-y-6">
|
<div class="content text-palenight-100 space-y-6">
|
||||||
<header class="mb-8">
|
<header class="mb-8">
|
||||||
<h1 class="text-4xl font-serif font-bold text-accent-yellow">Beyond Theory: Building Practical Tools with Guile Scheme</h1>
|
<h1 class="text-4xl font-serif font-bold text-accent-yellow">Blog Post</h1>
|
||||||
<div class="flex items-center gap-4 text-palenight-300 mt-4">
|
<div class="flex items-center gap-4 text-palenight-300 mt-4">
|
||||||
<time datetime="2024-12-03 10:00">2024-12-03 10:00</time>
|
<time datetime=""></time>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<span>5 min read</span>
|
<span>5 min read</span>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<span>By Glenn Thompson</span>
|
<span>By Glenn Thompson</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-wrap gap-2 mt-4">
|
</header>
|
||||||
<span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">tech</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">guile</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">scheme</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">development</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">functional-programming</span>
|
|
||||||
</div>
|
<article class="prose prose-palenight max-w-none">
|
||||||
</header>
|
<hr>
|
||||||
|
<h2>title: Beyond Theory: Building Practical Tools with Guile Scheme<br>author: Glenn Thompson<br>date: 2024-12-03 10:00<br>tags: tech, guile, scheme, development, functional-programming</h2>
|
||||||
<article class="prose prose-palenight max-w-none">
|
<h1>Beyond Theory: Building Practical Tools with Guile Scheme</h1>
|
||||||
<h1>Beyond Theory: Building Practical Tools with Guile Scheme</h1>
|
<h2>Introduction</h2>
|
||||||
<h2>Introduction</h2>
|
<p>A few months ago, I shared my journey into learning Scheme through building <code>stash</code>, a symlink manager. Since then, I've discovered that the gap between learning Scheme and applying it to real-world problems is where the most valuable lessons emerge. This post explores what I've learned about building practical tools with Guile Scheme, sharing both successes and challenges along the way.</p>
|
||||||
<p>A few months ago, I shared my journey into learning Scheme through building <code>stash</code>, a symlink manager. Since then, I've discovered that the gap between learning Scheme and applying it to real-world problems is where the most valuable lessons emerge. This post explores what I've learned about building practical tools with Guile Scheme, sharing both successes and challenges along the way.</p>
|
<h2>The Power of Modular Design</h2>
|
||||||
<h2>The Power of Modular Design</h2>
|
<p>One of the most important lessons I learned was the value of modular design. Breaking down a program into focused, single-responsibility modules not only makes the code more maintainable but also helps in reasoning about the program's behavior. Here's how I structured <code>stash</code>:</p>
|
||||||
<p>One of the most important lessons I learned was the value of modular design. Breaking down a program into focused, single-responsibility modules not only makes the code more maintainable but also helps in reasoning about the program's behavior. Here's how I structured <code>stash</code>:</p>
|
<pre><code class="language-scheme">(use-modules (ice-9 getopt-long)
|
||||||
<pre><code class="language-scheme">(use-modules (ice-9 getopt-long)
|
(stash help) ;; Help module
|
||||||
(stash help) ;; Help module
|
(stash colors) ;; ANSI colors
|
||||||
(stash colors) ;; ANSI colors
|
(stash log) ;; Logging module
|
||||||
(stash log) ;; Logging module
|
(stash paths) ;; Path handling module
|
||||||
(stash paths) ;; Path handling module
|
(stash conflict) ;; Conflict resolution module
|
||||||
(stash conflict) ;; Conflict resolution module
|
(stash file-ops)) ;; File and symlink operations module
|
||||||
(stash file-ops)) ;; File and symlink operations module
|
</code></pre>
|
||||||
</code></pre>
|
<p>Each module has a specific responsibility:</p>
|
||||||
<p>Each module has a specific responsibility:</p>
|
<ul>
|
||||||
<ul>
|
<li><code>colors.scm</code>: Handles ANSI color formatting for terminal output</li>
|
||||||
<li><code>colors.scm</code>: Handles ANSI color formatting for terminal output</li>
|
<li><code>conflict.scm</code>: Manages conflict resolution when files already exist</li>
|
||||||
<li><code>conflict.scm</code>: Manages conflict resolution when files already exist</li>
|
<li><code>file-ops.scm</code>: Handles file system operations</li>
|
||||||
<li><code>file-ops.scm</code>: Handles file system operations</li>
|
<li><code>help.scm</code>: Provides usage information</li>
|
||||||
<li><code>help.scm</code>: Provides usage information</li>
|
<li><code>log.scm</code>: Manages logging operations</li>
|
||||||
<li><code>log.scm</code>: Manages logging operations</li>
|
<li><code>paths.scm</code>: Handles path manipulation and normalization</li>
|
||||||
<li><code>paths.scm</code>: Handles path manipulation and normalization</li>
|
</ul>
|
||||||
</ul>
|
<h2>Robust Path Handling</h2>
|
||||||
<h2>Robust Path Handling</h2>
|
<p>One of the first challenges in building a file management tool is handling paths correctly. Here's how I approached it:</p>
|
||||||
<p>One of the first challenges in building a file management tool is handling paths correctly. Here's how I approached it:</p>
|
<pre><code class="language-scheme">(define (expand-home path)
|
||||||
<pre><code class="language-scheme">(define (expand-home path)
|
"Expand ~ to the user's home directory."
|
||||||
"Expand ~ to the user's home directory."
|
(if (string-prefix? "~" path)
|
||||||
(if (string-prefix? "~" path)
|
(string-append (getenv "HOME") (substring path 1))
|
||||||
(string-append (getenv "HOME") (substring path 1))
|
path))
|
||||||
path))
|
|
||||||
|
(define (concat-path base path)
|
||||||
(define (concat-path base path)
|
"Concatenate two paths, ensuring there are no double slashes."
|
||||||
"Concatenate two paths, ensuring there are no double slashes."
|
(if (string-suffix? "/" base)
|
||||||
(if (string-suffix? "/" base)
|
(string-append (string-drop-right base 1) "/" path)
|
||||||
(string-append (string-drop-right base 1) "/" path)
|
(string-append base "/" path)))
|
||||||
(string-append base "/" path)))
|
|
||||||
|
(define (ensure-config-path target-dir)
|
||||||
(define (ensure-config-path target-dir)
|
"Ensure that the target directory has .config appended, avoiding double slashes."
|
||||||
"Ensure that the target directory has .config appended, avoiding double slashes."
|
(let ((target-dir (expand-home target-dir)))
|
||||||
(let ((target-dir (expand-home target-dir)))
|
(if (string-suffix? "/" target-dir)
|
||||||
(if (string-suffix? "/" target-dir)
|
(set! target-dir (string-drop-right target-dir 1)))
|
||||||
(set! target-dir (string-drop-right target-dir 1)))
|
(if (not (string-suffix? "/.config" target-dir))
|
||||||
(if (not (string-suffix? "/.config" target-dir))
|
(string-append target-dir "/.config")
|
||||||
(string-append target-dir "/.config")
|
target-dir)))
|
||||||
target-dir)))
|
</code></pre>
|
||||||
</code></pre>
|
<p>This approach ensures that:</p>
|
||||||
<p>This approach ensures that:</p>
|
<ul>
|
||||||
<ul>
|
<li>Home directory references (<code>~</code>) are properly expanded</li>
|
||||||
<li>Home directory references (<code>~</code>) are properly expanded</li>
|
<li>Path concatenation doesn't create double slashes</li>
|
||||||
<li>Path concatenation doesn't create double slashes</li>
|
<li>Configuration paths are consistently structured</li>
|
||||||
<li>Configuration paths are consistently structured</li>
|
</ul>
|
||||||
</ul>
|
<h2>Interactive Conflict Resolution</h2>
|
||||||
<h2>Interactive Conflict Resolution</h2>
|
<p>Real-world tools often need to handle conflicts. I implemented an interactive conflict resolution system:</p>
|
||||||
<p>Real-world tools often need to handle conflicts. I implemented an interactive conflict resolution system:</p>
|
<pre><code class="language-scheme">(define (prompt-user-for-action)
|
||||||
<pre><code class="language-scheme">(define (prompt-user-for-action)
|
"Prompt the user to decide how to handle a conflict: overwrite (o), skip (s), or cancel (c)."
|
||||||
"Prompt the user to decide how to handle a conflict: overwrite (o), skip (s), or cancel (c)."
|
(display (color-message
|
||||||
(display (color-message
|
"A conflict was detected. Choose action - Overwrite (o), Skip (s), or Cancel (c): "
|
||||||
"A conflict was detected. Choose action - Overwrite (o), Skip (s), or Cancel (c): "
|
yellow-text))
|
||||||
yellow-text))
|
(let ((response (read-line)))
|
||||||
(let ((response (read-line)))
|
(cond
|
||||||
(cond
|
((string-ci=? response "o") 'overwrite)
|
||||||
((string-ci=? response "o") 'overwrite)
|
((string-ci=? response "s") 'skip)
|
||||||
((string-ci=? response "s") 'skip)
|
((string-ci=? response "c") 'cancel)
|
||||||
((string-ci=? response "c") 'cancel)
|
(else
|
||||||
(else
|
(display "Invalid input. Please try again.\n")
|
||||||
(display "Invalid input. Please try again.\n")
|
(prompt-user-for-action)))))
|
||||||
(prompt-user-for-action)))))
|
</code></pre>
|
||||||
</code></pre>
|
<p>This provides a user-friendly interface for resolving conflicts while maintaining data safety.</p>
|
||||||
<p>This provides a user-friendly interface for resolving conflicts while maintaining data safety.</p>
|
<h2>Logging for Debugging and Auditing</h2>
|
||||||
<h2>Logging for Debugging and Auditing</h2>
|
<p>Proper logging is crucial for debugging and auditing. I implemented a simple but effective logging system:</p>
|
||||||
<p>Proper logging is crucial for debugging and auditing. I implemented a simple but effective logging system:</p>
|
<pre><code class="language-scheme">(define (current-timestamp)
|
||||||
<pre><code class="language-scheme">(define (current-timestamp)
|
"Return the current date and time as a formatted string."
|
||||||
"Return the current date and time as a formatted string."
|
(let* ((time (current-time))
|
||||||
(let* ((time (current-time))
|
(seconds (time-second time)))
|
||||||
(seconds (time-second time)))
|
(strftime "%Y-%m-%d-%H-%M-%S" (localtime seconds))))
|
||||||
(strftime "%Y-%m-%d-%H-%M-%S" (localtime seconds))))
|
|
||||||
|
(define (log-action message)
|
||||||
(define (log-action message)
|
"Log an action with a timestamp to the stash.log file."
|
||||||
"Log an action with a timestamp to the stash.log file."
|
(let ((log-port (open-file "stash.log" "a")))
|
||||||
(let ((log-port (open-file "stash.log" "a")))
|
(display (color-message
|
||||||
(display (color-message
|
(string-append "[" (current-timestamp) "] " message)
|
||||||
(string-append "[" (current-timestamp) "] " message)
|
green-text) log-port)
|
||||||
green-text) log-port)
|
(newline log-port)
|
||||||
(newline log-port)
|
(close-port log-port)))
|
||||||
(close-port log-port)))
|
</code></pre>
|
||||||
</code></pre>
|
<p>This logging system:</p>
|
||||||
<p>This logging system:</p>
|
<ul>
|
||||||
<ul>
|
<li>Timestamps each action</li>
|
||||||
<li>Timestamps each action</li>
|
<li>Uses color coding for better readability</li>
|
||||||
<li>Uses color coding for better readability</li>
|
<li>Maintains a persistent log file</li>
|
||||||
<li>Maintains a persistent log file</li>
|
<li>Properly handles file operations</li>
|
||||||
<li>Properly handles file operations</li>
|
</ul>
|
||||||
</ul>
|
<h2>File Operations with Safety</h2>
|
||||||
<h2>File Operations with Safety</h2>
|
<p>When dealing with file system operations, safety is paramount. Here's how I handle moving directories:</p>
|
||||||
<p>When dealing with file system operations, safety is paramount. Here's how I handle moving directories:</p>
|
<pre><code class="language-scheme">(define (move-source-to-target source-dir target-dir)
|
||||||
<pre><code class="language-scheme">(define (move-source-to-target source-dir target-dir)
|
"Move the entire source directory to the target directory, ensuring .config in the target path."
|
||||||
"Move the entire source directory to the target directory, ensuring .config in the target path."
|
(let* ((target-dir (ensure-config-path target-dir))
|
||||||
(let* ((target-dir (ensure-config-path target-dir))
|
(source-dir (expand-home source-dir))
|
||||||
(source-dir (expand-home source-dir))
|
(source-name (basename source-dir))
|
||||||
(source-name (basename source-dir))
|
(target-source-dir (concat-path target-dir source-name)))
|
||||||
(target-source-dir (concat-path target-dir source-name)))
|
(if (not (file-exists? target-dir))
|
||||||
(if (not (file-exists? target-dir))
|
(mkdir target-dir #o755))
|
||||||
(mkdir target-dir #o755))
|
(if (file-exists? target-source-dir)
|
||||||
(if (file-exists? target-source-dir)
|
(handle-conflict target-source-dir source-dir delete-directory log-action)
|
||||||
(handle-conflict target-source-dir source-dir delete-directory log-action)
|
(begin
|
||||||
(begin
|
(rename-file source-dir target-source-dir)
|
||||||
(rename-file source-dir target-source-dir)
|
(display (format #f "Moved ~a to ~a\n" source-dir target-source-dir))
|
||||||
(display (format #f "Moved ~a to ~a\n" source-dir target-source-dir))
|
(log-action (format #f "Moved ~a to ~a" source-dir target-source-dir))))
|
||||||
(log-action (format #f "Moved ~a to ~a" source-dir target-source-dir))))
|
target-source-dir))
|
||||||
target-source-dir))
|
</code></pre>
|
||||||
</code></pre>
|
<p>This implementation:</p>
|
||||||
<p>This implementation:</p>
|
<ul>
|
||||||
<ul>
|
<li>Ensures paths are properly formatted</li>
|
||||||
<li>Ensures paths are properly formatted</li>
|
<li>Creates necessary directories</li>
|
||||||
<li>Creates necessary directories</li>
|
<li>Handles conflicts gracefully</li>
|
||||||
<li>Handles conflicts gracefully</li>
|
<li>Logs all operations</li>
|
||||||
<li>Logs all operations</li>
|
<li>Returns the new path for further operations</li>
|
||||||
<li>Returns the new path for further operations</li>
|
</ul>
|
||||||
</ul>
|
<h2>Lessons Learned</h2>
|
||||||
<h2>Lessons Learned</h2>
|
<h3>What Worked Well</h3>
|
||||||
<h3>What Worked Well</h3>
|
<ol>
|
||||||
<ol>
|
<li><strong>Modular Design</strong>: Breaking the code into focused modules made it easier to maintain and test</li>
|
||||||
<li><strong>Modular Design</strong>: Breaking the code into focused modules made it easier to maintain and test</li>
|
<li><strong>Functional Approach</strong>: Using pure functions where possible made the code more predictable</li>
|
||||||
<li><strong>Functional Approach</strong>: Using pure functions where possible made the code more predictable</li>
|
<li><strong>Interactive Interface</strong>: Providing clear user prompts and colored output improved usability</li>
|
||||||
<li><strong>Interactive Interface</strong>: Providing clear user prompts and colored output improved usability</li>
|
<li><strong>Robust Logging</strong>: Detailed logging helped with debugging and understanding program flow</li>
|
||||||
<li><strong>Robust Logging</strong>: Detailed logging helped with debugging and understanding program flow</li>
|
</ol>
|
||||||
</ol>
|
<h3>Challenges Faced</h3>
|
||||||
<h3>Challenges Faced</h3>
|
<ol>
|
||||||
<ol>
|
<li><strong>Path Handling</strong>: Dealing with different path formats and edge cases required careful attention</li>
|
||||||
<li><strong>Path Handling</strong>: Dealing with different path formats and edge cases required careful attention</li>
|
<li><strong>Error States</strong>: Managing various error conditions while keeping the code clean</li>
|
||||||
<li><strong>Error States</strong>: Managing various error conditions while keeping the code clean</li>
|
<li><strong>User Interface</strong>: Balancing between automation and user control</li>
|
||||||
<li><strong>User Interface</strong>: Balancing between automation and user control</li>
|
<li><strong>Documentation</strong>: Writing clear documentation that helps users understand the tool</li>
|
||||||
<li><strong>Documentation</strong>: Writing clear documentation that helps users understand the tool</li>
|
</ol>
|
||||||
</ol>
|
<h2>Moving Forward</h2>
|
||||||
<h2>Moving Forward</h2>
|
<p>Building <code>stash</code> has taught me that while functional programming principles are valuable, pragmatism is equally important. The key is finding the right balance between elegant functional code and practical solutions.</p>
|
||||||
<p>Building <code>stash</code> has taught me that while functional programming principles are valuable, pragmatism is equally important. The key is finding the right balance between elegant functional code and practical solutions.</p>
|
<h2>Resources</h2>
|
||||||
<h2>Resources</h2>
|
<ol>
|
||||||
<ol>
|
<li><a href="https://www.gnu.org/software/guile/manual/">Guile Manual</a></li>
|
||||||
<li><a href="https://www.gnu.org/software/guile/manual/">Guile Manual</a></li>
|
<li><a href="/content/posts/scheme-journey.html">My Previous Scheme Journey Post</a></li>
|
||||||
<li><a href="/content/posts/scheme-journey.html">My Previous Scheme Journey Post</a></li>
|
<li><a href="https://systemcrafters.net/community">System Crafters Community</a></li>
|
||||||
<li><a href="https://systemcrafters.net/community">System Crafters Community</a></li>
|
<li><a href="https://codeberg.org/glenneth/stash">Stash on Codeberg</a></li>
|
||||||
<li><a href="https://codeberg.org/glenneth/stash">Stash on Codeberg</a></li>
|
</ol>
|
||||||
</ol>
|
<p>The code examples in this post are from my actual implementation of <code>stash</code>. Feel free to explore, use, and improve upon them!</p>
|
||||||
<p>The code examples in this post are from my actual implementation of <code>stash</code>. Feel free to explore, use, and improve upon them!</p>
|
|
||||||
|
</article>
|
||||||
</article>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</main>
|
||||||
</main>
|
<footer class="bg-base-darker text-palenight-200 py-12 border-t border-palenight-400/20">
|
||||||
<footer class="bg-base-darker text-palenight-200 py-12 border-t border-palenight-400/20">
|
<div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
<div class="text-center">
|
||||||
<div class="text-center">
|
<p class="text-palenight-300">© 2026 Glenn Thompson. All rights reserved.</p>
|
||||||
<p class="text-palenight-300">© 2024 Glenn Thompson. All rights reserved.</p>
|
<div class="webring-text mt-6">
|
||||||
<div class="webring-text mt-6">
|
<p class="text-palenight-300">I am part of the <a href="https://systemcrafters.net" target="_blank" class="text-accent-blue hover:text-accent-cyan">System Crafters</a> webring:</p>
|
||||||
<p class="text-palenight-300">I am part of the <a href="https://systemcrafters.net" target="_blank" class="text-accent-blue hover:text-accent-cyan">System Crafters</a> webring:</p>
|
</div>
|
||||||
</div>
|
<div class="craftering mt-2 flex items-center justify-center gap-4 text-accent-blue">
|
||||||
<div class="craftering mt-2 flex items-center justify-center gap-4 text-accent-blue">
|
<a href="https://craftering.systemcrafters.net/@glenneth/previous" class="hover:text-accent-cyan">Previous</a>
|
||||||
<a href="https://craftering.systemcrafters.net/@glenneth/previous" class="hover:text-accent-cyan">Previous</a>
|
<a href="https://craftering.systemcrafters.net/@glenneth" class="hover:text-accent-cyan">Random</a>
|
||||||
<a href="https://craftering.systemcrafters.net/@glenneth" class="hover:text-accent-cyan">Random</a>
|
<a href="https://craftering.systemcrafters.net/@glenneth/next" class="hover:text-accent-cyan">Next</a>
|
||||||
<a href="https://craftering.systemcrafters.net/@glenneth/next" class="hover:text-accent-cyan">Next</a>
|
</div>
|
||||||
</div>
|
<p class="text-palenight-300 mt-2">
|
||||||
<p class="text-palenight-300 mt-2">
|
<a href="mailto:glenn@glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenn@glenneth.org</a> |
|
||||||
<a href="mailto:glenn@glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenn@glenneth.org</a> |
|
<a href="https://glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenneth.org</a>
|
||||||
<a href="https://glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenneth.org</a>
|
</p>
|
||||||
</p>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</footer>
|
||||||
</footer>
|
</body>
|
||||||
</body>
|
|
||||||
</html>
|
</html>
|
||||||
|
|
@ -1,197 +1,196 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en" class="bg-base-bg">
|
<html lang="en" class="bg-base-bg">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<meta name="description" content="A reflection on my evolving journey through static site generators - from Hugo to Haunt, and finally to building my own custom solution, highlighting the valuable lessons learned along the way.">
|
<meta name="description" content="">
|
||||||
<meta property="og:title" content="From Hugo to Haunt to Custom: My Journey in Static Site Generation">
|
<meta property="og:title" content="Blog Post">
|
||||||
<meta property="og:description" content="A reflection on my evolving journey through static site generators - from Hugo to Haunt, and finally to building my own custom solution, highlighting the valuable lessons learned along the way.">
|
<meta property="og:description" content="">
|
||||||
<meta property="og:url" content="https://glenneth.orgcontent/posts/2025-01-02-from-haunt-to-custom">
|
<meta property="og:url" content="https://glenneth.orgcontent/posts/2025-01-02-from-haunt-to-custom">
|
||||||
<title>From Hugo to Haunt to Custom: My Journey in Static Site Generation - Glenn Thompson</title>
|
<title>Blog Post - Glenn Thompson</title>
|
||||||
<link rel="alternate" type="application/rss+xml" title="Glenn Thompson's Blog" href="/feed.xml" />
|
<link rel="alternate" type="application/rss+xml" title="Glenn Thompson's Blog" href="/feed.xml" />
|
||||||
<link href="/dist/styles.css" rel="stylesheet">
|
<link href="/dist/styles.css" rel="stylesheet">
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Merriweather:wght@400;700&family=JetBrains+Mono:wght@400;700&display=swap" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Merriweather:wght@400;700&family=JetBrains+Mono:wght@400;700&display=swap" rel="stylesheet">
|
||||||
<style>
|
<style>
|
||||||
.prose-palenight {
|
.prose-palenight {
|
||||||
--tw-prose-body: #bfc7d5;
|
--tw-prose-body: #bfc7d5;
|
||||||
--tw-prose-headings: #ffd580;
|
--tw-prose-headings: #ffd580;
|
||||||
--tw-prose-links: #82aaff;
|
--tw-prose-links: #82aaff;
|
||||||
--tw-prose-code: #c792ea;
|
--tw-prose-code: #c792ea;
|
||||||
--tw-prose-pre-bg: #1b1e2b;
|
--tw-prose-pre-bg: #1b1e2b;
|
||||||
}
|
}
|
||||||
.prose h2 {
|
.prose h2 {
|
||||||
color: var(--tw-prose-headings);
|
color: var(--tw-prose-headings);
|
||||||
font-family: Merriweather, serif;
|
font-family: Merriweather, serif;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
font-size: 1.5rem;
|
font-size: 1.5rem;
|
||||||
margin-top: 2rem;
|
margin-top: 2rem;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
}
|
}
|
||||||
.prose p {
|
.prose p {
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
line-height: 1.625;
|
line-height: 1.625;
|
||||||
}
|
}
|
||||||
.prose a {
|
.prose a {
|
||||||
color: var(--tw-prose-links);
|
color: var(--tw-prose-links);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
.prose a:hover {
|
.prose a:hover {
|
||||||
color: #89ddff;
|
color: #89ddff;
|
||||||
}
|
}
|
||||||
.prose code {
|
.prose code {
|
||||||
color: var(--tw-prose-code);
|
color: var(--tw-prose-code);
|
||||||
font-family: 'JetBrains Mono', monospace;
|
font-family: 'JetBrains Mono', monospace;
|
||||||
}
|
}
|
||||||
.prose pre {
|
.prose pre {
|
||||||
background-color: var(--tw-prose-pre-bg);
|
background-color: var(--tw-prose-pre-bg);
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
}
|
}
|
||||||
.prose ul, .prose ol {
|
.prose ul, .prose ol {
|
||||||
margin-top: 0.5rem;
|
margin-top: 0.5rem;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
padding-left: 1.5rem;
|
padding-left: 1.5rem;
|
||||||
}
|
}
|
||||||
.prose ul {
|
.prose ul {
|
||||||
list-style-type: disc;
|
list-style-type: disc;
|
||||||
}
|
}
|
||||||
.prose ol {
|
.prose ol {
|
||||||
list-style-type: decimal;
|
list-style-type: decimal;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body class="bg-base-bg text-palenight-50">
|
<body class="bg-base-bg text-palenight-50">
|
||||||
<nav class="bg-base-darker/80 backdrop-blur-sm shadow-sm border-b border-palenight-400/20 mb-8">
|
<nav class="bg-base-darker/80 backdrop-blur-sm shadow-sm border-b border-palenight-400/20 mb-8">
|
||||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<div class="flex items-center justify-between h-16">
|
<div class="flex items-center justify-between h-16">
|
||||||
<a href="/" class="text-accent-yellow font-serif text-xl font-bold">Glenn Thompson</a>
|
<a href="/" class="text-accent-yellow font-serif text-xl font-bold">Glenn Thompson</a>
|
||||||
<div class="flex items-center gap-2 text-accent-yellow text-sm font-bold">
|
<div class="flex items-center gap-2 text-accent-yellow text-sm font-bold">
|
||||||
<span>web, development, javascript, static-site, haunt, guile, hugo</span>
|
<span>Tech</span>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<time datetime="2025-01-02">January 2, 2025</time>
|
<time datetime="undefined">Invalid Date</time>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<span>4 min read</span>
|
<span>5 min read</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<main class="pt-24 pb-16 px-4">
|
<main class="pt-24 pb-16 px-4">
|
||||||
<div class="max-w-4xl mx-auto">
|
<div class="max-w-4xl mx-auto">
|
||||||
<div class="content text-palenight-100 space-y-6">
|
<div class="content text-palenight-100 space-y-6">
|
||||||
<header class="mb-8">
|
<header class="mb-8">
|
||||||
<h1 class="text-4xl font-serif font-bold text-accent-yellow">From Hugo to Haunt to Custom: My Journey in Static Site Generation</h1>
|
<h1 class="text-4xl font-serif font-bold text-accent-yellow">Blog Post</h1>
|
||||||
<div class="flex items-center gap-4 text-palenight-300 mt-4">
|
<div class="flex items-center gap-4 text-palenight-300 mt-4">
|
||||||
<time datetime="2025-01-02">2025-01-02</time>
|
<time datetime=""></time>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<span>4 min read</span>
|
<span>5 min read</span>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<span>By Glenn Thompson</span>
|
<span>By Glenn Thompson</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-wrap gap-2 mt-4">
|
</header>
|
||||||
<span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">web</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">development</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">javascript</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">static-site</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">haunt</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">guile</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">hugo</span>
|
|
||||||
</div>
|
<article class="prose prose-palenight max-w-none">
|
||||||
</header>
|
<hr>
|
||||||
|
<h2>title: From Hugo to Haunt to Custom: My Journey in Static Site Generation<br>date: 2025-01-02<br>tags: web, development, javascript, static-site, haunt, guile, hugo<br>description: A reflection on my evolving journey through static site generators - from Hugo to Haunt, and finally to building my own custom solution, highlighting the valuable lessons learned along the way.</h2>
|
||||||
<article class="prose prose-palenight max-w-none">
|
<p>My journey with static site generators has been one of continuous learning and evolution. It started with Hugo, transitioned through Haunt, and has now led me to build my own custom solution. Each step of this journey has taught me valuable lessons about web development, programming languages, and the importance of understanding the tools we use.</p>
|
||||||
<p>My journey with static site generators has been one of continuous learning and evolution. It started with Hugo, transitioned through Haunt, and has now led me to build my own custom solution. Each step of this journey has taught me valuable lessons about web development, programming languages, and the importance of understanding the tools we use.</p>
|
<h2>The Hugo Beginning</h2>
|
||||||
<h2>The Hugo Beginning</h2>
|
<p>Like many "bloggers", I started with Hugo, a popular static site generator known for its speed and extensive theme ecosystem. Hugo served its purpose well, providing a robust platform for my blog with ready-made themes and a strong community.</p>
|
||||||
<p>Like many "bloggers", I started with Hugo, a popular static site generator known for its speed and extensive theme ecosystem. Hugo served its purpose well, providing a robust platform for my blog with ready-made themes and a strong community.</p>
|
<h2>The Transition to Haunt</h2>
|
||||||
<h2>The Transition to Haunt</h2>
|
<p>My journey took an interesting turn when I joined the <a href="https://systemcrafters.net/community/">System Crafters Community</a>. Through David Wilson's excellent course, <a href="https://systemcrafters.net/courses/hands-on-guile-scheme-beginners/">Hands-On Guile Scheme for Beginners</a>, I was introduced to the world of Scheme programming. This led me to adopt GNU Guix as my operating system, which naturally led me to <a href="https://dthompson.us/projects/haunt.html">Haunt</a>, a static site generator written in Guile Scheme.</p>
|
||||||
<p>My journey took an interesting turn when I joined the <a href="https://systemcrafters.net/community/">System Crafters Community</a>. Through David Wilson's excellent course, <a href="https://systemcrafters.net/courses/hands-on-guile-scheme-beginners/">Hands-On Guile Scheme for Beginners</a>, I was introduced to the world of Scheme programming. This led me to adopt GNU Guix as my operating system, which naturally led me to <a href="https://dthompson.us/projects/haunt.html">Haunt</a>, a static site generator written in Guile Scheme.</p>
|
<p>The transition to Haunt was motivated by several factors:</p>
|
||||||
<p>The transition to Haunt was motivated by several factors:</p>
|
<ul>
|
||||||
<ul>
|
<li>Alignment with my growing interest in Scheme and functional programming</li>
|
||||||
<li>Alignment with my growing interest in Scheme and functional programming</li>
|
<li>Integration with the GNU Guix ecosystem</li>
|
||||||
<li>Integration with the GNU Guix ecosystem</li>
|
<li>The opportunity to write site configuration in Scheme</li>
|
||||||
<li>The opportunity to write site configuration in Scheme</li>
|
<li>A desire for a simpler, more controllable setup</li>
|
||||||
<li>A desire for a simpler, more controllable setup</li>
|
</ul>
|
||||||
</ul>
|
<h3>The Haunt Experience</h3>
|
||||||
<h3>The Haunt Experience</h3>
|
<p>Haunt offered a different perspective on site generation. Some highlights of my Haunt experience included:</p>
|
||||||
<p>Haunt offered a different perspective on site generation. Some highlights of my Haunt experience included:</p>
|
<ul>
|
||||||
<ul>
|
<li>Writing site configuration in Scheme, which felt natural after learning Guile</li>
|
||||||
<li>Writing site configuration in Scheme, which felt natural after learning Guile</li>
|
<li>Creating custom templates that matched my site's aesthetic needs</li>
|
||||||
<li>Creating custom templates that matched my site's aesthetic needs</li>
|
<li>Learning to leverage Scheme's flexibility for site customization</li>
|
||||||
<li>Learning to leverage Scheme's flexibility for site customization</li>
|
<li>Being part of a community that values simplicity and transparency</li>
|
||||||
<li>Being part of a community that values simplicity and transparency</li>
|
</ul>
|
||||||
</ul>
|
<p>However, working with Haunt also presented challenges:</p>
|
||||||
<p>However, working with Haunt also presented challenges:</p>
|
<ul>
|
||||||
<ul>
|
<li>Limited availability of ready-made templates</li>
|
||||||
<li>Limited availability of ready-made templates</li>
|
<li>Need to create custom solutions for common features</li>
|
||||||
<li>Need to create custom solutions for common features</li>
|
<li>Learning curve of Scheme for web development</li>
|
||||||
<li>Learning curve of Scheme for web development</li>
|
</ul>
|
||||||
</ul>
|
<h2>The Move to Custom Development</h2>
|
||||||
<h2>The Move to Custom Development</h2>
|
<p>As I became more comfortable with web development and gained a deeper understanding of static site generation, I felt ready for the next step: building my own static site generator. This decision wasn't about Haunt's limitations - it was about the desire to understand every aspect of my site's generation process and have complete control over its architecture.</p>
|
||||||
<p>As I became more comfortable with web development and gained a deeper understanding of static site generation, I felt ready for the next step: building my own static site generator. This decision wasn't about Haunt's limitations - it was about the desire to understand every aspect of my site's generation process and have complete control over its architecture.</p>
|
<h2>The New Architecture</h2>
|
||||||
<h2>The New Architecture</h2>
|
<p>My custom solution combines the lessons learned from both Hugo and Haunt with modern web development practices:</p>
|
||||||
<p>My custom solution combines the lessons learned from both Hugo and Haunt with modern web development practices:</p>
|
<ul>
|
||||||
<ul>
|
<li><strong>Modern JavaScript</strong>: Using Node.js and contemporary JavaScript tools</li>
|
||||||
<li><strong>Modern JavaScript</strong>: Using Node.js and contemporary JavaScript tools</li>
|
<li><strong>Markdown Processing</strong>: Leveraging the <code>marked</code> library for flexible content processing</li>
|
||||||
<li><strong>Markdown Processing</strong>: Leveraging the <code>marked</code> library for flexible content processing</li>
|
<li><strong>Tailwind CSS</strong>: Adopting a utility-first approach to styling</li>
|
||||||
<li><strong>Tailwind CSS</strong>: Adopting a utility-first approach to styling</li>
|
<li><strong>Simple Build Process</strong>: A straightforward build script that handles all aspects of site generation</li>
|
||||||
<li><strong>Simple Build Process</strong>: A straightforward build script that handles all aspects of site generation</li>
|
<li><strong>Development Server</strong>: Live reload functionality for immediate feedback</li>
|
||||||
<li><strong>Development Server</strong>: Live reload functionality for immediate feedback</li>
|
</ul>
|
||||||
</ul>
|
<h2>Benefits of the Custom Solution</h2>
|
||||||
<h2>Benefits of the Custom Solution</h2>
|
<p>Building my own solution has brought several advantages:</p>
|
||||||
<p>Building my own solution has brought several advantages:</p>
|
<ol>
|
||||||
<ol>
|
<li><strong>Complete Understanding</strong>: I now understand every aspect of my site's generation</li>
|
||||||
<li><strong>Complete Understanding</strong>: I now understand every aspect of my site's generation</li>
|
<li><strong>Faster Iterations</strong>: Quick implementation of new features</li>
|
||||||
<li><strong>Faster Iterations</strong>: Quick implementation of new features</li>
|
<li><strong>Modern Development</strong>: Integration with current web development tools</li>
|
||||||
<li><strong>Modern Development</strong>: Integration with current web development tools</li>
|
<li><strong>Simplified Deployment</strong>: Streamlined process for updates</li>
|
||||||
<li><strong>Simplified Deployment</strong>: Streamlined process for updates</li>
|
<li><strong>Better Performance</strong>: Only including features I actually need</li>
|
||||||
<li><strong>Better Performance</strong>: Only including features I actually need</li>
|
</ol>
|
||||||
</ol>
|
<h2>Learning Experience</h2>
|
||||||
<h2>Learning Experience</h2>
|
<p>This journey from Hugo through Haunt to a custom solution has taught me:</p>
|
||||||
<p>This journey from Hugo through Haunt to a custom solution has taught me:</p>
|
<ul>
|
||||||
<ul>
|
<li>The value of understanding different approaches to static site generation</li>
|
||||||
<li>The value of understanding different approaches to static site generation</li>
|
<li>The importance of choosing tools that align with your learning goals</li>
|
||||||
<li>The importance of choosing tools that align with your learning goals</li>
|
<li>How different programming paradigms (Go, Scheme, JavaScript) approach similar problems</li>
|
||||||
<li>How different programming paradigms (Go, Scheme, JavaScript) approach similar problems</li>
|
<li>The benefits of building your own tools when the learning opportunity outweighs convenience</li>
|
||||||
<li>The benefits of building your own tools when the learning opportunity outweighs convenience</li>
|
</ul>
|
||||||
</ul>
|
<h2>Future Improvements</h2>
|
||||||
<h2>Future Improvements</h2>
|
<p>While my custom solution meets my current needs, I'm excited about potential improvements:</p>
|
||||||
<p>While my custom solution meets my current needs, I'm excited about potential improvements:</p>
|
<ul>
|
||||||
<ul>
|
<li>Adding support for draft posts</li>
|
||||||
<li>Adding support for draft posts</li>
|
<li>Implementing a tag-based navigation system</li>
|
||||||
<li>Implementing a tag-based navigation system</li>
|
<li>Adding search functionality</li>
|
||||||
<li>Adding search functionality</li>
|
<li>Improving the build process</li>
|
||||||
<li>Improving the build process</li>
|
<li>Adding image optimization</li>
|
||||||
<li>Adding image optimization</li>
|
</ul>
|
||||||
</ul>
|
<h2>Conclusion</h2>
|
||||||
<h2>Conclusion</h2>
|
<p>My journey from Hugo through Haunt to a custom solution reflects a common pattern in software development - starting with established tools, learning their principles, and eventually building your own solutions. Each step has been valuable:</p>
|
||||||
<p>My journey from Hugo through Haunt to a custom solution reflects a common pattern in software development - starting with established tools, learning their principles, and eventually building your own solutions. Each step has been valuable:</p>
|
<ul>
|
||||||
<ul>
|
<li>Hugo taught me about static site generators and their capabilities</li>
|
||||||
<li>Hugo taught me about static site generators and their capabilities</li>
|
<li>Haunt introduced me to functional programming and the beauty of Scheme</li>
|
||||||
<li>Haunt introduced me to functional programming and the beauty of Scheme</li>
|
<li>Building my own solution has given me deep insights into web development</li>
|
||||||
<li>Building my own solution has given me deep insights into web development</li>
|
</ul>
|
||||||
</ul>
|
<p>The source code for my site generator is available on <a href="https://github.com/glenneth1/personal-website">GitHub</a>. While it may not be the most feature-rich static site generator, it's perfectly tailored to my needs and represents a significant learning journey.</p>
|
||||||
<p>The source code for my site generator is available on <a href="https://github.com/glenneth1/personal-website">GitHub</a>. While it may not be the most feature-rich static site generator, it's perfectly tailored to my needs and represents a significant learning journey.</p>
|
<p>Remember, the goal of building your own tools isn't always to create something better than existing solutions - sometimes it's about the learning experience and creating something that perfectly fits your specific needs. Whether you're using Hugo, Haunt, or considering building your own solution, the most important thing is that it serves your purposes and helps you grow.</p>
|
||||||
<p>Remember, the goal of building your own tools isn't always to create something better than existing solutions - sometimes it's about the learning experience and creating something that perfectly fits your specific needs. Whether you're using Hugo, Haunt, or considering building your own solution, the most important thing is that it serves your purposes and helps you grow.</p>
|
|
||||||
|
</article>
|
||||||
</article>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</main>
|
||||||
</main>
|
<footer class="bg-base-darker text-palenight-200 py-12 border-t border-palenight-400/20">
|
||||||
<footer class="bg-base-darker text-palenight-200 py-12 border-t border-palenight-400/20">
|
<div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
<div class="text-center">
|
||||||
<div class="text-center">
|
<p class="text-palenight-300">© 2026 Glenn Thompson. All rights reserved.</p>
|
||||||
<p class="text-palenight-300">© 2024 Glenn Thompson. All rights reserved.</p>
|
<div class="webring-text mt-6">
|
||||||
<div class="webring-text mt-6">
|
<p class="text-palenight-300">I am part of the <a href="https://systemcrafters.net" target="_blank" class="text-accent-blue hover:text-accent-cyan">System Crafters</a> webring:</p>
|
||||||
<p class="text-palenight-300">I am part of the <a href="https://systemcrafters.net" target="_blank" class="text-accent-blue hover:text-accent-cyan">System Crafters</a> webring:</p>
|
</div>
|
||||||
</div>
|
<div class="craftering mt-2 flex items-center justify-center gap-4 text-accent-blue">
|
||||||
<div class="craftering mt-2 flex items-center justify-center gap-4 text-accent-blue">
|
<a href="https://craftering.systemcrafters.net/@glenneth/previous" class="hover:text-accent-cyan">Previous</a>
|
||||||
<a href="https://craftering.systemcrafters.net/@glenneth/previous" class="hover:text-accent-cyan">Previous</a>
|
<a href="https://craftering.systemcrafters.net/@glenneth" class="hover:text-accent-cyan">Random</a>
|
||||||
<a href="https://craftering.systemcrafters.net/@glenneth" class="hover:text-accent-cyan">Random</a>
|
<a href="https://craftering.systemcrafters.net/@glenneth/next" class="hover:text-accent-cyan">Next</a>
|
||||||
<a href="https://craftering.systemcrafters.net/@glenneth/next" class="hover:text-accent-cyan">Next</a>
|
</div>
|
||||||
</div>
|
<p class="text-palenight-300 mt-2">
|
||||||
<p class="text-palenight-300 mt-2">
|
<a href="mailto:glenn@glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenn@glenneth.org</a> |
|
||||||
<a href="mailto:glenn@glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenn@glenneth.org</a> |
|
<a href="https://glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenneth.org</a>
|
||||||
<a href="https://glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenneth.org</a>
|
</p>
|
||||||
</p>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</footer>
|
||||||
</footer>
|
</body>
|
||||||
</body>
|
|
||||||
</html>
|
</html>
|
||||||
|
|
@ -1,323 +1,322 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en" class="bg-base-bg">
|
<html lang="en" class="bg-base-bg">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<meta name="description" content="A comprehensive look at my current development setup in 2025, covering everything from my GNU Guix system foundation to editor configurations, terminal tools, and deployment processes.">
|
<meta name="description" content="">
|
||||||
<meta property="og:title" content="My Development Environment in 2025: From Editor to Deployment">
|
<meta property="og:title" content="Blog Post">
|
||||||
<meta property="og:description" content="A comprehensive look at my current development setup in 2025, covering everything from my GNU Guix system foundation to editor configurations, terminal tools, and deployment processes.">
|
<meta property="og:description" content="">
|
||||||
<meta property="og:url" content="https://glenneth.orgcontent/posts/2025-03-08-my-dev-environment-2025">
|
<meta property="og:url" content="https://glenneth.orgcontent/posts/2025-03-08-my-dev-environment-2025">
|
||||||
<title>My Development Environment in 2025: From Editor to Deployment - Glenn Thompson</title>
|
<title>Blog Post - Glenn Thompson</title>
|
||||||
<link rel="alternate" type="application/rss+xml" title="Glenn Thompson's Blog" href="/feed.xml" />
|
<link rel="alternate" type="application/rss+xml" title="Glenn Thompson's Blog" href="/feed.xml" />
|
||||||
<link href="/dist/styles.css" rel="stylesheet">
|
<link href="/dist/styles.css" rel="stylesheet">
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Merriweather:wght@400;700&family=JetBrains+Mono:wght@400;700&display=swap" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Merriweather:wght@400;700&family=JetBrains+Mono:wght@400;700&display=swap" rel="stylesheet">
|
||||||
<style>
|
<style>
|
||||||
.prose-palenight {
|
.prose-palenight {
|
||||||
--tw-prose-body: #bfc7d5;
|
--tw-prose-body: #bfc7d5;
|
||||||
--tw-prose-headings: #ffd580;
|
--tw-prose-headings: #ffd580;
|
||||||
--tw-prose-links: #82aaff;
|
--tw-prose-links: #82aaff;
|
||||||
--tw-prose-code: #c792ea;
|
--tw-prose-code: #c792ea;
|
||||||
--tw-prose-pre-bg: #1b1e2b;
|
--tw-prose-pre-bg: #1b1e2b;
|
||||||
}
|
}
|
||||||
.prose h2 {
|
.prose h2 {
|
||||||
color: var(--tw-prose-headings);
|
color: var(--tw-prose-headings);
|
||||||
font-family: Merriweather, serif;
|
font-family: Merriweather, serif;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
font-size: 1.5rem;
|
font-size: 1.5rem;
|
||||||
margin-top: 2rem;
|
margin-top: 2rem;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
}
|
}
|
||||||
.prose p {
|
.prose p {
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
line-height: 1.625;
|
line-height: 1.625;
|
||||||
}
|
}
|
||||||
.prose a {
|
.prose a {
|
||||||
color: var(--tw-prose-links);
|
color: var(--tw-prose-links);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
.prose a:hover {
|
.prose a:hover {
|
||||||
color: #89ddff;
|
color: #89ddff;
|
||||||
}
|
}
|
||||||
.prose code {
|
.prose code {
|
||||||
color: var(--tw-prose-code);
|
color: var(--tw-prose-code);
|
||||||
font-family: 'JetBrains Mono', monospace;
|
font-family: 'JetBrains Mono', monospace;
|
||||||
}
|
}
|
||||||
.prose pre {
|
.prose pre {
|
||||||
background-color: var(--tw-prose-pre-bg);
|
background-color: var(--tw-prose-pre-bg);
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
}
|
}
|
||||||
.prose ul, .prose ol {
|
.prose ul, .prose ol {
|
||||||
margin-top: 0.5rem;
|
margin-top: 0.5rem;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
padding-left: 1.5rem;
|
padding-left: 1.5rem;
|
||||||
}
|
}
|
||||||
.prose ul {
|
.prose ul {
|
||||||
list-style-type: disc;
|
list-style-type: disc;
|
||||||
}
|
}
|
||||||
.prose ol {
|
.prose ol {
|
||||||
list-style-type: decimal;
|
list-style-type: decimal;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body class="bg-base-bg text-palenight-50">
|
<body class="bg-base-bg text-palenight-50">
|
||||||
<nav class="bg-base-darker/80 backdrop-blur-sm shadow-sm border-b border-palenight-400/20 mb-8">
|
<nav class="bg-base-darker/80 backdrop-blur-sm shadow-sm border-b border-palenight-400/20 mb-8">
|
||||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<div class="flex items-center justify-between h-16">
|
<div class="flex items-center justify-between h-16">
|
||||||
<a href="/" class="text-accent-yellow font-serif text-xl font-bold">Glenn Thompson</a>
|
<a href="/" class="text-accent-yellow font-serif text-xl font-bold">Glenn Thompson</a>
|
||||||
<div class="flex items-center gap-2 text-accent-yellow text-sm font-bold">
|
<div class="flex items-center gap-2 text-accent-yellow text-sm font-bold">
|
||||||
<span>development, guix, tools, workflow, productivity, web</span>
|
<span>Tech</span>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<time datetime="2025-03-08">March 8, 2025</time>
|
<time datetime="undefined">Invalid Date</time>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<span>6 min read</span>
|
<span>6 min read</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<main class="pt-24 pb-16 px-4">
|
<main class="pt-24 pb-16 px-4">
|
||||||
<div class="max-w-4xl mx-auto">
|
<div class="max-w-4xl mx-auto">
|
||||||
<div class="content text-palenight-100 space-y-6">
|
<div class="content text-palenight-100 space-y-6">
|
||||||
<header class="mb-8">
|
<header class="mb-8">
|
||||||
<h1 class="text-4xl font-serif font-bold text-accent-yellow">My Development Environment in 2025: From Editor to Deployment</h1>
|
<h1 class="text-4xl font-serif font-bold text-accent-yellow">Blog Post</h1>
|
||||||
<div class="flex items-center gap-4 text-palenight-300 mt-4">
|
<div class="flex items-center gap-4 text-palenight-300 mt-4">
|
||||||
<time datetime="2025-03-08">2025-03-08</time>
|
<time datetime=""></time>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<span>6 min read</span>
|
<span>6 min read</span>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<span>By Glenn Thompson</span>
|
<span>By Glenn Thompson</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-wrap gap-2 mt-4">
|
</header>
|
||||||
<span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">development</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">guix</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">tools</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">workflow</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">productivity</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">web</span>
|
|
||||||
</div>
|
<article class="prose prose-palenight max-w-none">
|
||||||
</header>
|
<hr>
|
||||||
|
<h2>title: My Development Environment in 2025: From Editor to Deployment<br>date: 2025-03-08<br>tags: development, guix, tools, workflow, productivity, web<br>description: A comprehensive look at my current development setup in 2025, covering everything from my GNU Guix system foundation to editor configurations, terminal tools, and deployment processes.</h2>
|
||||||
<article class="prose prose-palenight max-w-none">
|
<h2>Introduction</h2>
|
||||||
<h2>Introduction</h2>
|
<p>The tools we use shape how we work. Over the years, my development environment has evolved alongside my technical journey through different programming languages, paradigms, and projects. This post offers a snapshot of my current setup in early 2025, detailing the choices I've made and why they work for me.</p>
|
||||||
<p>The tools we use shape how we work. Over the years, my development environment has evolved alongside my technical journey through different programming languages, paradigms, and projects. This post offers a snapshot of my current setup in early 2025, detailing the choices I've made and why they work for me.</p>
|
<h2>System Foundation: ArcoLinux with GNU Guix</h2>
|
||||||
<h2>System Foundation: ArcoLinux with GNU Guix</h2>
|
<p>My journey to <a href="https://guix.gnu.org/">GNU Guix</a> began through my exploration of Scheme programming, as I detailed in my <a href="/content/posts/2024-07-26-gnu-guix-journey.html">GNU Guix Journey</a> post. While I initially experimented with Guix System, I've settled on a hybrid approach: running Guix as a package manager on top of ArcoLinux (an Arch-based distribution).</p>
|
||||||
<p>My journey to <a href="https://guix.gnu.org/">GNU Guix</a> began through my exploration of Scheme programming, as I detailed in my <a href="/content/posts/2024-07-26-gnu-guix-journey.html">GNU Guix Journey</a> post. While I initially experimented with Guix System, I've settled on a hybrid approach: running Guix as a package manager on top of ArcoLinux (an Arch-based distribution).</p>
|
<h3>Current Configuration Approach</h3>
|
||||||
<h3>Current Configuration Approach</h3>
|
<p>I manage my development environment using a combination of Arch's pacman, AUR, and Guix's declarative package management. My Guix configuration lives in a Git repository, allowing me to:</p>
|
||||||
<p>I manage my development environment using a combination of Arch's pacman, AUR, and Guix's declarative package management. My Guix configuration lives in a Git repository, allowing me to:</p>
|
<ul>
|
||||||
<ul>
|
<li>Track changes to my development environment over time</li>
|
||||||
<li>Track changes to my development environment over time</li>
|
<li>Reproduce my development setup on new hardware</li>
|
||||||
<li>Reproduce my development setup on new hardware</li>
|
<li>Roll back to previous package states when needed</li>
|
||||||
<li>Roll back to previous package states when needed</li>
|
<li>Share configuration snippets with the community</li>
|
||||||
<li>Share configuration snippets with the community</li>
|
</ul>
|
||||||
</ul>
|
<h3>Key Packages and Tools</h3>
|
||||||
<h3>Key Packages and Tools</h3>
|
<p>I maintain a hybrid package approach:</p>
|
||||||
<p>I maintain a hybrid package approach:</p>
|
<p><strong>System packages (via pacman/AUR):</strong></p>
|
||||||
<p><strong>System packages (via pacman/AUR):</strong></p>
|
<ul>
|
||||||
<ul>
|
<li>Base system utilities and desktop environment</li>
|
||||||
<li>Base system utilities and desktop environment</li>
|
<li>Graphics drivers and hardware support</li>
|
||||||
<li>Graphics drivers and hardware support</li>
|
<li>Some GUI applications</li>
|
||||||
<li>Some GUI applications</li>
|
</ul>
|
||||||
</ul>
|
<p><strong>Development tools (via Guix):</strong></p>
|
||||||
<p><strong>Development tools (via Guix):</strong></p>
|
<pre><code class="language-scheme">;; My primary development tools managed by Guix
|
||||||
<pre><code class="language-scheme">;; My primary development tools managed by Guix
|
(specifications->manifest
|
||||||
(specifications->manifest
|
'("emacs" "git" "openssh" "ripgrep" "fd" "exa" "bat"
|
||||||
'("emacs" "git" "openssh" "ripgrep" "fd" "exa" "bat"
|
"guile" "node" "python" "gcc-toolchain" "make"
|
||||||
"guile" "node" "python" "gcc-toolchain" "make"
|
"nss-certs" "glibc-locales"))
|
||||||
"nss-certs" "glibc-locales"))
|
</code></pre>
|
||||||
</code></pre>
|
<p>This hybrid approach gives me the best of both worlds: Arch's extensive package repository and up-to-date system packages, combined with Guix's reproducible development environments.</p>
|
||||||
<p>This hybrid approach gives me the best of both worlds: Arch's extensive package repository and up-to-date system packages, combined with Guix's reproducible development environments.</p>
|
<h3>Reproducibility Benefits</h3>
|
||||||
<h3>Reproducibility Benefits</h3>
|
<p>The reproducibility of Guix for development environments has been invaluable. I can:</p>
|
||||||
<p>The reproducibility of Guix for development environments has been invaluable. I can:</p>
|
<ul>
|
||||||
<ul>
|
<li>Spin up development environments with precise dependencies</li>
|
||||||
<li>Spin up development environments with precise dependencies</li>
|
<li>Ensure consistent behavior across machines</li>
|
||||||
<li>Ensure consistent behavior across machines</li>
|
<li>Isolate project-specific dependencies using Guix environments</li>
|
||||||
<li>Isolate project-specific dependencies using Guix environments</li>
|
<li>Share exact environment specifications with collaborators</li>
|
||||||
<li>Share exact environment specifications with collaborators</li>
|
</ul>
|
||||||
</ul>
|
<h3>Challenges and Solutions</h3>
|
||||||
<h3>Challenges and Solutions</h3>
|
<p>Working with this hybrid approach isn't without challenges:</p>
|
||||||
<p>Working with this hybrid approach isn't without challenges:</p>
|
<ul>
|
||||||
<ul>
|
<li><p><strong>Challenge</strong>: Keeping Guix packages in sync with system libraries<br><strong>Solution</strong>: Careful management of library paths and containerization when needed</p>
|
||||||
<li><p><strong>Challenge</strong>: Keeping Guix packages in sync with system libraries<br><strong>Solution</strong>: Careful management of library paths and containerization when needed</p>
|
</li>
|
||||||
</li>
|
<li><p><strong>Challenge</strong>: Learning curve for Guix's declarative configuration<br><strong>Solution</strong>: Incremental adoption and community resources</p>
|
||||||
<li><p><strong>Challenge</strong>: Learning curve for Guix's declarative configuration<br><strong>Solution</strong>: Incremental adoption and community resources</p>
|
</li>
|
||||||
</li>
|
<li><p><strong>Challenge</strong>: Occasional conflicts between package managers<br><strong>Solution</strong>: Clear separation of responsibilities (system vs. development tools)</p>
|
||||||
<li><p><strong>Challenge</strong>: Occasional conflicts between package managers<br><strong>Solution</strong>: Clear separation of responsibilities (system vs. development tools)</p>
|
</li>
|
||||||
</li>
|
</ul>
|
||||||
</ul>
|
<h2>Editor Environment: Emacs</h2>
|
||||||
<h2>Editor Environment: Emacs</h2>
|
<p>After experimenting with various editors, I've settled on Emacs as my primary development environment. Its extensibility and Scheme-based configuration language (Emacs Lisp) align well with my interests.</p>
|
||||||
<p>After experimenting with various editors, I've settled on Emacs as my primary development environment. Its extensibility and Scheme-based configuration language (Emacs Lisp) align well with my interests.</p>
|
<h3>Configuration Approach</h3>
|
||||||
<h3>Configuration Approach</h3>
|
<p>I use a literate configuration with Org mode, which allows me to:</p>
|
||||||
<p>I use a literate configuration with Org mode, which allows me to:</p>
|
<ul>
|
||||||
<ul>
|
<li>Document my configuration choices</li>
|
||||||
<li>Document my configuration choices</li>
|
<li>Organize settings by purpose rather than file</li>
|
||||||
<li>Organize settings by purpose rather than file</li>
|
<li>Selectively load components based on context</li>
|
||||||
<li>Selectively load components based on context</li>
|
<li>Share readable documentation with others</li>
|
||||||
<li>Share readable documentation with others</li>
|
</ul>
|
||||||
</ul>
|
<h3>Key Extensions</h3>
|
||||||
<h3>Key Extensions</h3>
|
<p>My most valuable Emacs extensions include:</p>
|
||||||
<p>My most valuable Emacs extensions include:</p>
|
<ul>
|
||||||
<ul>
|
<li><strong>Magit</strong>: Git interface that has transformed my version control workflow</li>
|
||||||
<li><strong>Magit</strong>: Git interface that has transformed my version control workflow</li>
|
<li><strong>LSP Mode</strong>: Language server integration for intelligent code assistance</li>
|
||||||
<li><strong>LSP Mode</strong>: Language server integration for intelligent code assistance</li>
|
<li><strong>Org Mode</strong>: For notes, task management, and literate programming</li>
|
||||||
<li><strong>Org Mode</strong>: For notes, task management, and literate programming</li>
|
<li><strong>Projectile</strong>: Project navigation and management</li>
|
||||||
<li><strong>Projectile</strong>: Project navigation and management</li>
|
<li><strong>Company</strong>: Completion framework</li>
|
||||||
<li><strong>Company</strong>: Completion framework</li>
|
<li><strong>Consult/Vertico/Marginalia</strong>: Modern completion UI</li>
|
||||||
<li><strong>Consult/Vertico/Marginalia</strong>: Modern completion UI</li>
|
<li><strong>Tree-sitter</strong>: Improved syntax highlighting and structural editing</li>
|
||||||
<li><strong>Tree-sitter</strong>: Improved syntax highlighting and structural editing</li>
|
</ul>
|
||||||
</ul>
|
<h3>Language-Specific Setups</h3>
|
||||||
<h3>Language-Specific Setups</h3>
|
<p>For my primary languages:</p>
|
||||||
<p>For my primary languages:</p>
|
<ul>
|
||||||
<ul>
|
<li><strong>Scheme/Guile</strong>: Geiser for REPL integration</li>
|
||||||
<li><strong>Scheme/Guile</strong>: Geiser for REPL integration</li>
|
<li><strong>JavaScript/TypeScript</strong>: TypeScript LSP, prettier, eslint integration</li>
|
||||||
<li><strong>JavaScript/TypeScript</strong>: TypeScript LSP, prettier, eslint integration</li>
|
<li><strong>Python</strong>: Pyright LSP, black formatting</li>
|
||||||
<li><strong>Python</strong>: Pyright LSP, black formatting</li>
|
<li><strong>Web Development</strong>: Web mode, emmet, css-mode</li>
|
||||||
<li><strong>Web Development</strong>: Web mode, emmet, css-mode</li>
|
</ul>
|
||||||
</ul>
|
<h3>Productivity Enhancements</h3>
|
||||||
<h3>Productivity Enhancements</h3>
|
<p>Some productivity boosters in my setup:</p>
|
||||||
<p>Some productivity boosters in my setup:</p>
|
<ul>
|
||||||
<ul>
|
<li>Custom keybindings for frequent operations</li>
|
||||||
<li>Custom keybindings for frequent operations</li>
|
<li>Snippets for common code patterns</li>
|
||||||
<li>Snippets for common code patterns</li>
|
<li>Template generation for new projects</li>
|
||||||
<li>Template generation for new projects</li>
|
<li>Integration with system notifications</li>
|
||||||
<li>Integration with system notifications</li>
|
</ul>
|
||||||
</ul>
|
<h2>Terminal and CLI Tools</h2>
|
||||||
<h2>Terminal and CLI Tools</h2>
|
<p>While Emacs handles many tasks, I still rely heavily on terminal tools for specific workflows.</p>
|
||||||
<p>While Emacs handles many tasks, I still rely heavily on terminal tools for specific workflows.</p>
|
<h3>Shell Configuration</h3>
|
||||||
<h3>Shell Configuration</h3>
|
<p>I use Zsh with a custom configuration that provides:</p>
|
||||||
<p>I use Zsh with a custom configuration that provides:</p>
|
<ul>
|
||||||
<ul>
|
<li>Intuitive aliases</li>
|
||||||
<li>Intuitive aliases</li>
|
<li>Helpful prompts with Git integration</li>
|
||||||
<li>Helpful prompts with Git integration</li>
|
<li>Command history management</li>
|
||||||
<li>Command history management</li>
|
<li>Directory navigation shortcuts</li>
|
||||||
<li>Directory navigation shortcuts</li>
|
</ul>
|
||||||
</ul>
|
<h3>Custom Scripts and Utilities</h3>
|
||||||
<h3>Custom Scripts and Utilities</h3>
|
<p>I've developed several custom scripts to streamline repetitive tasks:</p>
|
||||||
<p>I've developed several custom scripts to streamline repetitive tasks:</p>
|
<ul>
|
||||||
<ul>
|
<li>Project initialization templates</li>
|
||||||
<li>Project initialization templates</li>
|
<li>Deployment automation</li>
|
||||||
<li>Deployment automation</li>
|
<li>System maintenance routines</li>
|
||||||
<li>System maintenance routines</li>
|
<li>Content management for this blog</li>
|
||||||
<li>Content management for this blog</li>
|
</ul>
|
||||||
</ul>
|
<h3>Task Automation</h3>
|
||||||
<h3>Task Automation</h3>
|
<p>For task automation, I use a combination of:</p>
|
||||||
<p>For task automation, I use a combination of:</p>
|
<ul>
|
||||||
<ul>
|
<li>Shell scripts for simple operations</li>
|
||||||
<li>Shell scripts for simple operations</li>
|
<li>Guile scripts for more complex logic</li>
|
||||||
<li>Guile scripts for more complex logic</li>
|
<li>Make for build processes</li>
|
||||||
<li>Make for build processes</li>
|
<li>Cron for scheduled tasks</li>
|
||||||
<li>Cron for scheduled tasks</li>
|
</ul>
|
||||||
</ul>
|
<h3>Version Control Workflow</h3>
|
||||||
<h3>Version Control Workflow</h3>
|
<p>My Git workflow relies on:</p>
|
||||||
<p>My Git workflow relies on:</p>
|
<ul>
|
||||||
<ul>
|
<li>Branch-per-feature approach</li>
|
||||||
<li>Branch-per-feature approach</li>
|
<li>Interactive rebasing for clean history</li>
|
||||||
<li>Interactive rebasing for clean history</li>
|
<li>Commit message templates</li>
|
||||||
<li>Commit message templates</li>
|
<li>Hooks for quality checks</li>
|
||||||
<li>Hooks for quality checks</li>
|
</ul>
|
||||||
</ul>
|
<h2>Web Development Stack</h2>
|
||||||
<h2>Web Development Stack</h2>
|
<p>As the creator of this website, my web development setup has been refined through experience.</p>
|
||||||
<p>As the creator of this website, my web development setup has been refined through experience.</p>
|
<h3>Local Development Server</h3>
|
||||||
<h3>Local Development Server</h3>
|
<p>For local development, I use:</p>
|
||||||
<p>For local development, I use:</p>
|
<ul>
|
||||||
<ul>
|
<li>Live-server for static sites</li>
|
||||||
<li>Live-server for static sites</li>
|
<li>Custom Node.js servers for API development</li>
|
||||||
<li>Custom Node.js servers for API development</li>
|
<li>Docker containers for complex dependencies</li>
|
||||||
<li>Docker containers for complex dependencies</li>
|
</ul>
|
||||||
</ul>
|
<h3>Build Tools and Processes</h3>
|
||||||
<h3>Build Tools and Processes</h3>
|
<p>My build process typically involves:</p>
|
||||||
<p>My build process typically involves:</p>
|
<ul>
|
||||||
<ul>
|
<li>Tailwind CSS for styling</li>
|
||||||
<li>Tailwind CSS for styling</li>
|
<li>Minimal JavaScript bundling</li>
|
||||||
<li>Minimal JavaScript bundling</li>
|
<li>Custom static site generation (as detailed in my <a href="/content/posts/2025-01-02-from-haunt-to-custom.html">previous post</a>)</li>
|
||||||
<li>Custom static site generation (as detailed in my <a href="/content/posts/2025-01-02-from-haunt-to-custom.html">previous post</a>)</li>
|
<li>Automated optimization steps</li>
|
||||||
<li>Automated optimization steps</li>
|
</ul>
|
||||||
</ul>
|
<h3>Testing Approach</h3>
|
||||||
<h3>Testing Approach</h3>
|
<p>For testing, I employ:</p>
|
||||||
<p>For testing, I employ:</p>
|
<ul>
|
||||||
<ul>
|
<li>Jest for JavaScript unit tests</li>
|
||||||
<li>Jest for JavaScript unit tests</li>
|
<li>Cypress for end-to-end testing</li>
|
||||||
<li>Cypress for end-to-end testing</li>
|
<li>Manual testing across devices and browsers</li>
|
||||||
<li>Manual testing across devices and browsers</li>
|
<li>Accessibility validation tools</li>
|
||||||
<li>Accessibility validation tools</li>
|
</ul>
|
||||||
</ul>
|
<h3>Browser Tools and Extensions</h3>
|
||||||
<h3>Browser Tools and Extensions</h3>
|
<p>Essential browser tools include:</p>
|
||||||
<p>Essential browser tools include:</p>
|
<ul>
|
||||||
<ul>
|
<li>Firefox Developer Edition as my primary browser</li>
|
||||||
<li>Firefox Developer Edition as my primary browser</li>
|
<li>Chrome for cross-browser testing</li>
|
||||||
<li>Chrome for cross-browser testing</li>
|
<li>DevTools for performance analysis</li>
|
||||||
<li>DevTools for performance analysis</li>
|
<li>React and Redux DevTools</li>
|
||||||
<li>React and Redux DevTools</li>
|
<li>Accessibility checkers</li>
|
||||||
<li>Accessibility checkers</li>
|
</ul>
|
||||||
</ul>
|
<h2>Deployment Pipeline</h2>
|
||||||
<h2>Deployment Pipeline</h2>
|
<p>My approach to deployment emphasizes security and reliability.</p>
|
||||||
<p>My approach to deployment emphasizes security and reliability.</p>
|
<h3>Secure Deployment Process</h3>
|
||||||
<h3>Secure Deployment Process</h3>
|
<p>As you might have noticed from my <a href="/content/posts/2025-03-08-my-dev-environment-2025.html">.env.gpg file</a>, I take security seriously:</p>
|
||||||
<p>As you might have noticed from my <a href="/content/posts/2025-03-08-my-dev-environment-2025.html">.env.gpg file</a>, I take security seriously:</p>
|
<ul>
|
||||||
<ul>
|
<li>Credentials stored in GPG-encrypted files</li>
|
||||||
<li>Credentials stored in GPG-encrypted files</li>
|
<li>Separate development and production configurations</li>
|
||||||
<li>Separate development and production configurations</li>
|
<li>Principle of least privilege for service accounts</li>
|
||||||
<li>Principle of least privilege for service accounts</li>
|
<li>Regular security audits</li>
|
||||||
<li>Regular security audits</li>
|
</ul>
|
||||||
</ul>
|
<h3>Automation Scripts</h3>
|
||||||
<h3>Automation Scripts</h3>
|
<p>My deployment is automated through:</p>
|
||||||
<p>My deployment is automated through:</p>
|
<ul>
|
||||||
<ul>
|
<li>Custom shell scripts for build and deploy</li>
|
||||||
<li>Custom shell scripts for build and deploy</li>
|
<li>Validation steps before deployment</li>
|
||||||
<li>Validation steps before deployment</li>
|
<li>Rollback capabilities</li>
|
||||||
<li>Rollback capabilities</li>
|
<li>Notification systems for success/failure</li>
|
||||||
<li>Notification systems for success/failure</li>
|
</ul>
|
||||||
</ul>
|
<h3>CI/CD Considerations</h3>
|
||||||
<h3>CI/CD Considerations</h3>
|
<p>While not using a formal CI/CD pipeline for this personal site, I follow similar principles:</p>
|
||||||
<p>While not using a formal CI/CD pipeline for this personal site, I follow similar principles:</p>
|
<ul>
|
||||||
<ul>
|
<li>Pre-commit checks for code quality</li>
|
||||||
<li>Pre-commit checks for code quality</li>
|
<li>Automated testing before deployment</li>
|
||||||
<li>Automated testing before deployment</li>
|
<li>Consistent build environments</li>
|
||||||
<li>Consistent build environments</li>
|
<li>Deployment approval steps</li>
|
||||||
<li>Deployment approval steps</li>
|
</ul>
|
||||||
</ul>
|
<h3>Monitoring and Analytics</h3>
|
||||||
<h3>Monitoring and Analytics</h3>
|
<p>For site monitoring, I use:</p>
|
||||||
<p>For site monitoring, I use:</p>
|
<ul>
|
||||||
<ul>
|
<li>Simple analytics for privacy-respecting visitor tracking</li>
|
||||||
<li>Simple analytics for privacy-respecting visitor tracking</li>
|
<li>Uptime monitoring</li>
|
||||||
<li>Uptime monitoring</li>
|
<li>Performance metrics collection</li>
|
||||||
<li>Performance metrics collection</li>
|
<li>Error logging and alerting</li>
|
||||||
<li>Error logging and alerting</li>
|
</ul>
|
||||||
</ul>
|
<h2>Future Improvements</h2>
|
||||||
<h2>Future Improvements</h2>
|
<p>My environment continues to evolve. Areas I'm exploring include:</p>
|
||||||
<p>My environment continues to evolve. Areas I'm exploring include:</p>
|
<ul>
|
||||||
<ul>
|
<li>Further integration between Emacs and system tools</li>
|
||||||
<li>Further integration between Emacs and system tools</li>
|
<li>More comprehensive test automation</li>
|
||||||
<li>More comprehensive test automation</li>
|
<li>Expanded use of Guix channels for package management</li>
|
||||||
<li>Expanded use of Guix channels for package management</li>
|
<li>Improved mobile development workflow</li>
|
||||||
<li>Improved mobile development workflow</li>
|
</ul>
|
||||||
</ul>
|
<h2>Conclusion</h2>
|
||||||
<h2>Conclusion</h2>
|
<p>A development environment is deeply personal, reflecting both technical needs and individual preferences. Mine has evolved through years of experimentation, learning, and refinement.</p>
|
||||||
<p>A development environment is deeply personal, reflecting both technical needs and individual preferences. Mine has evolved through years of experimentation, learning, and refinement.</p>
|
<p>The most important lesson I've learned is that tools should serve your workflow, not dictate it. Be willing to experiment, but also recognize when a tool is working well enough that further optimization yields diminishing returns.</p>
|
||||||
<p>The most important lesson I've learned is that tools should serve your workflow, not dictate it. Be willing to experiment, but also recognize when a tool is working well enough that further optimization yields diminishing returns.</p>
|
<p>I hope sharing my setup provides some inspiration for your own environment. I'd love to hear about your setup and what tools have made the biggest difference in your workflow.</p>
|
||||||
<p>I hope sharing my setup provides some inspiration for your own environment. I'd love to hear about your setup and what tools have made the biggest difference in your workflow.</p>
|
<p>What aspects of your development environment have you found most valuable? Are there tools or approaches you think I should consider? Let me know!</p>
|
||||||
<p>What aspects of your development environment have you found most valuable? Are there tools or approaches you think I should consider? Let me know!</p>
|
|
||||||
|
</article>
|
||||||
</article>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</main>
|
||||||
</main>
|
<footer class="bg-base-darker text-palenight-200 py-12 border-t border-palenight-400/20">
|
||||||
<footer class="bg-base-darker text-palenight-200 py-12 border-t border-palenight-400/20">
|
<div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
<div class="text-center">
|
||||||
<div class="text-center">
|
<p class="text-palenight-300">© 2026 Glenn Thompson. All rights reserved.</p>
|
||||||
<p class="text-palenight-300">© 2024 Glenn Thompson. All rights reserved.</p>
|
<div class="webring-text mt-6">
|
||||||
<div class="webring-text mt-6">
|
<p class="text-palenight-300">I am part of the <a href="https://systemcrafters.net" target="_blank" class="text-accent-blue hover:text-accent-cyan">System Crafters</a> webring:</p>
|
||||||
<p class="text-palenight-300">I am part of the <a href="https://systemcrafters.net" target="_blank" class="text-accent-blue hover:text-accent-cyan">System Crafters</a> webring:</p>
|
</div>
|
||||||
</div>
|
<div class="craftering mt-2 flex items-center justify-center gap-4 text-accent-blue">
|
||||||
<div class="craftering mt-2 flex items-center justify-center gap-4 text-accent-blue">
|
<a href="https://craftering.systemcrafters.net/@glenneth/previous" class="hover:text-accent-cyan">Previous</a>
|
||||||
<a href="https://craftering.systemcrafters.net/@glenneth/previous" class="hover:text-accent-cyan">Previous</a>
|
<a href="https://craftering.systemcrafters.net/@glenneth" class="hover:text-accent-cyan">Random</a>
|
||||||
<a href="https://craftering.systemcrafters.net/@glenneth" class="hover:text-accent-cyan">Random</a>
|
<a href="https://craftering.systemcrafters.net/@glenneth/next" class="hover:text-accent-cyan">Next</a>
|
||||||
<a href="https://craftering.systemcrafters.net/@glenneth/next" class="hover:text-accent-cyan">Next</a>
|
</div>
|
||||||
</div>
|
<p class="text-palenight-300 mt-2">
|
||||||
<p class="text-palenight-300 mt-2">
|
<a href="mailto:glenn@glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenn@glenneth.org</a> |
|
||||||
<a href="mailto:glenn@glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenn@glenneth.org</a> |
|
<a href="https://glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenneth.org</a>
|
||||||
<a href="https://glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenneth.org</a>
|
</p>
|
||||||
</p>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</footer>
|
||||||
</footer>
|
</body>
|
||||||
</body>
|
|
||||||
</html>
|
</html>
|
||||||
|
|
@ -1,196 +1,195 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en" class="bg-base-bg">
|
<html lang="en" class="bg-base-bg">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<meta name="description" content="">
|
<meta name="description" content="">
|
||||||
<meta property="og:title" content=""Lessons Learned: One Year with a Custom Static Site Generator"">
|
<meta property="og:title" content="Blog Post">
|
||||||
<meta property="og:description" content="">
|
<meta property="og:description" content="">
|
||||||
<meta property="og:url" content="https://glenneth.orgcontent/posts/2025-03-12-lessons-learned-custom-ssg">
|
<meta property="og:url" content="https://glenneth.orgcontent/posts/2025-03-12-lessons-learned-custom-ssg">
|
||||||
<title>"Lessons Learned: One Year with a Custom Static Site Generator" - Glenn Thompson</title>
|
<title>Blog Post - Glenn Thompson</title>
|
||||||
<link rel="alternate" type="application/rss+xml" title="Glenn Thompson's Blog" href="/feed.xml" />
|
<link rel="alternate" type="application/rss+xml" title="Glenn Thompson's Blog" href="/feed.xml" />
|
||||||
<link href="/dist/styles.css" rel="stylesheet">
|
<link href="/dist/styles.css" rel="stylesheet">
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Merriweather:wght@400;700&family=JetBrains+Mono:wght@400;700&display=swap" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Merriweather:wght@400;700&family=JetBrains+Mono:wght@400;700&display=swap" rel="stylesheet">
|
||||||
<style>
|
<style>
|
||||||
.prose-palenight {
|
.prose-palenight {
|
||||||
--tw-prose-body: #bfc7d5;
|
--tw-prose-body: #bfc7d5;
|
||||||
--tw-prose-headings: #ffd580;
|
--tw-prose-headings: #ffd580;
|
||||||
--tw-prose-links: #82aaff;
|
--tw-prose-links: #82aaff;
|
||||||
--tw-prose-code: #c792ea;
|
--tw-prose-code: #c792ea;
|
||||||
--tw-prose-pre-bg: #1b1e2b;
|
--tw-prose-pre-bg: #1b1e2b;
|
||||||
}
|
}
|
||||||
.prose h2 {
|
.prose h2 {
|
||||||
color: var(--tw-prose-headings);
|
color: var(--tw-prose-headings);
|
||||||
font-family: Merriweather, serif;
|
font-family: Merriweather, serif;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
font-size: 1.5rem;
|
font-size: 1.5rem;
|
||||||
margin-top: 2rem;
|
margin-top: 2rem;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
}
|
}
|
||||||
.prose p {
|
.prose p {
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
line-height: 1.625;
|
line-height: 1.625;
|
||||||
}
|
}
|
||||||
.prose a {
|
.prose a {
|
||||||
color: var(--tw-prose-links);
|
color: var(--tw-prose-links);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
.prose a:hover {
|
.prose a:hover {
|
||||||
color: #89ddff;
|
color: #89ddff;
|
||||||
}
|
}
|
||||||
.prose code {
|
.prose code {
|
||||||
color: var(--tw-prose-code);
|
color: var(--tw-prose-code);
|
||||||
font-family: 'JetBrains Mono', monospace;
|
font-family: 'JetBrains Mono', monospace;
|
||||||
}
|
}
|
||||||
.prose pre {
|
.prose pre {
|
||||||
background-color: var(--tw-prose-pre-bg);
|
background-color: var(--tw-prose-pre-bg);
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
}
|
}
|
||||||
.prose ul, .prose ol {
|
.prose ul, .prose ol {
|
||||||
margin-top: 0.5rem;
|
margin-top: 0.5rem;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
padding-left: 1.5rem;
|
padding-left: 1.5rem;
|
||||||
}
|
}
|
||||||
.prose ul {
|
.prose ul {
|
||||||
list-style-type: disc;
|
list-style-type: disc;
|
||||||
}
|
}
|
||||||
.prose ol {
|
.prose ol {
|
||||||
list-style-type: decimal;
|
list-style-type: decimal;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body class="bg-base-bg text-palenight-50">
|
<body class="bg-base-bg text-palenight-50">
|
||||||
<nav class="bg-base-darker/80 backdrop-blur-sm shadow-sm border-b border-palenight-400/20 mb-8">
|
<nav class="bg-base-darker/80 backdrop-blur-sm shadow-sm border-b border-palenight-400/20 mb-8">
|
||||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<div class="flex items-center justify-between h-16">
|
<div class="flex items-center justify-between h-16">
|
||||||
<a href="/" class="text-accent-yellow font-serif text-xl font-bold">Glenn Thompson</a>
|
<a href="/" class="text-accent-yellow font-serif text-xl font-bold">Glenn Thompson</a>
|
||||||
<div class="flex items-center gap-2 text-accent-yellow text-sm font-bold">
|
<div class="flex items-center gap-2 text-accent-yellow text-sm font-bold">
|
||||||
<span>[web, development, javascript, static-site, lessons]</span>
|
<span>Tech</span>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<time datetime="2025-03-13">March 13, 2025</time>
|
<time datetime="undefined">Invalid Date</time>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<span>6 min read</span>
|
<span>6 min read</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<main class="pt-24 pb-16 px-4">
|
<main class="pt-24 pb-16 px-4">
|
||||||
<div class="max-w-4xl mx-auto">
|
<div class="max-w-4xl mx-auto">
|
||||||
<div class="content text-palenight-100 space-y-6">
|
<div class="content text-palenight-100 space-y-6">
|
||||||
<header class="mb-8">
|
<header class="mb-8">
|
||||||
<h1 class="text-4xl font-serif font-bold text-accent-yellow">"Lessons Learned: One Year with a Custom Static Site Generator"</h1>
|
<h1 class="text-4xl font-serif font-bold text-accent-yellow">Blog Post</h1>
|
||||||
<div class="flex items-center gap-4 text-palenight-300 mt-4">
|
<div class="flex items-center gap-4 text-palenight-300 mt-4">
|
||||||
<time datetime="2025-03-13">2025-03-13</time>
|
<time datetime=""></time>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<span>6 min read</span>
|
<span>6 min read</span>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<span>By Glenn Thompson</span>
|
<span>By Glenn Thompson</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-wrap gap-2 mt-4">
|
</header>
|
||||||
<span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">[web</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">development</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">javascript</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">static-site</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">lessons]</span>
|
|
||||||
</div>
|
<article class="prose prose-palenight max-w-none">
|
||||||
</header>
|
<hr>
|
||||||
|
<h2>title: "Lessons Learned: One Year with a Custom Static Site Generator"<br>date: 2025-03-13<br>tags: [web, development, javascript, static-site, lessons]</h2>
|
||||||
<article class="prose prose-palenight max-w-none">
|
<p>It's been just over a year since I <a href="/content/posts/2025-01-02-from-haunt-to-custom.html">transitioned from Haunt to my own custom static site generator</a> for this website. What started as an experiment to gain more control over my publishing workflow has evolved into a valuable learning experience that has shaped how I approach web development projects.</p>
|
||||||
<p>It's been just over a year since I <a href="/content/posts/2025-01-02-from-haunt-to-custom.html">transitioned from Haunt to my own custom static site generator</a> for this website. What started as an experiment to gain more control over my publishing workflow has evolved into a valuable learning experience that has shaped how I approach web development projects.</p>
|
<p>In this post, I'll share the key lessons I've learned and insights I've gained from building and maintaining my own static site generator. While the technical details are interesting, the real value has been in the broader lessons about software development, user experience, and the balance between complexity and simplicity.</p>
|
||||||
<p>In this post, I'll share the key lessons I've learned and insights I've gained from building and maintaining my own static site generator. While the technical details are interesting, the real value has been in the broader lessons about software development, user experience, and the balance between complexity and simplicity.</p>
|
<h2>The Journey of Evolution</h2>
|
||||||
<h2>The Journey of Evolution</h2>
|
<h3>From Simple Beginnings</h3>
|
||||||
<h3>From Simple Beginnings</h3>
|
<p>When I first built my static site generator, it was remarkably simple - just the essential features needed to convert my writing into a website. No extra features, no complex configurations, just the basics.</p>
|
||||||
<p>When I first built my static site generator, it was remarkably simple - just the essential features needed to convert my writing into a website. No extra features, no complex configurations, just the basics.</p>
|
<p>Today, the system has evolved considerably, but not through grand design or elaborate planning. Instead, it grew organically based on real needs and actual usage. This organic growth taught me valuable lessons about software development.</p>
|
||||||
<p>Today, the system has evolved considerably, but not through grand design or elaborate planning. Instead, it grew organically based on real needs and actual usage. This organic growth taught me valuable lessons about software development.</p>
|
<h3>Lesson 1: Features Should Emerge from Usage</h3>
|
||||||
<h3>Lesson 1: Features Should Emerge from Usage</h3>
|
<p>Many of the features in my static site generator emerged from actual writing and publishing needs:</p>
|
||||||
<p>Many of the features in my static site generator emerged from actual writing and publishing needs:</p>
|
<ol>
|
||||||
<ol>
|
<li><p><strong>The Draft System</strong><br>When I found myself working on multiple posts simultaneously, I needed a way to keep unfinished posts separate from published content. This led to the draft system, which now helps me manage my writing workflow effectively.</p>
|
||||||
<li><p><strong>The Draft System</strong><br>When I found myself working on multiple posts simultaneously, I needed a way to keep unfinished posts separate from published content. This led to the draft system, which now helps me manage my writing workflow effectively.</p>
|
</li>
|
||||||
</li>
|
<li><p><strong>Tag Organization</strong><br>As my collection of posts grew, I needed a way to organize related content. The tag system emerged naturally from this need, rather than being built upfront based on assumptions about how I might want to organize content.</p>
|
||||||
<li><p><strong>Tag Organization</strong><br>As my collection of posts grew, I needed a way to organize related content. The tag system emerged naturally from this need, rather than being built upfront based on assumptions about how I might want to organize content.</p>
|
</li>
|
||||||
</li>
|
<li><p><strong>Content Validation</strong><br>After accidentally publishing a post with a malformed date and another with a duplicate title, I added validation checks. These weren't part of the initial design but came from real-world publishing mishaps.</p>
|
||||||
<li><p><strong>Content Validation</strong><br>After accidentally publishing a post with a malformed date and another with a duplicate title, I added validation checks. These weren't part of the initial design but came from real-world publishing mishaps.</p>
|
</li>
|
||||||
</li>
|
</ol>
|
||||||
</ol>
|
<h3>Lesson 2: Simplicity Drives Performance</h3>
|
||||||
<h3>Lesson 2: Simplicity Drives Performance</h3>
|
<p>One of the most surprising lessons was how simplicity led to better performance:</p>
|
||||||
<p>One of the most surprising lessons was how simplicity led to better performance:</p>
|
<ol>
|
||||||
<ol>
|
<li><p><strong>Static HTML Generation</strong><br>By generating plain HTML files, the site loads quickly without any client-side processing. There's no JavaScript framework, no hydration, and no complex build process - just simple, fast HTML.</p>
|
||||||
<li><p><strong>Static HTML Generation</strong><br>By generating plain HTML files, the site loads quickly without any client-side processing. There's no JavaScript framework, no hydration, and no complex build process - just simple, fast HTML.</p>
|
</li>
|
||||||
</li>
|
<li><p><strong>Incremental Builds</strong><br>The build system only processes files that have changed. This means that even with hundreds of posts, updates are nearly instantaneous because only the necessary files are rebuilt.</p>
|
||||||
<li><p><strong>Incremental Builds</strong><br>The build system only processes files that have changed. This means that even with hundreds of posts, updates are nearly instantaneous because only the necessary files are rebuilt.</p>
|
</li>
|
||||||
</li>
|
<li><p><strong>Minimal JavaScript</strong><br>By keeping JavaScript to a minimum and focusing on progressive enhancement, the site remains fast and accessible, even on slower connections.</p>
|
||||||
<li><p><strong>Minimal JavaScript</strong><br>By keeping JavaScript to a minimum and focusing on progressive enhancement, the site remains fast and accessible, even on slower connections.</p>
|
</li>
|
||||||
</li>
|
</ol>
|
||||||
</ol>
|
<h3>Lesson 3: Developer Experience Matters</h3>
|
||||||
<h3>Lesson 3: Developer Experience Matters</h3>
|
<p>A good developer experience has proven crucial for maintaining motivation to write and publish:</p>
|
||||||
<p>A good developer experience has proven crucial for maintaining motivation to write and publish:</p>
|
<ol>
|
||||||
<ol>
|
<li><p><strong>Smart Port Management</strong><br>After encountering port conflicts with other services, I added automatic port detection and fallback. The system now checks if a port is in use and automatically finds the next available one, eliminating the frustration of manual port configuration.</p>
|
||||||
<li><p><strong>Smart Port Management</strong><br>After encountering port conflicts with other services, I added automatic port detection and fallback. The system now checks if a port is in use and automatically finds the next available one, eliminating the frustration of manual port configuration.</p>
|
</li>
|
||||||
</li>
|
<li><p><strong>Clear Error Messages</strong><br>When something goes wrong (like a failed CSS build or HTML conversion), the system provides clear, actionable error messages. This immediate feedback helps quickly identify and fix issues during the development process.</p>
|
||||||
<li><p><strong>Clear Error Messages</strong><br>When something goes wrong (like a failed CSS build or HTML conversion), the system provides clear, actionable error messages. This immediate feedback helps quickly identify and fix issues during the development process.</p>
|
</li>
|
||||||
</li>
|
<li><p><strong>Automated Validation</strong><br>The build system validates the environment before starting, checking for required directories and dependencies. These checks catch common setup issues early, making the development process smoother.</p>
|
||||||
<li><p><strong>Automated Validation</strong><br>The build system validates the environment before starting, checking for required directories and dependencies. These checks catch common setup issues early, making the development process smoother.</p>
|
</li>
|
||||||
</li>
|
</ol>
|
||||||
</ol>
|
<h3>Lesson 4: Content Drives Development</h3>
|
||||||
<h3>Lesson 4: Content Drives Development</h3>
|
<p>Perhaps the most important lesson has been letting content needs drive development:</p>
|
||||||
<p>Perhaps the most important lesson has been letting content needs drive development:</p>
|
<ol>
|
||||||
<ol>
|
<li><p><strong>Markdown Features</strong><br>I only added support for additional Markdown features (like tables and task lists) when I actually needed them in my writing. This prevented feature bloat and kept the system focused.</p>
|
||||||
<li><p><strong>Markdown Features</strong><br>I only added support for additional Markdown features (like tables and task lists) when I actually needed them in my writing. This prevented feature bloat and kept the system focused.</p>
|
</li>
|
||||||
</li>
|
<li><p><strong>RSS Feed</strong><br>The RSS feed wasn't part of the initial design but was added when the content volume grew enough to warrant it. This is a pattern I've seen repeatedly - features are most valuable when they solve real, existing needs.</p>
|
||||||
<li><p><strong>RSS Feed</strong><br>The RSS feed wasn't part of the initial design but was added when the content volume grew enough to warrant it. This is a pattern I've seen repeatedly - features are most valuable when they solve real, existing needs.</p>
|
</li>
|
||||||
</li>
|
<li><p><strong>Summary Generation</strong><br>The way post summaries are generated has evolved based on the actual content I write. Initially, it was a simple character count, but it now intelligently extracts meaningful previews based on content structure.</p>
|
||||||
<li><p><strong>Summary Generation</strong><br>The way post summaries are generated has evolved based on the actual content I write. Initially, it was a simple character count, but it now intelligently extracts meaningful previews based on content structure.</p>
|
</li>
|
||||||
</li>
|
</ol>
|
||||||
</ol>
|
<h2>Looking Forward</h2>
|
||||||
<h2>Looking Forward</h2>
|
<p>This project has taught me that the best software often evolves gradually in response to real needs rather than being built all at once from a grand design. It's a lesson that applies well beyond static site generators - it's about building software that serves actual needs rather than imagined ones.</p>
|
||||||
<p>This project has taught me that the best software often evolves gradually in response to real needs rather than being built all at once from a grand design. It's a lesson that applies well beyond static site generators - it's about building software that serves actual needs rather than imagined ones.</p>
|
<p>Just today, while writing this post, I encountered and solved several development workflow issues. Instead of being frustrated by these challenges, I saw them as opportunities to improve the system. The resulting changes - like automatic port detection and better error handling - weren't part of any grand plan. They emerged naturally from real usage and made the system better in practical, meaningful ways.</p>
|
||||||
<p>Just today, while writing this post, I encountered and solved several development workflow issues. Instead of being frustrated by these challenges, I saw them as opportunities to improve the system. The resulting changes - like automatic port detection and better error handling - weren't part of any grand plan. They emerged naturally from real usage and made the system better in practical, meaningful ways.</p>
|
<p>The system isn't perfect, and it probably never will be. But it's continuously improving in ways that matter for my writing and publishing workflow. That, I've learned, is far more valuable than technical perfection.</p>
|
||||||
<p>The system isn't perfect, and it probably never will be. But it's continuously improving in ways that matter for my writing and publishing workflow. That, I've learned, is far more valuable than technical perfection.</p>
|
<p>If you're considering building your own tools, remember:</p>
|
||||||
<p>If you're considering building your own tools, remember:</p>
|
<ol>
|
||||||
<ol>
|
<li>Start simple and let features emerge from actual usage</li>
|
||||||
<li>Start simple and let features emerge from actual usage</li>
|
<li>Focus on the experience - both for users and developers</li>
|
||||||
<li>Focus on the experience - both for users and developers</li>
|
<li>Let real needs guide development</li>
|
||||||
<li>Let real needs guide development</li>
|
<li>Embrace incremental improvements</li>
|
||||||
<li>Embrace incremental improvements</li>
|
<li>Value simplicity - it often leads to better performance and maintainability</li>
|
||||||
<li>Value simplicity - it often leads to better performance and maintainability</li>
|
<li>Use real-world problems as opportunities for improvement</li>
|
||||||
<li>Use real-world problems as opportunities for improvement</li>
|
</ol>
|
||||||
</ol>
|
<p>These lessons have influenced not just how I approach this project, but how I think about software development in general. Sometimes, the best insights come from the simplest projects - and often, they come right in the middle of writing about them.</p>
|
||||||
<p>These lessons have influenced not just how I approach this project, but how I think about software development in general. Sometimes, the best insights come from the simplest projects - and often, they come right in the middle of writing about them.</p>
|
<h2>Looking Back and Forward</h2>
|
||||||
<h2>Looking Back and Forward</h2>
|
<p>Reflecting on this journey, the most valuable insight has been understanding that great software evolves naturally from real needs. Every feature in my static site generator—from the draft system to the validation checks—emerged from actual usage rather than upfront planning.</p>
|
||||||
<p>Reflecting on this journey, the most valuable insight has been understanding that great software evolves naturally from real needs. Every feature in my static site generator—from the draft system to the validation checks—emerged from actual usage rather than upfront planning.</p>
|
<p>This experience has fundamentally changed how I approach software development. Instead of trying to build the perfect system from the start, I've learned to:</p>
|
||||||
<p>This experience has fundamentally changed how I approach software development. Instead of trying to build the perfect system from the start, I've learned to:</p>
|
<ol>
|
||||||
<ol>
|
<li>Start with the simplest solution that works</li>
|
||||||
<li>Start with the simplest solution that works</li>
|
<li>Let real usage guide feature development</li>
|
||||||
<li>Let real usage guide feature development</li>
|
<li>Focus on maintainability over complexity</li>
|
||||||
<li>Focus on maintainability over complexity</li>
|
<li>Prioritize the developer experience</li>
|
||||||
<li>Prioritize the developer experience</li>
|
<li>Keep performance in mind at every step</li>
|
||||||
<li>Keep performance in mind at every step</li>
|
</ol>
|
||||||
</ol>
|
<p>These principles have not only made my static site generator better but have also influenced how I approach every new project. Sometimes the best insights come from the simplest projects, and often they come right in the middle of writing about them.</p>
|
||||||
<p>These principles have not only made my static site generator better but have also influenced how I approach every new project. Sometimes the best insights come from the simplest projects, and often they come right in the middle of writing about them.</p>
|
|
||||||
|
</article>
|
||||||
</article>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</main>
|
||||||
</main>
|
<footer class="bg-base-darker text-palenight-200 py-12 border-t border-palenight-400/20">
|
||||||
<footer class="bg-base-darker text-palenight-200 py-12 border-t border-palenight-400/20">
|
<div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
<div class="text-center">
|
||||||
<div class="text-center">
|
<p class="text-palenight-300">© 2026 Glenn Thompson. All rights reserved.</p>
|
||||||
<p class="text-palenight-300">© 2024 Glenn Thompson. All rights reserved.</p>
|
<div class="webring-text mt-6">
|
||||||
<div class="webring-text mt-6">
|
<p class="text-palenight-300">I am part of the <a href="https://systemcrafters.net" target="_blank" class="text-accent-blue hover:text-accent-cyan">System Crafters</a> webring:</p>
|
||||||
<p class="text-palenight-300">I am part of the <a href="https://systemcrafters.net" target="_blank" class="text-accent-blue hover:text-accent-cyan">System Crafters</a> webring:</p>
|
</div>
|
||||||
</div>
|
<div class="craftering mt-2 flex items-center justify-center gap-4 text-accent-blue">
|
||||||
<div class="craftering mt-2 flex items-center justify-center gap-4 text-accent-blue">
|
<a href="https://craftering.systemcrafters.net/@glenneth/previous" class="hover:text-accent-cyan">Previous</a>
|
||||||
<a href="https://craftering.systemcrafters.net/@glenneth/previous" class="hover:text-accent-cyan">Previous</a>
|
<a href="https://craftering.systemcrafters.net/@glenneth" class="hover:text-accent-cyan">Random</a>
|
||||||
<a href="https://craftering.systemcrafters.net/@glenneth" class="hover:text-accent-cyan">Random</a>
|
<a href="https://craftering.systemcrafters.net/@glenneth/next" class="hover:text-accent-cyan">Next</a>
|
||||||
<a href="https://craftering.systemcrafters.net/@glenneth/next" class="hover:text-accent-cyan">Next</a>
|
</div>
|
||||||
</div>
|
<p class="text-palenight-300 mt-2">
|
||||||
<p class="text-palenight-300 mt-2">
|
<a href="mailto:glenn@glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenn@glenneth.org</a> |
|
||||||
<a href="mailto:glenn@glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenn@glenneth.org</a> |
|
<a href="https://glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenneth.org</a>
|
||||||
<a href="https://glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenneth.org</a>
|
</p>
|
||||||
</p>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</footer>
|
||||||
</footer>
|
</body>
|
||||||
</body>
|
|
||||||
</html>
|
</html>
|
||||||
|
|
@ -126,9 +126,9 @@
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
<footer class="bg-base-darker text-palenight-200 py-12 border-t border-palenight-400/20">
|
<footer class="bg-base-darker text-palenight-200 py-12 border-t border-palenight-400/20">
|
||||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
<div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
<p class="text-palenight-300">© 2024 Glenn Thompson. All rights reserved.</p>
|
<p class="text-palenight-300">© 2026 Glenn Thompson. All rights reserved.</p>
|
||||||
<div class="webring-text mt-6">
|
<div class="webring-text mt-6">
|
||||||
<p class="text-palenight-300">I am part of the <a href="https://systemcrafters.net" target="_blank" class="text-accent-blue hover:text-accent-cyan">System Crafters</a> webring:</p>
|
<p class="text-palenight-300">I am part of the <a href="https://systemcrafters.net" target="_blank" class="text-accent-blue hover:text-accent-cyan">System Crafters</a> webring:</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -251,9 +251,9 @@
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
<footer class="bg-base-darker text-palenight-200 py-12 border-t border-palenight-400/20">
|
<footer class="bg-base-darker text-palenight-200 py-12 border-t border-palenight-400/20">
|
||||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
<div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
<p class="text-palenight-300">© 2024 Glenn Thompson. All rights reserved.</p>
|
<p class="text-palenight-300">© 2026 Glenn Thompson. All rights reserved.</p>
|
||||||
<div class="webring-text mt-6">
|
<div class="webring-text mt-6">
|
||||||
<p class="text-palenight-300">I am part of the <a href="https://systemcrafters.net" target="_blank" class="text-accent-blue hover:text-accent-cyan">System Crafters</a> webring:</p>
|
<p class="text-palenight-300">I am part of the <a href="https://systemcrafters.net" target="_blank" class="text-accent-blue hover:text-accent-cyan">System Crafters</a> webring:</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,144 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en" class="bg-base-bg">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<meta name="description" content=""After over a year of conversations with Fade on IRC, I'm excited to be contributing to asteroid.radio - a broadcasting station for asteroid music, designed to help you get into that deep workflow."">
|
||||||
|
<meta property="og:title" content=""Contributing to asteroid.radio: Broadcasting Asteroid Music for Deep Work"">
|
||||||
|
<meta property="og:description" content=""After over a year of conversations with Fade on IRC, I'm excited to be contributing to asteroid.radio - a broadcasting station for asteroid music, designed to help you get into that deep workflow."">
|
||||||
|
<meta property="og:url" content="https://glenneth.orgcontent/posts/2026-01-12-asteroid-radio">
|
||||||
|
<title>"Contributing to asteroid.radio: Broadcasting Asteroid Music for Deep Work" - Glenn Thompson</title>
|
||||||
|
<link rel="alternate" type="application/rss+xml" title="Glenn Thompson's Blog" href="/feed.xml" />
|
||||||
|
<link href="/dist/styles.css" rel="stylesheet">
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Merriweather:wght@400;700&family=JetBrains+Mono:wght@400;700&display=swap" rel="stylesheet">
|
||||||
|
<style>
|
||||||
|
.prose-palenight {
|
||||||
|
--tw-prose-body: #bfc7d5;
|
||||||
|
--tw-prose-headings: #ffd580;
|
||||||
|
--tw-prose-links: #82aaff;
|
||||||
|
--tw-prose-code: #c792ea;
|
||||||
|
--tw-prose-pre-bg: #1b1e2b;
|
||||||
|
}
|
||||||
|
.prose h2 {
|
||||||
|
color: var(--tw-prose-headings);
|
||||||
|
font-family: Merriweather, serif;
|
||||||
|
font-weight: 700;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
margin-top: 2rem;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
.prose p {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
line-height: 1.625;
|
||||||
|
}
|
||||||
|
.prose a {
|
||||||
|
color: var(--tw-prose-links);
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
.prose a:hover {
|
||||||
|
color: #89ddff;
|
||||||
|
}
|
||||||
|
.prose code {
|
||||||
|
color: var(--tw-prose-code);
|
||||||
|
font-family: 'JetBrains Mono', monospace;
|
||||||
|
}
|
||||||
|
.prose pre {
|
||||||
|
background-color: var(--tw-prose-pre-bg);
|
||||||
|
padding: 1rem;
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
overflow-x: auto;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
.prose ul, .prose ol {
|
||||||
|
margin-top: 0.5rem;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
padding-left: 1.5rem;
|
||||||
|
}
|
||||||
|
.prose ul {
|
||||||
|
list-style-type: disc;
|
||||||
|
}
|
||||||
|
.prose ol {
|
||||||
|
list-style-type: decimal;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body class="bg-base-bg text-palenight-50">
|
||||||
|
<nav class="bg-base-darker/80 backdrop-blur-sm shadow-sm border-b border-palenight-400/20 mb-8">
|
||||||
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
|
<div class="flex items-center justify-between h-16">
|
||||||
|
<a href="/" class="text-accent-yellow font-serif text-xl font-bold">Glenn Thompson</a>
|
||||||
|
<div class="flex items-center gap-2 text-accent-yellow text-sm font-bold">
|
||||||
|
<span>[community, radio, open-source, irc, music]</span>
|
||||||
|
<span>•</span>
|
||||||
|
<time datetime="2026-01-12">January 12, 2026</time>
|
||||||
|
<span>•</span>
|
||||||
|
<span>3 min read</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<main class="pt-24 pb-16 px-4">
|
||||||
|
<div class="max-w-4xl mx-auto">
|
||||||
|
<div class="content text-palenight-100 space-y-6">
|
||||||
|
<header class="mb-8">
|
||||||
|
<h1 class="text-4xl font-serif font-bold text-accent-yellow">"Contributing to asteroid.radio: Broadcasting Asteroid Music for Deep Work"</h1>
|
||||||
|
<div class="flex items-center gap-4 text-palenight-300 mt-4">
|
||||||
|
<time datetime="2026-01-12">2026-01-12</time>
|
||||||
|
<span>•</span>
|
||||||
|
<span>3 min read</span>
|
||||||
|
<span>•</span>
|
||||||
|
<span>By Glenn Thompson</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex flex-wrap gap-2 mt-4">
|
||||||
|
<span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">[community</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">radio</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">open-source</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">irc</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">music]</span>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<article class="prose prose-palenight max-w-none">
|
||||||
|
<h2>Introduction</h2>
|
||||||
|
<p>Sometimes the best projects emerge from casual conversations that span months or even years. That's exactly how my involvement with <a href="https://asteroid.radio">asteroid.radio</a> came about - through countless discussions with Fade on IRC, stretching back over a couple of years.</p>
|
||||||
|
<p>Fade is the development lead on asteroid.radio, and our conversations about the project have been a recurring thread in our IRC interactions. What started as occasional mentions evolved into deeper technical discussions, and eventually into an opportunity to contribute. I did bend Fades' arm a little bit to get us started, but I hope he appreciates the push.</p>
|
||||||
|
<h2>What is asteroid.radio?</h2>
|
||||||
|
<p><a href="https://asteroid.radio">asteroid.radio</a> is a broadcasting station dedicated to what Fade has dubbed "asteroid music" - that particular genre of sound that helps you slip into a deep workflow when hacking or deeply engaged at the computer. The moment Fade coined the term, I knew exactly what he was referencing. It's that music that fades into the background while simultaneously sharpening your focus.</p>
|
||||||
|
<p>We're attempting to build a community around this concept - a space for people who understand that the right soundtrack can transform a coding session from distracted fumbling into hours of productive flow. The project is open source, and you can find the code at <a href="https://github.com/fade/asteroid">github.com/fade/asteroid</a>.</p>
|
||||||
|
<h2>The IRC Connection</h2>
|
||||||
|
<p>My involvement with asteroid.radio is deeply rooted in IRC culture. Fade and easilok are both active in the IRC community, and it's through these channels that the project has grown and evolved.</p>
|
||||||
|
<p>There's something special about IRC as a medium for project collaboration. The asynchronous nature of conversations allows ideas to percolate over time. Fade and I would discuss asteroid.radio concepts, then return to them weeks or months later with fresh perspectives. This slow-burn approach to project development has its own rhythm - one that I've come to appreciate.</p>
|
||||||
|
<h2>Getting Involved</h2>
|
||||||
|
<p>After over a couple of years of these on-and-off conversations, I'm now actively contributing to the project. Working with Fade as the dev lead has been a great experience - there's a "clear" vision for what asteroid.radio should become (don't mention Autechre), while still leaving room for contributors to bring their own ideas and expertise.</p>
|
||||||
|
<p>The project represents exactly the kind of work I find most rewarding: community-focused, technically interesting, and aligned with the values of open source that I care about.</p>
|
||||||
|
<h2>Looking Forward</h2>
|
||||||
|
<p>I'm excited to see where <a href="https://asteroid.radio">asteroid.radio</a> goes from here. Projects like this demonstrate what's possible when communities come together to build something meaningful.</p>
|
||||||
|
<p>If you're interested in asteroid music, deep work soundtracks, or just want to see what we're building, tune in to <a href="https://asteroid.radio">asteroid.radio</a> and check out the <a href="https://github.com/fade/asteroid">source code on GitHub</a>. And if you're on IRC, come say hello - you might find yourself drawn into a years-long conversation that leads somewhere unexpected.</p>
|
||||||
|
<h2>Community Matters</h2>
|
||||||
|
<p>This experience has reinforced something I've come to believe strongly: the best open source contributions often come from genuine community connections. Whether it's the <a href="https://systemcrafters.net/">System Crafters</a> community, the <a href="https://craftering.systemcrafters.net/">Craftering webring</a>, or the IRC channels where projects like <a href="https://asteroid.radio">asteroid.radio</a> take shape, these spaces matter.</p>
|
||||||
|
<p>Thanks to Fade for the leadership on this project, to easilok for being part of the community, and to everyone who makes IRC such a valuable space for collaboration.</p>
|
||||||
|
<p>Happy Hacking!</p>
|
||||||
|
|
||||||
|
</article>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
<footer class="bg-base-darker text-palenight-200 py-12 border-t border-palenight-400/20">
|
||||||
|
<div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
|
<div class="text-center">
|
||||||
|
<p class="text-palenight-300">© 2026 Glenn Thompson. All rights reserved.</p>
|
||||||
|
<div class="webring-text mt-6">
|
||||||
|
<p class="text-palenight-300">I am part of the <a href="https://systemcrafters.net" target="_blank" class="text-accent-blue hover:text-accent-cyan">System Crafters</a> webring:</p>
|
||||||
|
</div>
|
||||||
|
<div class="craftering mt-2 flex items-center justify-center gap-4 text-accent-blue">
|
||||||
|
<a href="https://craftering.systemcrafters.net/@glenneth/previous" class="hover:text-accent-cyan">Previous</a>
|
||||||
|
<a href="https://craftering.systemcrafters.net/@glenneth" class="hover:text-accent-cyan">Random</a>
|
||||||
|
<a href="https://craftering.systemcrafters.net/@glenneth/next" class="hover:text-accent-cyan">Next</a>
|
||||||
|
</div>
|
||||||
|
<p class="text-palenight-300 mt-2">
|
||||||
|
<a href="mailto:glenn@glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenn@glenneth.org</a> |
|
||||||
|
<a href="https://glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenneth.org</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
---
|
||||||
|
title: "Contributing to asteroid.radio: Broadcasting Asteroid Music for Deep Work"
|
||||||
|
date: 2026-01-12
|
||||||
|
tags: [community, radio, open-source, irc, music]
|
||||||
|
description: "After over a year of conversations with Fade on IRC, I'm excited to be contributing to asteroid.radio - a broadcasting station for asteroid music, designed to help you get into that deep workflow."
|
||||||
|
---
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
|
||||||
|
Sometimes the best projects emerge from casual conversations that span months or even years. That's exactly how my involvement with [asteroid.radio](https://asteroid.radio) came about - through countless discussions with Fade on IRC, stretching back over a couple of years.
|
||||||
|
|
||||||
|
Fade is the development lead on asteroid.radio, and our conversations about the project have been a recurring thread in our IRC interactions. What started as occasional mentions evolved into deeper technical discussions, and eventually into an opportunity to contribute. I did bend Fades' arm a little bit to get us started, but I hope he appreciates the push.
|
||||||
|
|
||||||
|
## What is asteroid.radio?
|
||||||
|
|
||||||
|
[asteroid.radio](https://asteroid.radio) is a broadcasting station dedicated to what Fade has dubbed "asteroid music" - that particular genre of sound that helps you slip into a deep workflow when hacking or deeply engaged at the computer. The moment Fade coined the term, I knew exactly what he was referencing. It's that music that fades into the background while simultaneously sharpening your focus.
|
||||||
|
|
||||||
|
We're attempting to build a community around this concept - a space for people who understand that the right soundtrack can transform a coding session from distracted fumbling into hours of productive flow. The project is open source, and you can find the code at [github.com/fade/asteroid](https://github.com/fade/asteroid).
|
||||||
|
|
||||||
|
## The IRC Connection
|
||||||
|
|
||||||
|
My involvement with asteroid.radio is deeply rooted in IRC culture. Fade and easilok are both active in the IRC community, and it's through these channels that the project has grown and evolved.
|
||||||
|
|
||||||
|
There's something special about IRC as a medium for project collaboration. The asynchronous nature of conversations allows ideas to percolate over time. Fade and I would discuss asteroid.radio concepts, then return to them weeks or months later with fresh perspectives. This slow-burn approach to project development has its own rhythm - one that I've come to appreciate.
|
||||||
|
|
||||||
|
## Getting Involved
|
||||||
|
|
||||||
|
After over a couple of years of these on-and-off conversations, I'm now actively contributing to the project. Working with Fade as the dev lead has been a great experience - there's a "clear" vision for what asteroid.radio should become (don't mention Autechre), while still leaving room for contributors to bring their own ideas and expertise.
|
||||||
|
|
||||||
|
The project represents exactly the kind of work I find most rewarding: community-focused, technically interesting, and aligned with the values of open source that I care about.
|
||||||
|
|
||||||
|
## Looking Forward
|
||||||
|
|
||||||
|
I'm excited to see where [asteroid.radio](https://asteroid.radio) goes from here. Projects like this demonstrate what's possible when communities come together to build something meaningful.
|
||||||
|
|
||||||
|
If you're interested in asteroid music, deep work soundtracks, or just want to see what we're building, tune in to [asteroid.radio](https://asteroid.radio) and check out the [source code on GitHub](https://github.com/fade/asteroid). And if you're on IRC, come say hello - you might find yourself drawn into a years-long conversation that leads somewhere unexpected.
|
||||||
|
|
||||||
|
## Community Matters
|
||||||
|
|
||||||
|
This experience has reinforced something I've come to believe strongly: the best open source contributions often come from genuine community connections. Whether it's the [System Crafters](https://systemcrafters.net/) community, the [Craftering webring](https://craftering.systemcrafters.net/), or the IRC channels where projects like [asteroid.radio](https://asteroid.radio) take shape, these spaces matter.
|
||||||
|
|
||||||
|
Thanks to Fade for the leadership on this project, to easilok for being part of the community, and to everyone who makes IRC such a valuable space for collaboration.
|
||||||
|
|
||||||
|
Happy Hacking!
|
||||||
|
|
@ -1,147 +1,146 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en" class="bg-base-bg">
|
<html lang="en" class="bg-base-bg">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<meta name="description" content="">
|
<meta name="description" content="">
|
||||||
<meta property="og:title" content=""Aesthetic Meets Ergonomics: My Deep Dive into the Glove80 Keyboard"">
|
<meta property="og:title" content="Blog Post">
|
||||||
<meta property="og:description" content="">
|
<meta property="og:description" content="">
|
||||||
<meta property="og:url" content="https://glenneth.orgcontent/posts/2024-04-08-glove80-review">
|
<meta property="og:url" content="https://glenneth.orgcontent/posts/2024-04-08-glove80-review">
|
||||||
<title>"Aesthetic Meets Ergonomics: My Deep Dive into the Glove80 Keyboard" - Glenn Thompson</title>
|
<title>Blog Post - Glenn Thompson</title>
|
||||||
<link rel="alternate" type="application/rss+xml" title="Glenn Thompson's Blog" href="/feed.xml" />
|
<link rel="alternate" type="application/rss+xml" title="Glenn Thompson's Blog" href="/feed.xml" />
|
||||||
<link href="../../dist/styles.css" rel="stylesheet">
|
<link href="/dist/styles.css" rel="stylesheet">
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Merriweather:wght@400;700&family=JetBrains+Mono:wght@400;700&display=swap" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Merriweather:wght@400;700&family=JetBrains+Mono:wght@400;700&display=swap" rel="stylesheet">
|
||||||
<style>
|
<style>
|
||||||
.prose-palenight {
|
.prose-palenight {
|
||||||
--tw-prose-body: #bfc7d5;
|
--tw-prose-body: #bfc7d5;
|
||||||
--tw-prose-headings: #ffd580;
|
--tw-prose-headings: #ffd580;
|
||||||
--tw-prose-links: #82aaff;
|
--tw-prose-links: #82aaff;
|
||||||
--tw-prose-code: #c792ea;
|
--tw-prose-code: #c792ea;
|
||||||
--tw-prose-pre-bg: #1b1e2b;
|
--tw-prose-pre-bg: #1b1e2b;
|
||||||
}
|
}
|
||||||
.prose h2 {
|
.prose h2 {
|
||||||
color: var(--tw-prose-headings);
|
color: var(--tw-prose-headings);
|
||||||
font-family: Merriweather, serif;
|
font-family: Merriweather, serif;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
font-size: 1.5rem;
|
font-size: 1.5rem;
|
||||||
margin-top: 2rem;
|
margin-top: 2rem;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
}
|
}
|
||||||
.prose p {
|
.prose p {
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
line-height: 1.625;
|
line-height: 1.625;
|
||||||
}
|
}
|
||||||
.prose a {
|
.prose a {
|
||||||
color: var(--tw-prose-links);
|
color: var(--tw-prose-links);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
.prose a:hover {
|
.prose a:hover {
|
||||||
color: #89ddff;
|
color: #89ddff;
|
||||||
}
|
}
|
||||||
.prose code {
|
.prose code {
|
||||||
color: var(--tw-prose-code);
|
color: var(--tw-prose-code);
|
||||||
font-family: 'JetBrains Mono', monospace;
|
font-family: 'JetBrains Mono', monospace;
|
||||||
}
|
}
|
||||||
.prose pre {
|
.prose pre {
|
||||||
background-color: var(--tw-prose-pre-bg);
|
background-color: var(--tw-prose-pre-bg);
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
}
|
}
|
||||||
.prose ul, .prose ol {
|
.prose ul, .prose ol {
|
||||||
margin-top: 0.5rem;
|
margin-top: 0.5rem;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
padding-left: 1.5rem;
|
padding-left: 1.5rem;
|
||||||
}
|
}
|
||||||
.prose ul {
|
.prose ul {
|
||||||
list-style-type: disc;
|
list-style-type: disc;
|
||||||
}
|
}
|
||||||
.prose ol {
|
.prose ol {
|
||||||
list-style-type: decimal;
|
list-style-type: decimal;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body class="bg-base-bg text-palenight-50">
|
<body class="bg-base-bg text-palenight-50">
|
||||||
<nav class="bg-base-darker/80 backdrop-blur-sm shadow-sm border-b border-palenight-400/20 mb-8">
|
<nav class="bg-base-darker/80 backdrop-blur-sm shadow-sm border-b border-palenight-400/20 mb-8">
|
||||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<div class="flex items-center justify-between h-16">
|
<div class="flex items-center justify-between h-16">
|
||||||
<a href="/" class="text-accent-yellow font-serif text-xl font-bold">Glenn Thompson</a>
|
<a href="/" class="text-accent-yellow font-serif text-xl font-bold">Glenn Thompson</a>
|
||||||
<div class="flex items-center gap-2 text-accent-yellow text-sm font-bold">
|
<div class="flex items-center gap-2 text-accent-yellow text-sm font-bold">
|
||||||
<span>["personal", "tech", "keyboards", "glove80"]</span>
|
<span>Tech</span>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<time datetime=""2024-04-08 16:50"">Invalid Date</time>
|
<time datetime="undefined">Invalid Date</time>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<span>5 min read</span>
|
<span>5 min read</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<main class="pt-24 pb-16 px-4">
|
<main class="pt-24 pb-16 px-4">
|
||||||
<div class="max-w-4xl mx-auto">
|
<div class="max-w-4xl mx-auto">
|
||||||
<div class="content text-palenight-100 space-y-6">
|
<div class="content text-palenight-100 space-y-6">
|
||||||
<header class="mb-8">
|
<header class="mb-8">
|
||||||
<h1 class="text-4xl font-serif font-bold text-accent-yellow">"Aesthetic Meets Ergonomics: My Deep Dive into the Glove80 Keyboard"</h1>
|
<h1 class="text-4xl font-serif font-bold text-accent-yellow">Blog Post</h1>
|
||||||
<div class="flex items-center gap-4 text-palenight-300 mt-4">
|
<div class="flex items-center gap-4 text-palenight-300 mt-4">
|
||||||
<time datetime=""2024-04-08 16:50"">"2024-04-08 16:50"</time>
|
<time datetime=""></time>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<span>5 min read</span>
|
<span>5 min read</span>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<span>By "Glenn Thompson"</span>
|
<span>By Glenn Thompson</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-wrap gap-2 mt-4">
|
</header>
|
||||||
<span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">["personal"</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">"tech"</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">"keyboards"</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">"glove80"]</span>
|
|
||||||
</div>
|
<article class="prose prose-palenight max-w-none">
|
||||||
</header>
|
<hr>
|
||||||
|
<h2>title: "Aesthetic Meets Ergonomics: My Deep Dive into the Glove80 Keyboard"<br>author: "Glenn Thompson"<br>date: "2024-04-08 16:50"<br>tags: ["personal", "tech", "keyboards", "glove80"]</h2>
|
||||||
<article class="prose prose-palenight max-w-none">
|
<h2>In the quest for the ultimate ergonomic keyboard, aesthetics often take a backseat to functionality. Yet, when I first laid eyes on the Glove80, I was struck by its elegant design—a refreshing departure from the utilitarian look typical of many ergonomic keyboards. Unlike the retro vibes of the Kinesis Advantage or the DIY aesthetics of most Dactyls, the Glove80 boasts a modern, sleek appearance that complements the contemporary design language of Apple, Google, and LG devices. With its clean lines and visually appealing legends, the Glove80 not only promises ergonomic comfort but does so with style, standing out amidst a sea of competitors.</h2>
|
||||||
<h2>In the quest for the ultimate ergonomic keyboard, aesthetics often take a backseat to functionality. Yet, when I first laid eyes on the Glove80, I was struck by its elegant design—a refreshing departure from the utilitarian look typical of many ergonomic keyboards. Unlike the retro vibes of the Kinesis Advantage or the DIY aesthetics of most Dactyls, the Glove80 boasts a modern, sleek appearance that complements the contemporary design language of Apple, Google, and LG devices. With its clean lines and visually appealing legends, the Glove80 not only promises ergonomic comfort but does so with style, standing out amidst a sea of competitors.</h2>
|
<p>As my career trajectory veered from being an integral member of an electrical engineering team to assuming the role of Deputy Project Manager, the nature of my daily activities underwent a significant transformation. The hands-on tasks of yesteryears were gradually replaced by a deluge of documentations—writing, reviewing, and endless typing. This shift brought with it an unwelcome companion: discomfort in my hands and wrists, a stark reminder of the ergonomic pitfalls of conventional keyboards. It was in this context that my quest for a more ergonomic typing solution began, leading me towards the world of ALICE layout keyboards, with the <a href="https://www.keychron.com/products/keychron-q10-pro-alice-layout-qmk-via-wireless-custom-mechanical-keyboard"><strong>Q10 Pro</strong> by Keychron</a> being my initial foray into this new realm.</p>
|
||||||
<p>As my career trajectory veered from being an integral member of an electrical engineering team to assuming the role of Deputy Project Manager, the nature of my daily activities underwent a significant transformation. The hands-on tasks of yesteryears were gradually replaced by a deluge of documentations—writing, reviewing, and endless typing. This shift brought with it an unwelcome companion: discomfort in my hands and wrists, a stark reminder of the ergonomic pitfalls of conventional keyboards. It was in this context that my quest for a more ergonomic typing solution began, leading me towards the world of ALICE layout keyboards, with the <a href="https://www.keychron.com/products/keychron-q10-pro-alice-layout-qmk-via-wireless-custom-mechanical-keyboard"><strong>Q10 Pro</strong> by Keychron</a> being my initial foray into this new realm.</p>
|
<p>However, the relief was partial, and the shadow of wrist strain persisted, urging me to delve deeper into the ergonomic keyboard universe. My search for a truly ergonomic solution brought me to the doorstep of the <a href="https://www.moergo.com"><strong>Glove80</strong> by MoErgo</a>. Boasting a unique split design, concave key wells, and a commitment to ergonomics that seemed almost tailor-made for my situation, the Glove80 held the promise of being the oasis I was desperately seeking in the desert of my wrist discomfort.</p>
|
||||||
<p>However, the relief was partial, and the shadow of wrist strain persisted, urging me to delve deeper into the ergonomic keyboard universe. My search for a truly ergonomic solution brought me to the doorstep of the <a href="https://www.moergo.com"><strong>Glove80</strong> by MoErgo</a>. Boasting a unique split design, concave key wells, and a commitment to ergonomics that seemed almost tailor-made for my situation, the Glove80 held the promise of being the oasis I was desperately seeking in the desert of my wrist discomfort.</p>
|
<p>This journey from an ALICE layout keyboard user to a Glove80 enthusiast was not just about finding a better typing tool; it was about embracing a healthier typing posture and redefining my interaction with computers. After a month of integrating the Glove80 into my workflow, I'm ready to share my insights and experiences. This review will explore the initial adaptation period, the impact on my wrist health, and whether the Glove80 lives up to its promise as an ergonomic game-changer.</p>
|
||||||
<p>This journey from an ALICE layout keyboard user to a Glove80 enthusiast was not just about finding a better typing tool; it was about embracing a healthier typing posture and redefining my interaction with computers. After a month of integrating the Glove80 into my workflow, I'm ready to share my insights and experiences. This review will explore the initial adaptation period, the impact on my wrist health, and whether the Glove80 lives up to its promise as an ergonomic game-changer.</p>
|
<h3>First Impressions: Feel and Experience</h3>
|
||||||
<h3>First Impressions: Feel and Experience</h3>
|
<p>Upon beginning my typing journey with the Glove80, two aspects immediately stood out. The unique choc spacing, combined with finger-specific curves for each key column, facilitated effortless access to the bottom and number rows, as well as several function keys—without the need to move my hands. This ease of reach extended to the thumb keys, thoughtfully laid out in an arc to match the natural movement of my thumbs. Additionally, the keyboard's low profile on the desk encouraged a neutral wrist position, enhancing comfort during long typing sessions. These features converged to create a typing experience that was not just comfortable but intuitively aligned with natural hand movements.</p>
|
||||||
<p>Upon beginning my typing journey with the Glove80, two aspects immediately stood out. The unique choc spacing, combined with finger-specific curves for each key column, facilitated effortless access to the bottom and number rows, as well as several function keys—without the need to move my hands. This ease of reach extended to the thumb keys, thoughtfully laid out in an arc to match the natural movement of my thumbs. Additionally, the keyboard's low profile on the desk encouraged a neutral wrist position, enhancing comfort during long typing sessions. These features converged to create a typing experience that was not just comfortable but intuitively aligned with natural hand movements.</p>
|
<h4>The Details That Matter</h4>
|
||||||
<h4>The Details That Matter</h4>
|
<h5>Ergonomics at Its Core</h5>
|
||||||
<h5>Ergonomics at Its Core</h5>
|
<p>The hallmark of the Glove80 is its ergonomics, designed to seamlessly integrate with the user's hand movements. After fine-tuning the tenting and tilting angles—made possible by the adjustable feet on each half of the keyboard—my hands naturally fell into the optimal typing position. The thoughtfully designed key layout meant that reaching for higher rows required merely straightening or curling my fingers, aided by the keyboard's choc spacing. Each column's unique height and curve catered to the different lengths of my fingers, further minimizing strain.</p>
|
||||||
<p>The hallmark of the Glove80 is its ergonomics, designed to seamlessly integrate with the user's hand movements. After fine-tuning the tenting and tilting angles—made possible by the adjustable feet on each half of the keyboard—my hands naturally fell into the optimal typing position. The thoughtfully designed key layout meant that reaching for higher rows required merely straightening or curling my fingers, aided by the keyboard's choc spacing. Each column's unique height and curve catered to the different lengths of my fingers, further minimizing strain.</p>
|
<h5>Key Innovations</h5>
|
||||||
<h5>Key Innovations</h5>
|
<p>The Glove80 introduces keycaps with a novel MCC profile, featuring raised sides and a central cylindrical channel, made from a slick POM material. This design supports the natural sliding of fingers across keys, reducing the need to lift hands while typing. The keyboard's thumb clusters are another highlight, offering six easily accessible keys per hand. This ergonomic layout ensures that most keys are within reach without stretching, a testament to the keyboard's user-centric design.</p>
|
||||||
<p>The Glove80 introduces keycaps with a novel MCC profile, featuring raised sides and a central cylindrical channel, made from a slick POM material. This design supports the natural sliding of fingers across keys, reducing the need to lift hands while typing. The keyboard's thumb clusters are another highlight, offering six easily accessible keys per hand. This ergonomic layout ensures that most keys are within reach without stretching, a testament to the keyboard's user-centric design.</p>
|
<h5>Beyond Typing: Features and Flexibility</h5>
|
||||||
<h5>Beyond Typing: Features and Flexibility</h5>
|
<ul>
|
||||||
<ul>
|
<li><strong>Tenting and Adjustability:</strong> The Glove80's customizable tenting angles, enhanced by sturdy locking nuts, ensure a tailored typing experience that can be finely adjusted to individual preferences.</li>
|
||||||
<li><strong>Tenting and Adjustability:</strong> The Glove80's customizable tenting angles, enhanced by sturdy locking nuts, ensure a tailored typing experience that can be finely adjusted to individual preferences.</li>
|
<li><strong>Comfortable Palm Rest:</strong> The integrated, detachable palm rest offers additional comfort, catering to different typing styles with ease.</li>
|
||||||
<li><strong>Comfortable Palm Rest:</strong> The integrated, detachable palm rest offers additional comfort, catering to different typing styles with ease.</li>
|
<li><strong>Switch Selection:</strong> While the standard Kailh choc switches are adequate, enthusiasts might prefer customizing their keyboard with preferred switches for an optimized typing feel. I opted for the lighter Kailh Choc V1, Red Pro Linear 35gf switches.</li>
|
||||||
<li><strong>Switch Selection:</strong> While the standard Kailh choc switches are adequate, enthusiasts might prefer customizing their keyboard with preferred switches for an optimized typing feel. I opted for the lighter Kailh Choc V1, Red Pro Linear 35gf switches.</li>
|
<li><strong>Keycaps:</strong> The high-quality POM keycaps, combined with attractive and durable legends, enhance the keyboard's tactile and visual appeal.</li>
|
||||||
<li><strong>Keycaps:</strong> The high-quality POM keycaps, combined with attractive and durable legends, enhance the keyboard's tactile and visual appeal.</li>
|
<li><strong>Tech-Savvy Features:</strong> From its easy-to-use firmware updates via a web interface to seamless Bluetooth connectivity and impressive battery life, the Glove80 is designed for a modern, wireless world.</li>
|
||||||
<li><strong>Tech-Savvy Features:</strong> From its easy-to-use firmware updates via a web interface to seamless Bluetooth connectivity and impressive battery life, the Glove80 is designed for a modern, wireless world.</li>
|
<li><strong>RGB Lighting:</strong> While currently limited in customization, the RGB LEDs offer aesthetic versatility to match any setup.</li>
|
||||||
<li><strong>RGB Lighting:</strong> While currently limited in customization, the RGB LEDs offer aesthetic versatility to match any setup.</li>
|
</ul>
|
||||||
</ul>
|
<h3>Concluding Thoughts</h3>
|
||||||
<h3>Concluding Thoughts</h3>
|
<p>The Glove80 keyboard represents a significant leap forward in ergonomic design, marrying aesthetics with unmatched comfort and functionality. Its thoughtful features—from the infinitely adjustable tenting to the innovative keycap design—set a new standard for what ergonomic keyboards can be. While there's room for improvement in switch selection and RGB customization, these are minor quibbles in an otherwise outstanding product. For those in search of ergonomic excellence without compromising on style or performance, the Glove80 is an investment worth making, promising a typing experience that's not just comfortable but truly enjoyable.</p>
|
||||||
<p>The Glove80 keyboard represents a significant leap forward in ergonomic design, marrying aesthetics with unmatched comfort and functionality. Its thoughtful features—from the infinitely adjustable tenting to the innovative keycap design—set a new standard for what ergonomic keyboards can be. While there's room for improvement in switch selection and RGB customization, these are minor quibbles in an otherwise outstanding product. For those in search of ergonomic excellence without compromising on style or performance, the Glove80 is an investment worth making, promising a typing experience that's not just comfortable but truly enjoyable.</p>
|
|
||||||
|
</article>
|
||||||
</article>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</main>
|
||||||
</main>
|
<footer class="bg-base-darker text-palenight-200 py-12 border-t border-palenight-400/20">
|
||||||
<footer class="bg-base-darker text-palenight-200 py-12 border-t border-palenight-400/20">
|
<div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
<div class="text-center">
|
||||||
<div class="text-center">
|
<p class="text-palenight-300">© 2026 Glenn Thompson. All rights reserved.</p>
|
||||||
<p class="text-palenight-300">© 2024 Glenn Thompson. All rights reserved.</p>
|
<div class="webring-text mt-6">
|
||||||
<div class="webring-text mt-6">
|
<p class="text-palenight-300">I am part of the <a href="https://systemcrafters.net" target="_blank" class="text-accent-blue hover:text-accent-cyan">System Crafters</a> webring:</p>
|
||||||
<p class="text-palenight-300">I am part of the <a href="https://systemcrafters.net" target="_blank" class="text-accent-blue hover:text-accent-cyan">System Crafters</a> webring:</p>
|
</div>
|
||||||
</div>
|
<div class="craftering mt-2 flex items-center justify-center gap-4 text-accent-blue">
|
||||||
<div class="craftering mt-2 flex items-center justify-center gap-4 text-accent-blue">
|
<a href="https://craftering.systemcrafters.net/@glenneth/previous" class="hover:text-accent-cyan">Previous</a>
|
||||||
<a href="https://craftering.systemcrafters.net/@glenneth/previous" class="hover:text-accent-cyan">Previous</a>
|
<a href="https://craftering.systemcrafters.net/@glenneth" class="hover:text-accent-cyan">Random</a>
|
||||||
<a href="https://craftering.systemcrafters.net/@glenneth" class="hover:text-accent-cyan">Random</a>
|
<a href="https://craftering.systemcrafters.net/@glenneth/next" class="hover:text-accent-cyan">Next</a>
|
||||||
<a href="https://craftering.systemcrafters.net/@glenneth/next" class="hover:text-accent-cyan">Next</a>
|
</div>
|
||||||
</div>
|
<p class="text-palenight-300 mt-2">
|
||||||
<p class="text-palenight-300 mt-2">
|
<a href="mailto:glenn@glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenn@glenneth.org</a> |
|
||||||
<a href="mailto:glenn@glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenn@glenneth.org</a> |
|
<a href="https://glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenneth.org</a>
|
||||||
<a href="https://glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenneth.org</a>
|
</p>
|
||||||
</p>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</footer>
|
||||||
</footer>
|
</body>
|
||||||
</body>
|
|
||||||
</html>
|
</html>
|
||||||
|
|
@ -1,140 +1,139 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en" class="bg-base-bg">
|
<html lang="en" class="bg-base-bg">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<meta name="description" content="">
|
<meta name="description" content="">
|
||||||
<meta property="og:title" content="A Rollercoaster Week: From Amman to Newcastle, and back again">
|
<meta property="og:title" content="Blog Post">
|
||||||
<meta property="og:description" content="">
|
<meta property="og:description" content="">
|
||||||
<meta property="og:url" content="https://glenneth.orgcontent/posts/2024-05-01-amman-newcastle-journey">
|
<meta property="og:url" content="https://glenneth.orgcontent/posts/2024-05-01-amman-newcastle-journey">
|
||||||
<title>A Rollercoaster Week: From Amman to Newcastle, and back again - Glenn Thompson</title>
|
<title>Blog Post - Glenn Thompson</title>
|
||||||
<link rel="alternate" type="application/rss+xml" title="Glenn Thompson's Blog" href="/feed.xml" />
|
<link rel="alternate" type="application/rss+xml" title="Glenn Thompson's Blog" href="/feed.xml" />
|
||||||
<link href="../../dist/styles.css" rel="stylesheet">
|
<link href="/dist/styles.css" rel="stylesheet">
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Merriweather:wght@400;700&family=JetBrains+Mono:wght@400;700&display=swap" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Merriweather:wght@400;700&family=JetBrains+Mono:wght@400;700&display=swap" rel="stylesheet">
|
||||||
<style>
|
<style>
|
||||||
.prose-palenight {
|
.prose-palenight {
|
||||||
--tw-prose-body: #bfc7d5;
|
--tw-prose-body: #bfc7d5;
|
||||||
--tw-prose-headings: #ffd580;
|
--tw-prose-headings: #ffd580;
|
||||||
--tw-prose-links: #82aaff;
|
--tw-prose-links: #82aaff;
|
||||||
--tw-prose-code: #c792ea;
|
--tw-prose-code: #c792ea;
|
||||||
--tw-prose-pre-bg: #1b1e2b;
|
--tw-prose-pre-bg: #1b1e2b;
|
||||||
}
|
}
|
||||||
.prose h2 {
|
.prose h2 {
|
||||||
color: var(--tw-prose-headings);
|
color: var(--tw-prose-headings);
|
||||||
font-family: Merriweather, serif;
|
font-family: Merriweather, serif;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
font-size: 1.5rem;
|
font-size: 1.5rem;
|
||||||
margin-top: 2rem;
|
margin-top: 2rem;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
}
|
}
|
||||||
.prose p {
|
.prose p {
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
line-height: 1.625;
|
line-height: 1.625;
|
||||||
}
|
}
|
||||||
.prose a {
|
.prose a {
|
||||||
color: var(--tw-prose-links);
|
color: var(--tw-prose-links);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
.prose a:hover {
|
.prose a:hover {
|
||||||
color: #89ddff;
|
color: #89ddff;
|
||||||
}
|
}
|
||||||
.prose code {
|
.prose code {
|
||||||
color: var(--tw-prose-code);
|
color: var(--tw-prose-code);
|
||||||
font-family: 'JetBrains Mono', monospace;
|
font-family: 'JetBrains Mono', monospace;
|
||||||
}
|
}
|
||||||
.prose pre {
|
.prose pre {
|
||||||
background-color: var(--tw-prose-pre-bg);
|
background-color: var(--tw-prose-pre-bg);
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
}
|
}
|
||||||
.prose ul, .prose ol {
|
.prose ul, .prose ol {
|
||||||
margin-top: 0.5rem;
|
margin-top: 0.5rem;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
padding-left: 1.5rem;
|
padding-left: 1.5rem;
|
||||||
}
|
}
|
||||||
.prose ul {
|
.prose ul {
|
||||||
list-style-type: disc;
|
list-style-type: disc;
|
||||||
}
|
}
|
||||||
.prose ol {
|
.prose ol {
|
||||||
list-style-type: decimal;
|
list-style-type: decimal;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body class="bg-base-bg text-palenight-50">
|
<body class="bg-base-bg text-palenight-50">
|
||||||
<nav class="bg-base-darker/80 backdrop-blur-sm shadow-sm border-b border-palenight-400/20 mb-8">
|
<nav class="bg-base-darker/80 backdrop-blur-sm shadow-sm border-b border-palenight-400/20 mb-8">
|
||||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<div class="flex items-center justify-between h-16">
|
<div class="flex items-center justify-between h-16">
|
||||||
<a href="/" class="text-accent-yellow font-serif text-xl font-bold">Glenn Thompson</a>
|
<a href="/" class="text-accent-yellow font-serif text-xl font-bold">Glenn Thompson</a>
|
||||||
<div class="flex items-center gap-2 text-accent-yellow text-sm font-bold">
|
<div class="flex items-center gap-2 text-accent-yellow text-sm font-bold">
|
||||||
<span>work, travel</span>
|
<span>Tech</span>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<time datetime="2024-05-01 17:40:58+03:00">May 1, 2024</time>
|
<time datetime="undefined">Invalid Date</time>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<span>3 min read</span>
|
<span>3 min read</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<main class="pt-24 pb-16 px-4">
|
<main class="pt-24 pb-16 px-4">
|
||||||
<div class="max-w-4xl mx-auto">
|
<div class="max-w-4xl mx-auto">
|
||||||
<div class="content text-palenight-100 space-y-6">
|
<div class="content text-palenight-100 space-y-6">
|
||||||
<header class="mb-8">
|
<header class="mb-8">
|
||||||
<h1 class="text-4xl font-serif font-bold text-accent-yellow">A Rollercoaster Week: From Amman to Newcastle, and back again</h1>
|
<h1 class="text-4xl font-serif font-bold text-accent-yellow">Blog Post</h1>
|
||||||
<div class="flex items-center gap-4 text-palenight-300 mt-4">
|
<div class="flex items-center gap-4 text-palenight-300 mt-4">
|
||||||
<time datetime="2024-05-01 17:40:58+03:00">2024-05-01 17:40:58+03:00</time>
|
<time datetime=""></time>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<span>3 min read</span>
|
<span>3 min read</span>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<span>By Glenn Thompson</span>
|
<span>By Glenn Thompson</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-wrap gap-2 mt-4">
|
</header>
|
||||||
<span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">work</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">travel</span>
|
|
||||||
</div>
|
<article class="prose prose-palenight max-w-none">
|
||||||
</header>
|
<hr>
|
||||||
|
<h2>title: A Rollercoaster Week: From Amman to Newcastle, and back again<br>author: Glenn Thompson<br>date: 2024-05-01 17:40:58+03:00<br>tags: work, travel</h2>
|
||||||
<article class="prose prose-palenight max-w-none">
|
<p>Two weeks ago was a whirlwind of events, taking me from the conforting embrace of Amman, Jordan to the vibrant streets of Newcastle, England. It was a journey filled with highs and lows, professional achievements, and personal challenges.</p>
|
||||||
<p>Two weeks ago was a whirlwind of events, taking me from the conforting embrace of Amman, Jordan to the vibrant streets of Newcastle, England. It was a journey filled with highs and lows, professional achievements, and personal challenges.</p>
|
<h2>The Journey Begins</h2>
|
||||||
<h2>The Journey Begins</h2>
|
<p>It all started on a Monday morning in Amman as I embarked on a journey to attend a Quality Control (QC) conference in Newcastle. The anticipation of presenting my work at an international forum filled me with excitement and nerves. The conference was scheduled for just one day, but the impact it had on me would last much longer.</p>
|
||||||
<p>It all started on a Monday morning in Amman as I embarked on a journey to attend a Quality Control (QC) conference in Newcastle. The anticipation of presenting my work at an international forum filled me with excitement and nerves. The conference was scheduled for just one day, but the impact it had on me would last much longer.</p>
|
<h2>A Successful Presentation</h2>
|
||||||
<h2>A Successful Presentation</h2>
|
<p>Tuesday arrived, and with it came the day of the conference. Armed with a PowerPoint presentation comprising over 130 slides, I delved into four hours of intense presenting. Despite the pressure, the conference was a resounding success. My project received positive feedback, and I felt a sense of accomplishment as I shared my work with colleagues from around the world.</p>
|
||||||
<p>Tuesday arrived, and with it came the day of the conference. Armed with a PowerPoint presentation comprising over 130 slides, I delved into four hours of intense presenting. Despite the pressure, the conference was a resounding success. My project received positive feedback, and I felt a sense of accomplishment as I shared my work with colleagues from around the world.</p>
|
<h2>The Toll of Travel</h2>
|
||||||
<h2>The Toll of Travel</h2>
|
<p>However, as I returned to Amman on Wednesday, I couldn't shake off a sense of exhaustion. Little did I know that the toll of travel would soon manifest itself in a most unexpected manner. </p>
|
||||||
<p>However, as I returned to Amman on Wednesday, I couldn't shake off a sense of exhaustion. Little did I know that the toll of travel would soon manifest itself in a most unexpected manner. </p>
|
<p>Thursday morning greeted me with heavy flu-like symptoms. It hit me like a ton of bricks. The combination of jet lag, long hours of presenting, and exposure to new environments had taken its toll on my immune system. I was bedridden, grappling with a chesty cough that seemed relentless.</p>
|
||||||
<p>Thursday morning greeted me with heavy flu-like symptoms. It hit me like a ton of bricks. The combination of jet lag, long hours of presenting, and exposure to new environments had taken its toll on my immune system. I was bedridden, grappling with a chesty cough that seemed relentless.</p>
|
<h2>The Show Must Go On</h2>
|
||||||
<h2>The Show Must Go On</h2>
|
<p>Despite my illness, there was no time for rest. The following week demanded my presence at a site meeting where I was tasked with condensing my extensive slide deck into a concise presentation of just 12 slides. The challenge was daunting, but I tackled it with determination.</p>
|
||||||
<p>Despite my illness, there was no time for rest. The following week demanded my presence at a site meeting where I was tasked with condensing my extensive slide deck into a concise presentation of just 12 slides. The challenge was daunting, but I tackled it with determination.</p>
|
<h2>Reflecting on the Journey</h2>
|
||||||
<h2>Reflecting on the Journey</h2>
|
<p>As I look back on the rollercoaster week that was, I'm struck by the juxtaposition of success and struggle. From the heights of presenting at an international conference to the lows of battling illness, it was a journey that tested my resilience and resolve.</p>
|
||||||
<p>As I look back on the rollercoaster week that was, I'm struck by the juxtaposition of success and struggle. From the heights of presenting at an international conference to the lows of battling illness, it was a journey that tested my resilience and resolve.</p>
|
<p>But through it all, one thing remains clear: adversity only serves to make us stronger. Each obstacle we overcome, whether professional or personal, contributes to our growth and development.</p>
|
||||||
<p>But through it all, one thing remains clear: adversity only serves to make us stronger. Each obstacle we overcome, whether professional or personal, contributes to our growth and development.</p>
|
<p>So here's to the rollercoaster weeks, the ones filled with ups and downs, twists and turns. For it is in those moments of challenge that we discover the true extent of our capabilities.</p>
|
||||||
<p>So here's to the rollercoaster weeks, the ones filled with ups and downs, twists and turns. For it is in those moments of challenge that we discover the true extent of our capabilities.</p>
|
<p>As I upload this blog post using Hugo, I do so with a renewed sense of gratitude for the journey and all it has taught me. Here's to embracing the ride, wherever it may take us.</p>
|
||||||
<p>As I upload this blog post using Hugo, I do so with a renewed sense of gratitude for the journey and all it has taught me. Here's to embracing the ride, wherever it may take us.</p>
|
|
||||||
|
</article>
|
||||||
</article>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</main>
|
||||||
</main>
|
<footer class="bg-base-darker text-palenight-200 py-12 border-t border-palenight-400/20">
|
||||||
<footer class="bg-base-darker text-palenight-200 py-12 border-t border-palenight-400/20">
|
<div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
<div class="text-center">
|
||||||
<div class="text-center">
|
<p class="text-palenight-300">© 2026 Glenn Thompson. All rights reserved.</p>
|
||||||
<p class="text-palenight-300">© 2024 Glenn Thompson. All rights reserved.</p>
|
<div class="webring-text mt-6">
|
||||||
<div class="webring-text mt-6">
|
<p class="text-palenight-300">I am part of the <a href="https://systemcrafters.net" target="_blank" class="text-accent-blue hover:text-accent-cyan">System Crafters</a> webring:</p>
|
||||||
<p class="text-palenight-300">I am part of the <a href="https://systemcrafters.net" target="_blank" class="text-accent-blue hover:text-accent-cyan">System Crafters</a> webring:</p>
|
</div>
|
||||||
</div>
|
<div class="craftering mt-2 flex items-center justify-center gap-4 text-accent-blue">
|
||||||
<div class="craftering mt-2 flex items-center justify-center gap-4 text-accent-blue">
|
<a href="https://craftering.systemcrafters.net/@glenneth/previous" class="hover:text-accent-cyan">Previous</a>
|
||||||
<a href="https://craftering.systemcrafters.net/@glenneth/previous" class="hover:text-accent-cyan">Previous</a>
|
<a href="https://craftering.systemcrafters.net/@glenneth" class="hover:text-accent-cyan">Random</a>
|
||||||
<a href="https://craftering.systemcrafters.net/@glenneth" class="hover:text-accent-cyan">Random</a>
|
<a href="https://craftering.systemcrafters.net/@glenneth/next" class="hover:text-accent-cyan">Next</a>
|
||||||
<a href="https://craftering.systemcrafters.net/@glenneth/next" class="hover:text-accent-cyan">Next</a>
|
</div>
|
||||||
</div>
|
<p class="text-palenight-300 mt-2">
|
||||||
<p class="text-palenight-300 mt-2">
|
<a href="mailto:glenn@glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenn@glenneth.org</a> |
|
||||||
<a href="mailto:glenn@glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenn@glenneth.org</a> |
|
<a href="https://glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenneth.org</a>
|
||||||
<a href="https://glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenneth.org</a>
|
</p>
|
||||||
</p>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</footer>
|
||||||
</footer>
|
</body>
|
||||||
</body>
|
|
||||||
</html>
|
</html>
|
||||||
|
|
@ -1,362 +1,361 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en" class="bg-base-bg">
|
<html lang="en" class="bg-base-bg">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<meta name="description" content="">
|
<meta name="description" content="">
|
||||||
<meta property="og:title" content="Transitioning from Hugo to Haunt: Embracing Scheme and GNU Guix">
|
<meta property="og:title" content="Blog Post">
|
||||||
<meta property="og:description" content="">
|
<meta property="og:description" content="">
|
||||||
<meta property="og:url" content="https://glenneth.orgcontent/posts/2024-05-15-hugo-to-haunt">
|
<meta property="og:url" content="https://glenneth.orgcontent/posts/2024-05-15-hugo-to-haunt">
|
||||||
<title>Transitioning from Hugo to Haunt: Embracing Scheme and GNU Guix - Glenn Thompson</title>
|
<title>Blog Post - Glenn Thompson</title>
|
||||||
<link rel="alternate" type="application/rss+xml" title="Glenn Thompson's Blog" href="/feed.xml" />
|
<link rel="alternate" type="application/rss+xml" title="Glenn Thompson's Blog" href="/feed.xml" />
|
||||||
<link href="../../dist/styles.css" rel="stylesheet">
|
<link href="/dist/styles.css" rel="stylesheet">
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Merriweather:wght@400;700&family=JetBrains+Mono:wght@400;700&display=swap" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Merriweather:wght@400;700&family=JetBrains+Mono:wght@400;700&display=swap" rel="stylesheet">
|
||||||
<style>
|
<style>
|
||||||
.prose-palenight {
|
.prose-palenight {
|
||||||
--tw-prose-body: #bfc7d5;
|
--tw-prose-body: #bfc7d5;
|
||||||
--tw-prose-headings: #ffd580;
|
--tw-prose-headings: #ffd580;
|
||||||
--tw-prose-links: #82aaff;
|
--tw-prose-links: #82aaff;
|
||||||
--tw-prose-code: #c792ea;
|
--tw-prose-code: #c792ea;
|
||||||
--tw-prose-pre-bg: #1b1e2b;
|
--tw-prose-pre-bg: #1b1e2b;
|
||||||
}
|
}
|
||||||
.prose h2 {
|
.prose h2 {
|
||||||
color: var(--tw-prose-headings);
|
color: var(--tw-prose-headings);
|
||||||
font-family: Merriweather, serif;
|
font-family: Merriweather, serif;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
font-size: 1.5rem;
|
font-size: 1.5rem;
|
||||||
margin-top: 2rem;
|
margin-top: 2rem;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
}
|
}
|
||||||
.prose p {
|
.prose p {
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
line-height: 1.625;
|
line-height: 1.625;
|
||||||
}
|
}
|
||||||
.prose a {
|
.prose a {
|
||||||
color: var(--tw-prose-links);
|
color: var(--tw-prose-links);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
.prose a:hover {
|
.prose a:hover {
|
||||||
color: #89ddff;
|
color: #89ddff;
|
||||||
}
|
}
|
||||||
.prose code {
|
.prose code {
|
||||||
color: var(--tw-prose-code);
|
color: var(--tw-prose-code);
|
||||||
font-family: 'JetBrains Mono', monospace;
|
font-family: 'JetBrains Mono', monospace;
|
||||||
}
|
}
|
||||||
.prose pre {
|
.prose pre {
|
||||||
background-color: var(--tw-prose-pre-bg);
|
background-color: var(--tw-prose-pre-bg);
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
}
|
}
|
||||||
.prose ul, .prose ol {
|
.prose ul, .prose ol {
|
||||||
margin-top: 0.5rem;
|
margin-top: 0.5rem;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
padding-left: 1.5rem;
|
padding-left: 1.5rem;
|
||||||
}
|
}
|
||||||
.prose ul {
|
.prose ul {
|
||||||
list-style-type: disc;
|
list-style-type: disc;
|
||||||
}
|
}
|
||||||
.prose ol {
|
.prose ol {
|
||||||
list-style-type: decimal;
|
list-style-type: decimal;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body class="bg-base-bg text-palenight-50">
|
<body class="bg-base-bg text-palenight-50">
|
||||||
<nav class="bg-base-darker/80 backdrop-blur-sm shadow-sm border-b border-palenight-400/20 mb-8">
|
<nav class="bg-base-darker/80 backdrop-blur-sm shadow-sm border-b border-palenight-400/20 mb-8">
|
||||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<div class="flex items-center justify-between h-16">
|
<div class="flex items-center justify-between h-16">
|
||||||
<a href="/" class="text-accent-yellow font-serif text-xl font-bold">Glenn Thompson</a>
|
<a href="/" class="text-accent-yellow font-serif text-xl font-bold">Glenn Thompson</a>
|
||||||
<div class="flex items-center gap-2 text-accent-yellow text-sm font-bold">
|
<div class="flex items-center gap-2 text-accent-yellow text-sm font-bold">
|
||||||
<span>personal, tech, keyboards, glove80</span>
|
<span>Tech</span>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<time datetime="2024-05-15 10:30">May 15, 2024</time>
|
<time datetime="undefined">Invalid Date</time>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<span>7 min read</span>
|
<span>7 min read</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<main class="pt-24 pb-16 px-4">
|
<main class="pt-24 pb-16 px-4">
|
||||||
<div class="max-w-4xl mx-auto">
|
<div class="max-w-4xl mx-auto">
|
||||||
<div class="content text-palenight-100 space-y-6">
|
<div class="content text-palenight-100 space-y-6">
|
||||||
<header class="mb-8">
|
<header class="mb-8">
|
||||||
<h1 class="text-4xl font-serif font-bold text-accent-yellow">Transitioning from Hugo to Haunt: Embracing Scheme and GNU Guix</h1>
|
<h1 class="text-4xl font-serif font-bold text-accent-yellow">Blog Post</h1>
|
||||||
<div class="flex items-center gap-4 text-palenight-300 mt-4">
|
<div class="flex items-center gap-4 text-palenight-300 mt-4">
|
||||||
<time datetime="2024-05-15 10:30">2024-05-15 10:30</time>
|
<time datetime=""></time>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<span>7 min read</span>
|
<span>7 min read</span>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<span>By Glenn Thompson</span>
|
<span>By Glenn Thompson</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-wrap gap-2 mt-4">
|
</header>
|
||||||
<span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">personal</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">tech</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">keyboards</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">glove80</span>
|
|
||||||
</div>
|
<article class="prose prose-palenight max-w-none">
|
||||||
</header>
|
<hr>
|
||||||
|
<h2>title: Transitioning from Hugo to Haunt: Embracing Scheme and GNU Guix<br>author: Glenn Thompson<br>date: 2024-05-15 10:30<br>tags: personal, tech, keyboards, glove80</h2>
|
||||||
<article class="prose prose-palenight max-w-none">
|
<h1>Transitioning from Hugo to Haunt: Embracing Scheme and GNU Guix</h1>
|
||||||
<h1>Transitioning from Hugo to Haunt: Embracing Scheme and GNU Guix</h1>
|
<p>Hello there! I'm Glenn Thompson, and today, I want to share a significant part of my recent journey into the world of Scheme, GNU Guix, and static site generation.</p>
|
||||||
<p>Hello there! I'm Glenn Thompson, and today, I want to share a significant part of my recent journey into the world of Scheme, GNU Guix, and static site generation.</p>
|
<h2>Discovering Scheme with System Crafters</h2>
|
||||||
<h2>Discovering Scheme with System Crafters</h2>
|
<p>My journey began with a desire to dive deeper into programming languages and their ecosystems. I am a member of the <a href="https://systemcrafters.net/community/">System Crafters Community</a>, and its founder, David Wilson, announced a short four week course as an introduction to Guile Scheme. The course, <a href="https://systemcrafters.net/courses/hands-on-guile-scheme-beginners/">Hands-On Guile Scheme for Beginners</a>, provided me with a robust introduction to Guile Scheme, a language that emphasizes simplicity and elegance. David's clear explanations and practical examples made learning Scheme both engaging and approachable.</p>
|
||||||
<p>My journey began with a desire to dive deeper into programming languages and their ecosystems. I am a member of the <a href="https://systemcrafters.net/community/">System Crafters Community</a>, and its founder, David Wilson, announced a short four week course as an introduction to Guile Scheme. The course, <a href="https://systemcrafters.net/courses/hands-on-guile-scheme-beginners/">Hands-On Guile Scheme for Beginners</a>, provided me with a robust introduction to Guile Scheme, a language that emphasizes simplicity and elegance. David's clear explanations and practical examples made learning Scheme both engaging and approachable.</p>
|
<h2>The Move to GNU Guix</h2>
|
||||||
<h2>The Move to GNU Guix</h2>
|
<p>Inspired by the principles of Scheme, I decided to take a leap further into the open-source world by transitioning from Arch Linux to GNU Guix. The Guix community, particularly the folks in the <code>#systemcrafters</code> channel on <code>irc.libera.chat</code>, were incredibly supportive and instrumental in helping me navigate this new environment. Their guidance made the switch smooth and rewarding, reinforcing the power and flexibility of GNU Guix as a functional package manager and operating system. More about that experience in another post.</p>
|
||||||
<p>Inspired by the principles of Scheme, I decided to take a leap further into the open-source world by transitioning from Arch Linux to GNU Guix. The Guix community, particularly the folks in the <code>#systemcrafters</code> channel on <code>irc.libera.chat</code>, were incredibly supportive and instrumental in helping me navigate this new environment. Their guidance made the switch smooth and rewarding, reinforcing the power and flexibility of GNU Guix as a functional package manager and operating system. More about that experience in another post.</p>
|
<p>There are too many individuals to name here that have helped with the installation and configuration on Gnu guix to mention here. You all have been an incredible help for which I am extremely grateful. Thank you all , for enduring my ignorance, and for your patience and your help.</p>
|
||||||
<p>There are too many individuals to name here that have helped with the installation and configuration on Gnu guix to mention here. You all have been an incredible help for which I am extremely grateful. Thank you all , for enduring my ignorance, and for your patience and your help.</p>
|
<h2>From Hugo to Haunt</h2>
|
||||||
<h2>From Hugo to Haunt</h2>
|
<p>As I settled into Guix, I faced a challenge: Hugo, the static site generator I previously used, was not available as a Guix package. This led me to explore alternatives and eventually discover <a href="https://dthompson.us/projects/haunt.html">Haunt</a>, a Scheme-based static site generator that aligns perfectly with my newfound appreciation for Scheme and Guix.</p>
|
||||||
<p>As I settled into Guix, I faced a challenge: Hugo, the static site generator I previously used, was not available as a Guix package. This led me to explore alternatives and eventually discover <a href="https://dthompson.us/projects/haunt.html">Haunt</a>, a Scheme-based static site generator that aligns perfectly with my newfound appreciation for Scheme and Guix.</p>
|
<h2>Overcoming Challenges with Haunt</h2>
|
||||||
<h2>Overcoming Challenges with Haunt</h2>
|
<p>Transitioning to Haunt wasn't without its challenges. There are no readily available templating systems available for haunt like there are for hugo, but there are plenty of examples <a href="https://awesome.haunt.page/">here</a>. One of my own primary difficulties was creating a custom template that matched my site's aesthetic requirements and functionality needs. Initially, I struggled with configuring the theme layout and ensuring the CSS was applied correctly. Another hurdle was generating the correct URLs for posts and ensuring that summaries appeared as intended on the front page.</p>
|
||||||
<p>Transitioning to Haunt wasn't without its challenges. There are no readily available templating systems available for haunt like there are for hugo, but there are plenty of examples <a href="https://awesome.haunt.page/">here</a>. One of my own primary difficulties was creating a custom template that matched my site's aesthetic requirements and functionality needs. Initially, I struggled with configuring the theme layout and ensuring the CSS was applied correctly. Another hurdle was generating the correct URLs for posts and ensuring that summaries appeared as intended on the front page.</p>
|
<p>Thankfully, the Haunt manual proved to be an invaluable resource throughout this process. The comprehensive documentation provided clear guidance on using various modules, functions, and procedures. By carefully studying the examples and explanations, I was able to overcome the obstacles and achieve the desired results for my site. The manual's detailed descriptions of Haunt's inner workings were particularly helpful in understanding how to leverage the flexibility of Scheme to customize my blog.</p>
|
||||||
<p>Thankfully, the Haunt manual proved to be an invaluable resource throughout this process. The comprehensive documentation provided clear guidance on using various modules, functions, and procedures. By carefully studying the examples and explanations, I was able to overcome the obstacles and achieve the desired results for my site. The manual's detailed descriptions of Haunt's inner workings were particularly helpful in understanding how to leverage the flexibility of Scheme to customize my blog.</p>
|
<h2>Crafting My Own Template</h2>
|
||||||
<h2>Crafting My Own Template</h2>
|
<p>Moving from Hugo to Haunt required me to create my own template and customize my site's appearance. This was an exciting opportunity to apply the skills I had learned from David's course and experiment with Scheme in a practical context.</p>
|
||||||
<p>Moving from Hugo to Haunt required me to create my own template and customize my site's appearance. This was an exciting opportunity to apply the skills I had learned from David's course and experiment with Scheme in a practical context.</p>
|
<h4>Creating the Template</h4>
|
||||||
<h4>Creating the Template</h4>
|
<p>Haunt's flexibility allowed me to define my own theme layout and structure. Here's a snippet of my <code>haunt.scm</code> file, where I defined the theme layout and added custom footer content:</p>
|
||||||
<p>Haunt's flexibility allowed me to define my own theme layout and structure. Here's a snippet of my <code>haunt.scm</code> file, where I defined the theme layout and added custom footer content:</p>
|
<pre><code class="language-scheme">(use-modules (haunt asset)
|
||||||
<pre><code class="language-scheme">(use-modules (haunt asset)
|
(haunt builder blog)
|
||||||
(haunt builder blog)
|
(haunt builder atom)
|
||||||
(haunt builder atom)
|
(haunt builder assets)
|
||||||
(haunt builder assets)
|
(haunt reader commonmark)
|
||||||
(haunt reader commonmark)
|
(haunt site)
|
||||||
(haunt site)
|
(haunt post)
|
||||||
(haunt post)
|
(sxml simple) ; For HTML generation
|
||||||
(sxml simple) ; For HTML generation
|
(srfi srfi-1)
|
||||||
(srfi srfi-1)
|
(srfi srfi-19)) ; For date and time procedures
|
||||||
(srfi srfi-19)) ; For date and time procedures
|
|
||||||
|
;; Load custom templates
|
||||||
;; Load custom templates
|
(load "templates/post.scm")
|
||||||
(load "templates/post.scm")
|
|
||||||
|
(define (format-date date)
|
||||||
(define (format-date date)
|
(date->string date "~Y-~m-~d"))
|
||||||
(date->string date "~Y-~m-~d"))
|
|
||||||
|
;; Define a function to generate the URL for a post
|
||||||
;; Define a function to generate the URL for a post
|
(define (post-url post)
|
||||||
(define (post-url post)
|
(string-append "/" (post-slug post) ".html"))
|
||||||
(string-append "/" (post-slug post) ".html"))
|
|
||||||
|
;; Define a function to extract a summary from the post content
|
||||||
;; Define a function to extract a summary from the post content
|
(define (post-summary post)
|
||||||
(define (post-summary post)
|
(let ((content (post-sxml post)))
|
||||||
(let ((content (post-sxml post)))
|
(if (null? content)
|
||||||
(if (null? content)
|
""
|
||||||
""
|
(let ((first-paragraph (car content)))
|
||||||
(let ((first-paragraph (car content)))
|
(if (string? first-paragraph)
|
||||||
(if (string? first-paragraph)
|
(substring first-paragraph 0 (min 200 (string-length first-paragraph)))
|
||||||
(substring first-paragraph 0 (min 200 (string-length first-paragraph)))
|
(sxml->string first-paragraph))))))
|
||||||
(sxml->string first-paragraph))))))
|
|
||||||
|
;; Define the theme layout
|
||||||
;; Define the theme layout
|
(define (theme-layout site title content)
|
||||||
(define (theme-layout site title content)
|
(let ((current-year (number->string (date-year (current-date)))))
|
||||||
(let ((current-year (number->string (date-year (current-date)))))
|
`(html
|
||||||
`(html
|
(head
|
||||||
(head
|
(meta (@ (charset "utf-8")))
|
||||||
(meta (@ (charset "utf-8")))
|
(meta (@ (name "viewport") (content "width=device-width, initial-scale=1.0, shrink-to-fit=no")))
|
||||||
(meta (@ (name "viewport") (content "width=device-width, initial-scale=1.0, shrink-to-fit=no")))
|
(link (@ (rel "stylesheet") (href "/assets/palenight.css")))
|
||||||
(link (@ (rel "stylesheet") (href "/assets/palenight.css")))
|
(style
|
||||||
(style
|
" .craftering {
|
||||||
" .craftering {
|
margin: auto;
|
||||||
margin: auto;
|
width: 50%;
|
||||||
width: 50%;
|
text-align: center;
|
||||||
text-align: center;
|
}
|
||||||
}
|
.webring-text {
|
||||||
.webring-text {
|
text-align: center;
|
||||||
text-align: center;
|
margin-bottom: 20px;
|
||||||
margin-bottom: 20px;
|
color: white;
|
||||||
color: white;
|
}
|
||||||
}
|
.craftering a {
|
||||||
.craftering a {
|
color: #dddddd;
|
||||||
color: #dddddd;
|
}
|
||||||
}
|
.webring-text a {
|
||||||
.webring-text a {
|
color: #dddddd;
|
||||||
color: #dddddd;
|
}")
|
||||||
}")
|
(title ,title))
|
||||||
(title ,title))
|
(body
|
||||||
(body
|
(header (h1 ,(site-title site)))
|
||||||
(header (h1 ,(site-title site)))
|
(main ,content)
|
||||||
(main ,content)
|
(footer (@ (class "bg-black bottom-0 w-100 pa3") (role "contentinfo"))
|
||||||
(footer (@ (class "bg-black bottom-0 w-100 pa3") (role "contentinfo"))
|
(div (@ (class "flex justify-between"))
|
||||||
(div (@ (class "flex justify-between"))
|
(div (@ (class "webring-text"))
|
||||||
(div (@ (class "webring-text"))
|
(p "I am part of the " (a (@ (href "https://systemcrafters.net") (target "_blank")) "System Crafters") " webring:"))
|
||||||
(p "I am part of the " (a (@ (href "https://systemcrafters.net") (target "_blank")) "System Crafters") " webring:"))
|
(div (@ (class "craftering"))
|
||||||
(div (@ (class "craftering"))
|
(a (@ (href "https://craftering.systemcrafters.net/@glenneth/previous")) "←")
|
||||||
(a (@ (href "https://craftering.systemcrafters.net/@glenneth/previous")) "←")
|
(a (@ (href "https://craftering.systemcrafters.net/")) "craftering")
|
||||||
(a (@ (href "https://craftering.systemcrafters.net/")) "craftering")
|
(a (@ (href "https://craftering.systemcrafters.net/@glenneth/next")) "→"))))))))
|
||||||
(a (@ (href "https://craftering.systemcrafters.net/@glenneth/next")) "→"))))))))
|
|
||||||
|
;; Define the custom theme with a consistent layout for index
|
||||||
;; Define the custom theme with a consistent layout for index
|
(define my-theme
|
||||||
(define my-theme
|
(theme #:name "My Custom Theme"
|
||||||
(theme #:name "My Custom Theme"
|
#:layout theme-layout
|
||||||
#:layout theme-layout
|
#:post-template post-template
|
||||||
#:post-template post-template
|
#:collection-template
|
||||||
#:collection-template
|
(lambda (site title posts prefix)
|
||||||
(lambda (site title posts prefix)
|
`(div (@ (class "content"))
|
||||||
`(div (@ (class "content"))
|
(h2 ,title)
|
||||||
(h2 ,title)
|
(ul
|
||||||
(ul
|
,@(map (lambda (post)
|
||||||
,@(map (lambda (post)
|
`(li
|
||||||
`(li
|
(article
|
||||||
(article
|
(header
|
||||||
(header
|
(h3 (a (@ (href ,(post-url post))) ,(post-title post))))
|
||||||
(h3 (a (@ (href ,(post-url post))) ,(post-title post))))
|
(p ,(format-date (post-date post)))
|
||||||
(p ,(format-date (post-date post)))
|
(p ,(post-summary post))
|
||||||
(p ,(post-summary post))
|
(p (a (@ (href ,(post-url post))) "Read more...")))))
|
||||||
(p (a (@ (href ,(post-url post))) "Read more...")))))
|
posts))))))
|
||||||
posts))))))
|
|
||||||
|
;; Site configuration
|
||||||
;; Site configuration
|
(site #:title "Just Another Personal Blog"
|
||||||
(site #:title "Just Another Personal Blog"
|
#:domain "glenneth.srht.site"
|
||||||
#:domain "glenneth.srht.site"
|
#:default-metadata
|
||||||
#:default-metadata
|
'((author . "Glenn Thompson")
|
||||||
'((author . "Glenn Thompson")
|
(email . "glenn@kirstol.org"))
|
||||||
(email . "glenn@kirstol.org"))
|
#:readers (list commonmark-reader)
|
||||||
#:readers (list commonmark-reader)
|
#:builders (list
|
||||||
#:builders (list
|
(blog #:theme my-theme)
|
||||||
(blog #:theme my-theme)
|
(atom-feed)
|
||||||
(atom-feed)
|
(atom-feeds-by-tag)
|
||||||
(atom-feeds-by-tag)
|
(static-directory "images")
|
||||||
(static-directory "images")
|
(static-directory "assets")))
|
||||||
(static-directory "assets")))
|
</code></pre>
|
||||||
</code></pre>
|
<h3>Customizing the CSS</h3>
|
||||||
<h3>Customizing the CSS</h3>
|
<p>To give my site a personalized touch, I crafted a CSS stylesheet that matched my aesthetic preferences. Here’s an excerpt from my <code>palenight.css</code> file:</p>
|
||||||
<p>To give my site a personalized touch, I crafted a CSS stylesheet that matched my aesthetic preferences. Here’s an excerpt from my <code>palenight.css</code> file:</p>
|
<pre><code class="language-css">body {
|
||||||
<pre><code class="language-css">body {
|
display: flex;
|
||||||
display: flex;
|
justify-content: center;
|
||||||
justify-content: center;
|
padding: 10px;
|
||||||
padding: 10px;
|
}
|
||||||
}
|
|
||||||
|
.content, header, footer, main {
|
||||||
.content, header, footer, main {
|
max-width: 90%;
|
||||||
max-width: 90%;
|
padding: 0 5%;
|
||||||
padding: 0 5%;
|
}
|
||||||
}
|
|
||||||
|
header {
|
||||||
header {
|
text-align: center;
|
||||||
text-align: center;
|
margin-bottom: 20px;
|
||||||
margin-bottom: 20px;
|
}
|
||||||
}
|
|
||||||
|
footer {
|
||||||
footer {
|
text-align: center;
|
||||||
text-align: center;
|
margin-top: 20px;
|
||||||
margin-top: 20px;
|
}
|
||||||
}
|
|
||||||
|
ul {
|
||||||
ul {
|
list-style-type: none;
|
||||||
list-style-type: none;
|
padding: 0;
|
||||||
padding: 0;
|
}
|
||||||
}
|
|
||||||
|
li {
|
||||||
li {
|
margin-bottom: 20px;
|
||||||
margin-bottom: 20px;
|
}
|
||||||
}
|
|
||||||
|
a {
|
||||||
a {
|
text-decoration: none;
|
||||||
text-decoration: none;
|
}
|
||||||
}
|
|
||||||
|
a:hover {
|
||||||
a:hover {
|
text-decoration: underline;
|
||||||
text-decoration: underline;
|
}
|
||||||
}
|
|
||||||
|
body {
|
||||||
body {
|
background-color: #292d3e;
|
||||||
background-color: #292d3e;
|
color: #d0d0d0;
|
||||||
color: #d0d0d0;
|
}
|
||||||
}
|
|
||||||
|
a {
|
||||||
a {
|
color: #82aaff;
|
||||||
color: #82aaff;
|
}
|
||||||
}
|
|
||||||
|
h1, h2, h3, h4, h5, h6 {
|
||||||
h1, h2, h3, h4, h5, h6 {
|
color: #c792ea;
|
||||||
color: #c792ea;
|
}
|
||||||
}
|
|
||||||
|
.content {
|
||||||
.content {
|
background-color: #1e1e2e;
|
||||||
background-color: #1e1e2e;
|
padding: 20px;
|
||||||
padding: 20px;
|
border-radius: 5px;
|
||||||
border-radius: 5px;
|
}
|
||||||
}
|
|
||||||
|
article {
|
||||||
article {
|
background-color: #282a36;
|
||||||
background-color: #282a36;
|
padding: 15px;
|
||||||
padding: 15px;
|
border-radius: 8px;
|
||||||
border-radius: 8px;
|
margin-bottom: 20px;
|
||||||
margin-bottom: 20px;
|
}
|
||||||
}
|
|
||||||
|
article header {
|
||||||
article header {
|
margin-bottom: 10px;
|
||||||
margin-bottom: 10px;
|
}
|
||||||
}
|
|
||||||
|
.date {
|
||||||
.date {
|
color: #6272a4;
|
||||||
color: #6272a4;
|
font-size: 0.9em;
|
||||||
font-size: 0.9em;
|
}
|
||||||
}
|
|
||||||
|
/* Additional styles for the craftering */
|
||||||
/* Additional styles for the craftering */
|
.craftering {
|
||||||
.craftering {
|
margin: auto;
|
||||||
margin: auto;
|
width: 50%;
|
||||||
width: 50%;
|
text-align: center;
|
||||||
text-align: center;
|
}
|
||||||
}
|
|
||||||
|
.webring-text {
|
||||||
.webring-text {
|
text-align: center;
|
||||||
text-align: center;
|
margin-bottom: 20px;
|
||||||
margin-bottom: 20px;
|
color: white;
|
||||||
color: white;
|
}
|
||||||
}
|
|
||||||
|
.craftering a {
|
||||||
.craftering a {
|
color: #dddddd;
|
||||||
color: #dddddd;
|
}
|
||||||
}
|
|
||||||
|
.webring-text a {
|
||||||
.webring-text a {
|
color: #dddddd;
|
||||||
color: #dddddd;
|
}
|
||||||
}
|
|
||||||
|
/* Additions for mobile device readability */
|
||||||
/* Additions for mobile device readability */
|
|
||||||
|
meta {
|
||||||
meta {
|
name: viewport;
|
||||||
name: viewport;
|
content: width=device-width, initial-scale=1, shrink-to-fit=no;
|
||||||
content: width=device-width, initial-scale=1, shrink-to-fit=no;
|
}
|
||||||
}
|
|
||||||
|
@media screen and (max-width: 767px) {
|
||||||
@media screen and (max-width: 767px) {
|
/* Customize styles for smaller screens */
|
||||||
/* Customize styles for smaller screens */
|
.logo {
|
||||||
.logo {
|
max-width: 200px;
|
||||||
max-width: 200px;
|
}
|
||||||
}
|
|
||||||
|
}
|
||||||
}
|
</code></pre>
|
||||||
</code></pre>
|
<p>I use the <code>doom-palenight</code> theme in Emacs, my preferred text editor, and I wanted my site to match that aesthetic.</p>
|
||||||
<p>I use the <code>doom-palenight</code> theme in Emacs, my preferred text editor, and I wanted my site to match that aesthetic.</p>
|
<h3>Publishing with Haunt and Hut</h3>
|
||||||
<h3>Publishing with Haunt and Hut</h3>
|
<p>In addition to using Haunt, I adopted hut, a set of command-line tools for interacting with SourceHut, to publish my blog. This streamlined my workflow, making it easier to manage and deploy my site directly from my local environment.</p>
|
||||||
<p>In addition to using Haunt, I adopted hut, a set of command-line tools for interacting with SourceHut, to publish my blog. This streamlined my workflow, making it easier to manage and deploy my site directly from my local environment.</p>
|
<h3>Conclusion</h3>
|
||||||
<h3>Conclusion</h3>
|
<p>Transitioning from Hugo to Haunt, learning Scheme, and embracing GNU Guix has been an enriching experience. It's not just about using new tools; it's about joining a community that values simplicity, transparency, and collaboration. If you're curious about Scheme or GNU Guix, I highly recommend checking out David Wilson's course on System Crafters and joining the discussions on IRC.</p>
|
||||||
<p>Transitioning from Hugo to Haunt, learning Scheme, and embracing GNU Guix has been an enriching experience. It's not just about using new tools; it's about joining a community that values simplicity, transparency, and collaboration. If you're curious about Scheme or GNU Guix, I highly recommend checking out David Wilson's course on System Crafters and joining the discussions on IRC.</p>
|
<p>I am not a developer of any kind, and learning Scheme has opened my eyes as to how I can craft an environment that I want to work in, and not endure a working environment that the computer is forcing upon me.</p>
|
||||||
<p>I am not a developer of any kind, and learning Scheme has opened my eyes as to how I can craft an environment that I want to work in, and not endure a working environment that the computer is forcing upon me.</p>
|
<p>Thank you for reading, and stay tuned for more updates on my journey!</p>
|
||||||
<p>Thank you for reading, and stay tuned for more updates on my journey!</p>
|
|
||||||
|
</article>
|
||||||
</article>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</main>
|
||||||
</main>
|
<footer class="bg-base-darker text-palenight-200 py-12 border-t border-palenight-400/20">
|
||||||
<footer class="bg-base-darker text-palenight-200 py-12 border-t border-palenight-400/20">
|
<div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
<div class="text-center">
|
||||||
<div class="text-center">
|
<p class="text-palenight-300">© 2026 Glenn Thompson. All rights reserved.</p>
|
||||||
<p class="text-palenight-300">© 2024 Glenn Thompson. All rights reserved.</p>
|
<div class="webring-text mt-6">
|
||||||
<div class="webring-text mt-6">
|
<p class="text-palenight-300">I am part of the <a href="https://systemcrafters.net" target="_blank" class="text-accent-blue hover:text-accent-cyan">System Crafters</a> webring:</p>
|
||||||
<p class="text-palenight-300">I am part of the <a href="https://systemcrafters.net" target="_blank" class="text-accent-blue hover:text-accent-cyan">System Crafters</a> webring:</p>
|
</div>
|
||||||
</div>
|
<div class="craftering mt-2 flex items-center justify-center gap-4 text-accent-blue">
|
||||||
<div class="craftering mt-2 flex items-center justify-center gap-4 text-accent-blue">
|
<a href="https://craftering.systemcrafters.net/@glenneth/previous" class="hover:text-accent-cyan">Previous</a>
|
||||||
<a href="https://craftering.systemcrafters.net/@glenneth/previous" class="hover:text-accent-cyan">Previous</a>
|
<a href="https://craftering.systemcrafters.net/@glenneth" class="hover:text-accent-cyan">Random</a>
|
||||||
<a href="https://craftering.systemcrafters.net/@glenneth" class="hover:text-accent-cyan">Random</a>
|
<a href="https://craftering.systemcrafters.net/@glenneth/next" class="hover:text-accent-cyan">Next</a>
|
||||||
<a href="https://craftering.systemcrafters.net/@glenneth/next" class="hover:text-accent-cyan">Next</a>
|
</div>
|
||||||
</div>
|
<p class="text-palenight-300 mt-2">
|
||||||
<p class="text-palenight-300 mt-2">
|
<a href="mailto:glenn@glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenn@glenneth.org</a> |
|
||||||
<a href="mailto:glenn@glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenn@glenneth.org</a> |
|
<a href="https://glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenneth.org</a>
|
||||||
<a href="https://glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenneth.org</a>
|
</p>
|
||||||
</p>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</footer>
|
||||||
</footer>
|
</body>
|
||||||
</body>
|
|
||||||
</html>
|
</html>
|
||||||
|
|
@ -1,190 +1,189 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en" class="bg-base-bg">
|
<html lang="en" class="bg-base-bg">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<meta name="description" content="">
|
<meta name="description" content="">
|
||||||
<meta property="og:title" content="A Journey Through GNU Guix: From Installation to Returning to Arch Linux">
|
<meta property="og:title" content="Blog Post">
|
||||||
<meta property="og:description" content="">
|
<meta property="og:description" content="">
|
||||||
<meta property="og:url" content="https://glenneth.orgcontent/posts/2024-07-26-gnu-guix-journey">
|
<meta property="og:url" content="https://glenneth.orgcontent/posts/2024-07-26-gnu-guix-journey">
|
||||||
<title>A Journey Through GNU Guix: From Installation to Returning to Arch Linux - Glenn Thompson</title>
|
<title>Blog Post - Glenn Thompson</title>
|
||||||
<link rel="alternate" type="application/rss+xml" title="Glenn Thompson's Blog" href="/feed.xml" />
|
<link rel="alternate" type="application/rss+xml" title="Glenn Thompson's Blog" href="/feed.xml" />
|
||||||
<link href="../../dist/styles.css" rel="stylesheet">
|
<link href="/dist/styles.css" rel="stylesheet">
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Merriweather:wght@400;700&family=JetBrains+Mono:wght@400;700&display=swap" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Merriweather:wght@400;700&family=JetBrains+Mono:wght@400;700&display=swap" rel="stylesheet">
|
||||||
<style>
|
<style>
|
||||||
.prose-palenight {
|
.prose-palenight {
|
||||||
--tw-prose-body: #bfc7d5;
|
--tw-prose-body: #bfc7d5;
|
||||||
--tw-prose-headings: #ffd580;
|
--tw-prose-headings: #ffd580;
|
||||||
--tw-prose-links: #82aaff;
|
--tw-prose-links: #82aaff;
|
||||||
--tw-prose-code: #c792ea;
|
--tw-prose-code: #c792ea;
|
||||||
--tw-prose-pre-bg: #1b1e2b;
|
--tw-prose-pre-bg: #1b1e2b;
|
||||||
}
|
}
|
||||||
.prose h2 {
|
.prose h2 {
|
||||||
color: var(--tw-prose-headings);
|
color: var(--tw-prose-headings);
|
||||||
font-family: Merriweather, serif;
|
font-family: Merriweather, serif;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
font-size: 1.5rem;
|
font-size: 1.5rem;
|
||||||
margin-top: 2rem;
|
margin-top: 2rem;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
}
|
}
|
||||||
.prose p {
|
.prose p {
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
line-height: 1.625;
|
line-height: 1.625;
|
||||||
}
|
}
|
||||||
.prose a {
|
.prose a {
|
||||||
color: var(--tw-prose-links);
|
color: var(--tw-prose-links);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
.prose a:hover {
|
.prose a:hover {
|
||||||
color: #89ddff;
|
color: #89ddff;
|
||||||
}
|
}
|
||||||
.prose code {
|
.prose code {
|
||||||
color: var(--tw-prose-code);
|
color: var(--tw-prose-code);
|
||||||
font-family: 'JetBrains Mono', monospace;
|
font-family: 'JetBrains Mono', monospace;
|
||||||
}
|
}
|
||||||
.prose pre {
|
.prose pre {
|
||||||
background-color: var(--tw-prose-pre-bg);
|
background-color: var(--tw-prose-pre-bg);
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
}
|
}
|
||||||
.prose ul, .prose ol {
|
.prose ul, .prose ol {
|
||||||
margin-top: 0.5rem;
|
margin-top: 0.5rem;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
padding-left: 1.5rem;
|
padding-left: 1.5rem;
|
||||||
}
|
}
|
||||||
.prose ul {
|
.prose ul {
|
||||||
list-style-type: disc;
|
list-style-type: disc;
|
||||||
}
|
}
|
||||||
.prose ol {
|
.prose ol {
|
||||||
list-style-type: decimal;
|
list-style-type: decimal;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body class="bg-base-bg text-palenight-50">
|
<body class="bg-base-bg text-palenight-50">
|
||||||
<nav class="bg-base-darker/80 backdrop-blur-sm shadow-sm border-b border-palenight-400/20 mb-8">
|
<nav class="bg-base-darker/80 backdrop-blur-sm shadow-sm border-b border-palenight-400/20 mb-8">
|
||||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<div class="flex items-center justify-between h-16">
|
<div class="flex items-center justify-between h-16">
|
||||||
<a href="/" class="text-accent-yellow font-serif text-xl font-bold">Glenn Thompson</a>
|
<a href="/" class="text-accent-yellow font-serif text-xl font-bold">Glenn Thompson</a>
|
||||||
<div class="flex items-center gap-2 text-accent-yellow text-sm font-bold">
|
<div class="flex items-center gap-2 text-accent-yellow text-sm font-bold">
|
||||||
<span>personal, tech, gnu, guix, swaywm, nvidia</span>
|
<span>Tech</span>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<time datetime="2024-07-26 10:30">July 26, 2024</time>
|
<time datetime="undefined">Invalid Date</time>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<span>7 min read</span>
|
<span>7 min read</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<main class="pt-24 pb-16 px-4">
|
<main class="pt-24 pb-16 px-4">
|
||||||
<div class="max-w-4xl mx-auto">
|
<div class="max-w-4xl mx-auto">
|
||||||
<div class="content text-palenight-100 space-y-6">
|
<div class="content text-palenight-100 space-y-6">
|
||||||
<header class="mb-8">
|
<header class="mb-8">
|
||||||
<h1 class="text-4xl font-serif font-bold text-accent-yellow">A Journey Through GNU Guix: From Installation to Returning to Arch Linux</h1>
|
<h1 class="text-4xl font-serif font-bold text-accent-yellow">Blog Post</h1>
|
||||||
<div class="flex items-center gap-4 text-palenight-300 mt-4">
|
<div class="flex items-center gap-4 text-palenight-300 mt-4">
|
||||||
<time datetime="2024-07-26 10:30">2024-07-26 10:30</time>
|
<time datetime=""></time>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<span>7 min read</span>
|
<span>7 min read</span>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<span>By Glenn Thompson</span>
|
<span>By Glenn Thompson</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-wrap gap-2 mt-4">
|
</header>
|
||||||
<span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">personal</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">tech</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">gnu</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">guix</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">swaywm</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">nvidia</span>
|
|
||||||
</div>
|
<article class="prose prose-palenight max-w-none">
|
||||||
</header>
|
<hr>
|
||||||
|
<h2>title: A Journey Through GNU Guix: From Installation to Returning to Arch Linux<br>author: Glenn Thompson<br>date: 2024-07-26 10:30<br>tags: personal, tech, gnu, guix, swaywm, nvidia</h2>
|
||||||
<article class="prose prose-palenight max-w-none">
|
<h1>A Journey Through GNU Guix: From Installation to Returning to Arch Linux</h1>
|
||||||
<h1>A Journey Through GNU Guix: From Installation to Returning to Arch Linux</h1>
|
<p>As a long-time user of Arch Linux, I decided to explore the world of GNU Guix to see if it could better suit my needs, especially with my growing interest in functional package management. The journey was insightful, filled with learning experiences, but ultimately led me back to the reliable shores of Arch. Here's a detailed account of my venture into GNU Guix, adding non-GNU channels, dealing with Nvidia drivers, running SwayWM, and the eventual retreat to Arch.</p>
|
||||||
<p>As a long-time user of Arch Linux, I decided to explore the world of GNU Guix to see if it could better suit my needs, especially with my growing interest in functional package management. The journey was insightful, filled with learning experiences, but ultimately led me back to the reliable shores of Arch. Here's a detailed account of my venture into GNU Guix, adding non-GNU channels, dealing with Nvidia drivers, running SwayWM, and the eventual retreat to Arch.</p>
|
<h2>Installation of GNU Guix</h2>
|
||||||
<h2>Installation of GNU Guix</h2>
|
<p>The installation process of GNU Guix was straightforward, thanks to the well-documented guide provided on their official website. Here's a quick rundown of the steps I followed:</p>
|
||||||
<p>The installation process of GNU Guix was straightforward, thanks to the well-documented guide provided on their official website. Here's a quick rundown of the steps I followed:</p>
|
<ol>
|
||||||
<ol>
|
<li><strong>Downloading the Installation Image</strong>: I started by downloading the latest ISO image from the <a href="https://guix.gnu.org/">GNU Guix website</a>.</li>
|
||||||
<li><strong>Downloading the Installation Image</strong>: I started by downloading the latest ISO image from the <a href="https://guix.gnu.org/">GNU Guix website</a>.</li>
|
<li><strong>Creating a Bootable USB</strong>: Using <code>dd</code>, I created a bootable USB stick to install GNU Guix on my system.</li>
|
||||||
<li><strong>Creating a Bootable USB</strong>: Using <code>dd</code>, I created a bootable USB stick to install GNU Guix on my system.</li>
|
<li><strong>Booting into the Installer</strong>: Booting from the USB was smooth, and I was greeted with the GNU Guix installer. The installer's simplicity reminded me of early days with Arch, where a minimalistic approach is preferred.</li>
|
||||||
<li><strong>Booting into the Installer</strong>: Booting from the USB was smooth, and I was greeted with the GNU Guix installer. The installer's simplicity reminded me of early days with Arch, where a minimalistic approach is preferred.</li>
|
<li><strong>Partitioning and Setting Up File Systems</strong>: I partitioned my drive using <code>fdisk</code> and set up my file systems. I opted for ext4 for simplicity.</li>
|
||||||
<li><strong>Partitioning and Setting Up File Systems</strong>: I partitioned my drive using <code>fdisk</code> and set up my file systems. I opted for ext4 for simplicity.</li>
|
<li><strong>Configuring the System</strong>: Following the partition setup, I proceeded to configure my system by selecting the required packages and services. I decided to go with the Sway window manager as it's my preferred choice on Arch.</li>
|
||||||
<li><strong>Configuring the System</strong>: Following the partition setup, I proceeded to configure my system by selecting the required packages and services. I decided to go with the Sway window manager as it's my preferred choice on Arch.</li>
|
</ol>
|
||||||
</ol>
|
<h2>System Configuration</h2>
|
||||||
<h2>System Configuration</h2>
|
<p>During the installation process a window appears informing you that the <code>config.scm</code> file is located at <code>/etc/config.scm</code>. The first time I installed gnu guix on my work laptop I missed this message (pilot error) and I had to ask in the <a href="https://systemcrafters.net">System Crafters</a> IRC channel at <code>irc.libera.chat</code>, <code>#systemcrafters</code>. Come and join. It's a great place to be and the community there are an absolute treasure. Use your favourite IRC client or join through the webchat <a href="https://web.libera.chat/?channel=#systemcrafters">here</a>. We would be glad to see you. Tell them glenneth sent you :).</p>
|
||||||
<p>During the installation process a window appears informing you that the <code>config.scm</code> file is located at <code>/etc/config.scm</code>. The first time I installed gnu guix on my work laptop I missed this message (pilot error) and I had to ask in the <a href="https://systemcrafters.net">System Crafters</a> IRC channel at <code>irc.libera.chat</code>, <code>#systemcrafters</code>. Come and join. It's a great place to be and the community there are an absolute treasure. Use your favourite IRC client or join through the webchat <a href="https://web.libera.chat/?channel=#systemcrafters">here</a>. We would be glad to see you. Tell them glenneth sent you :).</p>
|
<p>My point is, I missed some vital information, so to the guix manual online it was. This can be found <a href="https://guix.gnu.org/manual/devel/en/guix.html">here</a>. This link will take you to the dev version of the manual. Something else they don't tell you. This version has a little more detail than the standard manual, and I believe details extra features and may even be a little more up to date.</p>
|
||||||
<p>My point is, I missed some vital information, so to the guix manual online it was. This can be found <a href="https://guix.gnu.org/manual/devel/en/guix.html">here</a>. This link will take you to the dev version of the manual. Something else they don't tell you. This version has a little more detail than the standard manual, and I believe details extra features and may even be a little more up to date.</p>
|
<h2>Adding Non-GNU Channels</h2>
|
||||||
<h2>Adding Non-GNU Channels</h2>
|
<p>One of the standout features of GNU Guix is the ability to add non-GNU channels to access a wider array of software packages. Here's how I did it:</p>
|
||||||
<p>One of the standout features of GNU Guix is the ability to add non-GNU channels to access a wider array of software packages. Here's how I did it:</p>
|
<ol>
|
||||||
<ol>
|
<li><strong>Editing Channels</strong>: I edited the <code>~/.config/guix/channels.scm</code> file to include non-GNU channels.<pre><code class="language-scheme">(cons* (channel
|
||||||
<li><strong>Editing Channels</strong>: I edited the <code>~/.config/guix/channels.scm</code> file to include non-GNU channels.<pre><code class="language-scheme">(cons* (channel
|
(name 'non-gnu)
|
||||||
(name 'non-gnu)
|
(url "https://example.com/non-gnu-channel.git"))
|
||||||
(url "https://example.com/non-gnu-channel.git"))
|
%default-channels)
|
||||||
%default-channels)
|
</code></pre>
|
||||||
</code></pre>
|
</li>
|
||||||
</li>
|
<li><strong>Updating Channels</strong>: Running <code>guix pull</code> updated my system to include packages from the non-GNU channel.</li>
|
||||||
<li><strong>Updating Channels</strong>: Running <code>guix pull</code> updated my system to include packages from the non-GNU channel.</li>
|
</ol>
|
||||||
</ol>
|
<h2>Installing Nvidia Drivers</h2>
|
||||||
<h2>Installing Nvidia Drivers</h2>
|
<p>Being a gamer and someone who requires GPU acceleration for certain tasks, Nvidia drivers were a must. Here's the process I followed:</p>
|
||||||
<p>Being a gamer and someone who requires GPU acceleration for certain tasks, Nvidia drivers were a must. Here's the process I followed:</p>
|
<ol>
|
||||||
<ol>
|
<li><strong>Adding Nvidia Channel</strong>: Added a channel that includes Nvidia drivers.</li>
|
||||||
<li><strong>Adding Nvidia Channel</strong>: Added a channel that includes Nvidia drivers.</li>
|
<li><strong>Installing Drivers</strong>: Installed the drivers using <code>guix package -i nvidia-driver</code>.</li>
|
||||||
<li><strong>Installing Drivers</strong>: Installed the drivers using <code>guix package -i nvidia-driver</code>.</li>
|
<li><strong>Configuring the System</strong>: I had to manually configure Xorg to use the Nvidia drivers, which involved editing the Xorg configuration files.</li>
|
||||||
<li><strong>Configuring the System</strong>: I had to manually configure Xorg to use the Nvidia drivers, which involved editing the Xorg configuration files.</li>
|
</ol>
|
||||||
</ol>
|
<h2>Creating My Home Environment</h2>
|
||||||
<h2>Creating My Home Environment</h2>
|
<p>To personalize my setup further, I used <code>guix home import</code> to create my own home environment and add packages. This allowed me to have a consistent environment across different machines. I also edited the <code>config.scm</code> file to include the latest Linux kernels and Nvidia drivers.</p>
|
||||||
<p>To personalize my setup further, I used <code>guix home import</code> to create my own home environment and add packages. This allowed me to have a consistent environment across different machines. I also edited the <code>config.scm</code> file to include the latest Linux kernels and Nvidia drivers.</p>
|
<p>Additionally, I used the <code>syncthing home-service-type</code> in my <code>home-configuration.scm</code> file to install and configure Syncthing. This setup ensured my files were always in sync across devices, which is crucial for my workflow.</p>
|
||||||
<p>Additionally, I used the <code>syncthing home-service-type</code> in my <code>home-configuration.scm</code> file to install and configure Syncthing. This setup ensured my files were always in sync across devices, which is crucial for my workflow.</p>
|
<h2>GNOME</h2>
|
||||||
<h2>GNOME</h2>
|
<p>All was good and I had a solid desktop environment running, even though it was gnome desktop. I had never used gnome, and I am more at home with a keyboard driven workflow. I had come from hyprland on Arch and wanted to get back to that workflow. The option I was presented with, in order to continue using wayland, pipewire etc. was SwayWM.</p>
|
||||||
<p>All was good and I had a solid desktop environment running, even though it was gnome desktop. I had never used gnome, and I am more at home with a keyboard driven workflow. I had come from hyprland on Arch and wanted to get back to that workflow. The option I was presented with, in order to continue using wayland, pipewire etc. was SwayWM.</p>
|
<h2>Sway</h2>
|
||||||
<h2>Sway</h2>
|
<p>Installing SwayWM and it's dependencies and nice to haves was relatively straightforward. add the required packages, sway, swaybg, swayidle, swaylock, to my home-configuration.scm gile and run <code>guix home reconfigure</code> easy! The packages were installed and we were good to go.</p>
|
||||||
<p>Installing SwayWM and it's dependencies and nice to haves was relatively straightforward. add the required packages, sway, swaybg, swayidle, swaylock, to my home-configuration.scm gile and run <code>guix home reconfigure</code> easy! The packages were installed and we were good to go.</p>
|
<p>The first issue I encountered was that sway does not run with the proprietary nvidia drivers, this was on the work laptop. I could get it to run but only after adding the <code>--unsupported-gpu</code> flag to <code>exec sway</code>. Lo and behold, we had a default sway window manager running.</p>
|
||||||
<p>The first issue I encountered was that sway does not run with the proprietary nvidia drivers, this was on the work laptop. I could get it to run but only after adding the <code>--unsupported-gpu</code> flag to <code>exec sway</code>. Lo and behold, we had a default sway window manager running.</p>
|
<h2>Challenges with SwayWM and SMB Shares</h2>
|
||||||
<h2>Challenges with SwayWM and SMB Shares</h2>
|
<p>With the system set up, I ran into a major roadblock: accessing SMB shares in a file manager while running SwayWM.</p>
|
||||||
<p>With the system set up, I ran into a major roadblock: accessing SMB shares in a file manager while running SwayWM.</p>
|
<ol>
|
||||||
<ol>
|
<li><strong>Thunar and GNOME Files</strong>: Neither Thunar nor the GNOME Files application could access SMB shares. This was crucial for my workflow as I frequently access network shares.</li>
|
||||||
<li><strong>Thunar and GNOME Files</strong>: Neither Thunar nor the GNOME Files application could access SMB shares. This was crucial for my workflow as I frequently access network shares.</li>
|
<li><strong>Troubleshooting</strong>: I tried various solutions, including installing additional packages and tweaking configurations, but nothing seemed to work.</li>
|
||||||
<li><strong>Troubleshooting</strong>: I tried various solutions, including installing additional packages and tweaking configurations, but nothing seemed to work.</li>
|
<li><strong>Community Support</strong>: I reached out to the GNU Guix community for help. While they were supportive, the solutions provided didn't resolve my issues.</li>
|
||||||
<li><strong>Community Support</strong>: I reached out to the GNU Guix community for help. While they were supportive, the solutions provided didn't resolve my issues.</li>
|
</ol>
|
||||||
</ol>
|
<p>To ensure that the problem was not hardware-related, I went out and purchased a Lenovo ThinkPad E16 Gen 1. I upgraded the RAM to 48GB and installed a Lenovo 2TB SSD to make it my personal laptop. However, even on this new setup, I faced the same issues accessing SMB shares and some networking services just wouldn't work.</p>
|
||||||
<p>To ensure that the problem was not hardware-related, I went out and purchased a Lenovo ThinkPad E16 Gen 1. I upgraded the RAM to 48GB and installed a Lenovo 2TB SSD to make it my personal laptop. However, even on this new setup, I faced the same issues accessing SMB shares and some networking services just wouldn't work.</p>
|
<p>I tried deleting the <code>gdm</code> login manager in my system configuration file, but after rebooting it was still showing the gnome login window. This was after reading somewhere online that sway was not on friendly terms with the gdm login manager.</p>
|
||||||
<p>I tried deleting the <code>gdm</code> login manager in my system configuration file, but after rebooting it was still showing the gnome login window. This was after reading somewhere online that sway was not on friendly terms with the gdm login manager.</p>
|
<h2>Returning to Arch Linux</h2>
|
||||||
<h2>Returning to Arch Linux</h2>
|
<p>After several days of troubleshooting and not being able to access my SMB shares reliably, I made the difficult decision to revert to Arch Linux. The steps were:</p>
|
||||||
<p>After several days of troubleshooting and not being able to access my SMB shares reliably, I made the difficult decision to revert to Arch Linux. The steps were:</p>
|
<ol>
|
||||||
<ol>
|
<li><strong>Reinstalling Arch</strong>: I reinstalled Arch Linux using my tried-and-tested setup process.</li>
|
||||||
<li><strong>Reinstalling Arch</strong>: I reinstalled Arch Linux using my tried-and-tested setup process.</li>
|
<li><strong>Configuring SwayWM</strong>: Set up SwayWM and ensured all my applications were running smoothly.</li>
|
||||||
<li><strong>Configuring SwayWM</strong>: Set up SwayWM and ensured all my applications were running smoothly.</li>
|
<li><strong>Accessing SMB Shares</strong>: Accessing SMB shares was seamless, just as it was before my experiment with GNU Guix.</li>
|
||||||
<li><strong>Accessing SMB Shares</strong>: Accessing SMB shares was seamless, just as it was before my experiment with GNU Guix.</li>
|
</ol>
|
||||||
</ol>
|
<h2>Conclusion</h2>
|
||||||
<h2>Conclusion</h2>
|
<p>I am still running GNU guix on the work laptop, I had to cave on my personal laptop and revert to Arch. My journey with GNU Guix was both enlightening and challenging. While I appreciate the functional package management and the philosophy behind GNU Guix, certain practical issues, like accessing SMB shares, were deal-breakers for my workflow. Arch Linux continues to be my go-to distribution, providing the flexibility and reliability I need for my daily tasks. So, at the moment I am using my personal laptop for work and still trying to figure out the issues I am having on my work laptop. But, to be honest, I prefer working on the thinkpad over working on the MSI laptop that work handed out :).</p>
|
||||||
<p>I am still running GNU guix on the work laptop, I had to cave on my personal laptop and revert to Arch. My journey with GNU Guix was both enlightening and challenging. While I appreciate the functional package management and the philosophy behind GNU Guix, certain practical issues, like accessing SMB shares, were deal-breakers for my workflow. Arch Linux continues to be my go-to distribution, providing the flexibility and reliability I need for my daily tasks. So, at the moment I am using my personal laptop for work and still trying to figure out the issues I am having on my work laptop. But, to be honest, I prefer working on the thinkpad over working on the MSI laptop that work handed out :).</p>
|
<p>If you're an enthusiast looking to explore new package management paradigms, I highly recommend giving GNU Guix a try. Just be prepared for a few hiccups along the way, and always have a backup plan!</p>
|
||||||
<p>If you're an enthusiast looking to explore new package management paradigms, I highly recommend giving GNU Guix a try. Just be prepared for a few hiccups along the way, and always have a backup plan!</p>
|
<hr>
|
||||||
<hr>
|
<p>Feel free to share your thoughts and experiences with GNU Guix or any other distributions you've tried. Let's keep the conversation going!</p>
|
||||||
<p>Feel free to share your thoughts and experiences with GNU Guix or any other distributions you've tried. Let's keep the conversation going!</p>
|
<h2>Shameless plug</h2>
|
||||||
<h2>Shameless plug</h2>
|
<p>Go <a href="https://systemcrafters.net/community/">here</a> to find all the ways you can engage with the SystemCrafters community. It's a great place to hang out and discuss all thing craftery. You will also notice the Craftering ring that I am a part of. Click the links and see blogs by some of the community members. Always interesting to read what other Crafters are up to.</p>
|
||||||
<p>Go <a href="https://systemcrafters.net/community/">here</a> to find all the ways you can engage with the SystemCrafters community. It's a great place to hang out and discuss all thing craftery. You will also notice the Craftering ring that I am a part of. Click the links and see blogs by some of the community members. Always interesting to read what other Crafters are up to.</p>
|
<p>Thanks for taking the time to read my blog post. It is greatly appreciated, and I hope you come back.</p>
|
||||||
<p>Thanks for taking the time to read my blog post. It is greatly appreciated, and I hope you come back.</p>
|
<p>Happy Hacking!!</p>
|
||||||
<p>Happy Hacking!!</p>
|
|
||||||
|
</article>
|
||||||
</article>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</main>
|
||||||
</main>
|
<footer class="bg-base-darker text-palenight-200 py-12 border-t border-palenight-400/20">
|
||||||
<footer class="bg-base-darker text-palenight-200 py-12 border-t border-palenight-400/20">
|
<div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
<div class="text-center">
|
||||||
<div class="text-center">
|
<p class="text-palenight-300">© 2026 Glenn Thompson. All rights reserved.</p>
|
||||||
<p class="text-palenight-300">© 2024 Glenn Thompson. All rights reserved.</p>
|
<div class="webring-text mt-6">
|
||||||
<div class="webring-text mt-6">
|
<p class="text-palenight-300">I am part of the <a href="https://systemcrafters.net" target="_blank" class="text-accent-blue hover:text-accent-cyan">System Crafters</a> webring:</p>
|
||||||
<p class="text-palenight-300">I am part of the <a href="https://systemcrafters.net" target="_blank" class="text-accent-blue hover:text-accent-cyan">System Crafters</a> webring:</p>
|
</div>
|
||||||
</div>
|
<div class="craftering mt-2 flex items-center justify-center gap-4 text-accent-blue">
|
||||||
<div class="craftering mt-2 flex items-center justify-center gap-4 text-accent-blue">
|
<a href="https://craftering.systemcrafters.net/@glenneth/previous" class="hover:text-accent-cyan">Previous</a>
|
||||||
<a href="https://craftering.systemcrafters.net/@glenneth/previous" class="hover:text-accent-cyan">Previous</a>
|
<a href="https://craftering.systemcrafters.net/@glenneth" class="hover:text-accent-cyan">Random</a>
|
||||||
<a href="https://craftering.systemcrafters.net/@glenneth" class="hover:text-accent-cyan">Random</a>
|
<a href="https://craftering.systemcrafters.net/@glenneth/next" class="hover:text-accent-cyan">Next</a>
|
||||||
<a href="https://craftering.systemcrafters.net/@glenneth/next" class="hover:text-accent-cyan">Next</a>
|
</div>
|
||||||
</div>
|
<p class="text-palenight-300 mt-2">
|
||||||
<p class="text-palenight-300 mt-2">
|
<a href="mailto:glenn@glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenn@glenneth.org</a> |
|
||||||
<a href="mailto:glenn@glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenn@glenneth.org</a> |
|
<a href="https://glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenneth.org</a>
|
||||||
<a href="https://glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenneth.org</a>
|
</p>
|
||||||
</p>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</footer>
|
||||||
</footer>
|
</body>
|
||||||
</body>
|
|
||||||
</html>
|
</html>
|
||||||
|
|
@ -1,188 +1,187 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en" class="bg-base-bg">
|
<html lang="en" class="bg-base-bg">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<meta name="description" content="">
|
<meta name="description" content="">
|
||||||
<meta property="og:title" content="A Journey into Scheme">
|
<meta property="og:title" content="Blog Post">
|
||||||
<meta property="og:description" content="">
|
<meta property="og:description" content="">
|
||||||
<meta property="og:url" content="https://glenneth.orgcontent/posts/2024-09-24-scheme-journey">
|
<meta property="og:url" content="https://glenneth.orgcontent/posts/2024-09-24-scheme-journey">
|
||||||
<title>A Journey into Scheme - Glenn Thompson</title>
|
<title>Blog Post - Glenn Thompson</title>
|
||||||
<link rel="alternate" type="application/rss+xml" title="Glenn Thompson's Blog" href="/feed.xml" />
|
<link rel="alternate" type="application/rss+xml" title="Glenn Thompson's Blog" href="/feed.xml" />
|
||||||
<link href="../../dist/styles.css" rel="stylesheet">
|
<link href="/dist/styles.css" rel="stylesheet">
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Merriweather:wght@400;700&family=JetBrains+Mono:wght@400;700&display=swap" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Merriweather:wght@400;700&family=JetBrains+Mono:wght@400;700&display=swap" rel="stylesheet">
|
||||||
<style>
|
<style>
|
||||||
.prose-palenight {
|
.prose-palenight {
|
||||||
--tw-prose-body: #bfc7d5;
|
--tw-prose-body: #bfc7d5;
|
||||||
--tw-prose-headings: #ffd580;
|
--tw-prose-headings: #ffd580;
|
||||||
--tw-prose-links: #82aaff;
|
--tw-prose-links: #82aaff;
|
||||||
--tw-prose-code: #c792ea;
|
--tw-prose-code: #c792ea;
|
||||||
--tw-prose-pre-bg: #1b1e2b;
|
--tw-prose-pre-bg: #1b1e2b;
|
||||||
}
|
}
|
||||||
.prose h2 {
|
.prose h2 {
|
||||||
color: var(--tw-prose-headings);
|
color: var(--tw-prose-headings);
|
||||||
font-family: Merriweather, serif;
|
font-family: Merriweather, serif;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
font-size: 1.5rem;
|
font-size: 1.5rem;
|
||||||
margin-top: 2rem;
|
margin-top: 2rem;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
}
|
}
|
||||||
.prose p {
|
.prose p {
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
line-height: 1.625;
|
line-height: 1.625;
|
||||||
}
|
}
|
||||||
.prose a {
|
.prose a {
|
||||||
color: var(--tw-prose-links);
|
color: var(--tw-prose-links);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
.prose a:hover {
|
.prose a:hover {
|
||||||
color: #89ddff;
|
color: #89ddff;
|
||||||
}
|
}
|
||||||
.prose code {
|
.prose code {
|
||||||
color: var(--tw-prose-code);
|
color: var(--tw-prose-code);
|
||||||
font-family: 'JetBrains Mono', monospace;
|
font-family: 'JetBrains Mono', monospace;
|
||||||
}
|
}
|
||||||
.prose pre {
|
.prose pre {
|
||||||
background-color: var(--tw-prose-pre-bg);
|
background-color: var(--tw-prose-pre-bg);
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
}
|
}
|
||||||
.prose ul, .prose ol {
|
.prose ul, .prose ol {
|
||||||
margin-top: 0.5rem;
|
margin-top: 0.5rem;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
padding-left: 1.5rem;
|
padding-left: 1.5rem;
|
||||||
}
|
}
|
||||||
.prose ul {
|
.prose ul {
|
||||||
list-style-type: disc;
|
list-style-type: disc;
|
||||||
}
|
}
|
||||||
.prose ol {
|
.prose ol {
|
||||||
list-style-type: decimal;
|
list-style-type: decimal;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body class="bg-base-bg text-palenight-50">
|
<body class="bg-base-bg text-palenight-50">
|
||||||
<nav class="bg-base-darker/80 backdrop-blur-sm shadow-sm border-b border-palenight-400/20 mb-8">
|
<nav class="bg-base-darker/80 backdrop-blur-sm shadow-sm border-b border-palenight-400/20 mb-8">
|
||||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<div class="flex items-center justify-between h-16">
|
<div class="flex items-center justify-between h-16">
|
||||||
<a href="/" class="text-accent-yellow font-serif text-xl font-bold">Glenn Thompson</a>
|
<a href="/" class="text-accent-yellow font-serif text-xl font-bold">Glenn Thompson</a>
|
||||||
<div class="flex items-center gap-2 text-accent-yellow text-sm font-bold">
|
<div class="flex items-center gap-2 text-accent-yellow text-sm font-bold">
|
||||||
<span>personal, tech, guile, scheme, gnu, development</span>
|
<span>Tech</span>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<time datetime="2024-09-24 09:30">September 24, 2024</time>
|
<time datetime="undefined">Invalid Date</time>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<span>5 min read</span>
|
<span>5 min read</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<main class="pt-24 pb-16 px-4">
|
<main class="pt-24 pb-16 px-4">
|
||||||
<div class="max-w-4xl mx-auto">
|
<div class="max-w-4xl mx-auto">
|
||||||
<div class="content text-palenight-100 space-y-6">
|
<div class="content text-palenight-100 space-y-6">
|
||||||
<header class="mb-8">
|
<header class="mb-8">
|
||||||
<h1 class="text-4xl font-serif font-bold text-accent-yellow">A Journey into Scheme</h1>
|
<h1 class="text-4xl font-serif font-bold text-accent-yellow">Blog Post</h1>
|
||||||
<div class="flex items-center gap-4 text-palenight-300 mt-4">
|
<div class="flex items-center gap-4 text-palenight-300 mt-4">
|
||||||
<time datetime="2024-09-24 09:30">2024-09-24 09:30</time>
|
<time datetime=""></time>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<span>5 min read</span>
|
<span>5 min read</span>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<span>By Glenn Thompson</span>
|
<span>By Glenn Thompson</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-wrap gap-2 mt-4">
|
</header>
|
||||||
<span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">personal</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">tech</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">guile</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">scheme</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">gnu</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">development</span>
|
|
||||||
</div>
|
<article class="prose prose-palenight max-w-none">
|
||||||
</header>
|
<hr>
|
||||||
|
<h2>title: A Journey into Scheme<br>author: Glenn Thompson<br>date: 2024-09-24 09:30<br>tags: personal, tech, guile, scheme, gnu, development</h2>
|
||||||
<article class="prose prose-palenight max-w-none">
|
<h1>My Journey into Scheme: Building a Simple Symlink Manager with Guile Scheme</h1>
|
||||||
<h1>My Journey into Scheme: Building a Simple Symlink Manager with Guile Scheme</h1>
|
<h2>Introduction</h2>
|
||||||
<h2>Introduction</h2>
|
<p>I've spent my career as an electrical engineer, not a software developer. However, my recent journey in to GNU/Liniux required a tool for managing symlinks, and that's how I began learning Scheme—specifically Guile Scheme. I'm writing this post to share how I built <code>stash</code>, a utility that mimics GNU Stow's functionality, and how my learning journey was shaped by David Wilson's "Hands-On Guile Scheme for Beginners" course from System Crafters, more about this below.</p>
|
||||||
<p>I've spent my career as an electrical engineer, not a software developer. However, my recent journey in to GNU/Liniux required a tool for managing symlinks, and that's how I began learning Scheme—specifically Guile Scheme. I'm writing this post to share how I built <code>stash</code>, a utility that mimics GNU Stow's functionality, and how my learning journey was shaped by David Wilson's "Hands-On Guile Scheme for Beginners" course from System Crafters, more about this below.</p>
|
<h2>How I Started with Scheme</h2>
|
||||||
<h2>How I Started with Scheme</h2>
|
<p>My programming background was <em>VERY</em> limited, I produce documents in (La)Tex but I decided to take the plunge into learning Scheme, thanks to a course led by David Wilson from System Crafters. The course, <a href="https://systemcrafters.net/courses/hands-on-guile-scheme-beginners/">"Hands-On Guile Scheme for Beginners"</a>, was incredibly helpful in making Scheme accessible even for someone like me, without a traditional programming background. I know (La)Tex isn't a programming language, it's typesetting. But how hard can it be? Right?</p>
|
||||||
<p>My programming background was <em>VERY</em> limited, I produce documents in (La)Tex but I decided to take the plunge into learning Scheme, thanks to a course led by David Wilson from System Crafters. The course, <a href="https://systemcrafters.net/courses/hands-on-guile-scheme-beginners/">"Hands-On Guile Scheme for Beginners"</a>, was incredibly helpful in making Scheme accessible even for someone like me, without a traditional programming background. I know (La)Tex isn't a programming language, it's typesetting. But how hard can it be? Right?</p>
|
<p>The course took me through the basics of Scheme, from simple expressions to more complex concepts like functions, recursion, and working with files. This structured learning environment gave me the confidence to start building <code>stash</code>.</p>
|
||||||
<p>The course took me through the basics of Scheme, from simple expressions to more complex concepts like functions, recursion, and working with files. This structured learning environment gave me the confidence to start building <code>stash</code>.</p>
|
<p>The course was "instructor-led" with live meet-up sessions weekly. David has since made this course on-demand, and will be, if not already, available at the above link. Highly recommended if you are interested in taking your first steps with scheme.</p>
|
||||||
<p>The course was "instructor-led" with live meet-up sessions weekly. David has since made this course on-demand, and will be, if not already, available at the above link. Highly recommended if you are interested in taking your first steps with scheme.</p>
|
<h2>Why Build Stash?</h2>
|
||||||
<h2>Why Build Stash?</h2>
|
<p>After completing David Wilson's course, I wanted to put my newly found Guile Scheme skills into practice with a real project. It wasn't enough just to understand the language conceptually—I needed to build something tangible that solved a problem I encountered regularly in my workflow. Writing <code>stash</code> gave me that opportunity. It allowed me to apply what I'd learned while also deepening my understanding of file manipulation, command-line tools, and conflict resolution—all within the Guile Scheme environment.</p>
|
||||||
<p>After completing David Wilson's course, I wanted to put my newly found Guile Scheme skills into practice with a real project. It wasn't enough just to understand the language conceptually—I needed to build something tangible that solved a problem I encountered regularly in my workflow. Writing <code>stash</code> gave me that opportunity. It allowed me to apply what I'd learned while also deepening my understanding of file manipulation, command-line tools, and conflict resolution—all within the Guile Scheme environment.</p>
|
<p>After migrating to GNU/Linux and speaking with other <a href="https://systemcrafters.net/community">System Crafters Community</a> members, I found I needed a way to manage symbolic links and organize directories. Existing tools like GNU Stow helped, but I wanted to learn how such tools are built. I decided to write my own version using Guile Scheme to enhance my understanding of the language and to have more control over the functionality.</p>
|
||||||
<p>After migrating to GNU/Linux and speaking with other <a href="https://systemcrafters.net/community">System Crafters Community</a> members, I found I needed a way to manage symbolic links and organize directories. Existing tools like GNU Stow helped, but I wanted to learn how such tools are built. I decided to write my own version using Guile Scheme to enhance my understanding of the language and to have more control over the functionality.</p>
|
<p>The goal of <code>stash</code> is simple: allow users to move directories and create symlinks with conflict resolution, offering options to overwrite, back up, skip, or cancel the operation.</p>
|
||||||
<p>The goal of <code>stash</code> is simple: allow users to move directories and create symlinks with conflict resolution, offering options to overwrite, back up, skip, or cancel the operation.</p>
|
<h2>Breaking Down Stash</h2>
|
||||||
<h2>Breaking Down Stash</h2>
|
<p>The core of <code>stash</code> revolves around:</p>
|
||||||
<p>The core of <code>stash</code> revolves around:</p>
|
<ol>
|
||||||
<ol>
|
<li><strong>Moving Directories</strong>: Using Scheme's file manipulation functions, I learned how to move directories and files around. </li>
|
||||||
<li><strong>Moving Directories</strong>: Using Scheme's file manipulation functions, I learned how to move directories and files around. </li>
|
<li><strong>Creating Symlinks</strong>: I implemented functions to create symlinks to the moved directories, ensuring that the original structure remains accessible.</li>
|
||||||
<li><strong>Creating Symlinks</strong>: I implemented functions to create symlinks to the moved directories, ensuring that the original structure remains accessible.</li>
|
<li><strong>Conflict Resolution</strong>: One of the key features I wanted was handling conflicts when a file or symlink already exists at the target location. This required prompting the user for input and responding accordingly (backup, overwrite, skip, or cancel).</li>
|
||||||
<li><strong>Conflict Resolution</strong>: One of the key features I wanted was handling conflicts when a file or symlink already exists at the target location. This required prompting the user for input and responding accordingly (backup, overwrite, skip, or cancel).</li>
|
</ol>
|
||||||
</ol>
|
<p>Here's an excerpt of the core functionality that handles moving a source directory and creating a symlink:</p>
|
||||||
<p>Here's an excerpt of the core functionality that handles moving a source directory and creating a symlink:</p>
|
<pre><code class="language-scheme">;;; Helper function to move source to target
|
||||||
<pre><code class="language-scheme">;;; Helper function to move source to target
|
(define (move-source-to-target source-dir target-dir)
|
||||||
(define (move-source-to-target source-dir target-dir)
|
"Move the entire source directory to the target directory."
|
||||||
"Move the entire source directory to the target directory."
|
(let* ((source-dir (expand-home source-dir))
|
||||||
(let* ((source-dir (expand-home source-dir))
|
(target-dir (expand-home target-dir))
|
||||||
(target-dir (expand-home target-dir))
|
(source-name (basename source-dir))
|
||||||
(source-name (basename source-dir))
|
(target-source-dir (string-append target-dir "/" source-name)))
|
||||||
(target-source-dir (string-append target-dir "/" source-name)))
|
(if (file-exists? target-source-dir)
|
||||||
(if (file-exists? target-source-dir)
|
;; Conflict handling here...
|
||||||
;; Conflict handling here...
|
...)
|
||||||
...)
|
(rename-file source-dir target-source-dir)
|
||||||
(rename-file source-dir target-source-dir)
|
(display (format #f "Moved ~a to ~a\n" source-dir target-source-dir))))
|
||||||
(display (format #f "Moved ~a to ~a\n" source-dir target-source-dir))))
|
</code></pre>
|
||||||
</code></pre>
|
<h2>What I Learned</h2>
|
||||||
<h2>What I Learned</h2>
|
<p>This project taught me a lot about not just Scheme, but programming in general:</p>
|
||||||
<p>This project taught me a lot about not just Scheme, but programming in general:</p>
|
<ul>
|
||||||
<ul>
|
<li><strong>File and Directory Manipulation</strong>: Scheme's file handling functions were different from what I had experienced before, but they allowed for powerful manipulation of file systems.</li>
|
||||||
<li><strong>File and Directory Manipulation</strong>: Scheme's file handling functions were different from what I had experienced before, but they allowed for powerful manipulation of file systems.</li>
|
<li><strong>Command-Line Utilities</strong>: Scheme isn't just a language for academic exercises; you can write real, useful command-line tools with it.</li>
|
||||||
<li><strong>Command-Line Utilities</strong>: Scheme isn't just a language for academic exercises; you can write real, useful command-line tools with it.</li>
|
<li><strong>Problem Solving</strong>: From parsing command-line arguments to resolving conflicts with existing files, every part of the program required careful thought and consideration of edge cases.</li>
|
||||||
<li><strong>Problem Solving</strong>: From parsing command-line arguments to resolving conflicts with existing files, every part of the program required careful thought and consideration of edge cases.</li>
|
</ul>
|
||||||
</ul>
|
<h2>Guile Scheme Support Resources</h2>
|
||||||
<h2>Guile Scheme Support Resources</h2>
|
<ol>
|
||||||
<ol>
|
<li><p><strong><a href="https://www.gnu.org/software/guile/docs/">Guile Scheme Documentation</a></strong><br>The official documentation for Guile Scheme, which includes tutorials, references, and the Guile Manual.</p>
|
||||||
<li><p><strong><a href="https://www.gnu.org/software/guile/docs/">Guile Scheme Documentation</a></strong><br>The official documentation for Guile Scheme, which includes tutorials, references, and the Guile Manual.</p>
|
</li>
|
||||||
</li>
|
<li><p><strong><a href="https://www.gnu.org/software/guile/manual/html_node/">Guile Reference Manual</a></strong><br>A comprehensive manual covering core language concepts, libraries, and functions available in Guile Scheme.</p>
|
||||||
<li><p><strong><a href="https://www.gnu.org/software/guile/manual/html_node/">Guile Reference Manual</a></strong><br>A comprehensive manual covering core language concepts, libraries, and functions available in Guile Scheme.</p>
|
</li>
|
||||||
</li>
|
<li><p><strong><a href="http://community.schemewiki.org/">Scheme Wiki</a></strong><br>A community-maintained wiki that covers various Scheme dialects, including Guile Scheme, with tutorials, guides, and general information on Scheme programming.</p>
|
||||||
<li><p><strong><a href="http://community.schemewiki.org/">Scheme Wiki</a></strong><br>A community-maintained wiki that covers various Scheme dialects, including Guile Scheme, with tutorials, guides, and general information on Scheme programming.</p>
|
</li>
|
||||||
</li>
|
<li><p><strong><a href="http://schemers.org/">Guile at Schemers.org</a></strong><br>A site dedicated to Scheme with resources, libraries, tools, and documentation for Scheme and its implementations, including Guile.</p>
|
||||||
<li><p><strong><a href="http://schemers.org/">Guile at Schemers.org</a></strong><br>A site dedicated to Scheme with resources, libraries, tools, and documentation for Scheme and its implementations, including Guile.</p>
|
</li>
|
||||||
</li>
|
<li><p><strong><a href="https://systemcrafters.net/">System Crafters</a></strong><br>Led by David Wilson, System Crafters provides tutorials and blog posts on Guile Scheme and other GNU tools.</p>
|
||||||
<li><p><strong><a href="https://systemcrafters.net/">System Crafters</a></strong><br>Led by David Wilson, System Crafters provides tutorials and blog posts on Guile Scheme and other GNU tools.</p>
|
</li>
|
||||||
</li>
|
<li><p><strong><a href="https://lists.gnu.org/mailman/listinfo/guile-user">Guile Users Mailing List</a></strong><br>Join the Guile mailing list to ask questions and engage with the Guile Scheme community.</p>
|
||||||
<li><p><strong><a href="https://lists.gnu.org/mailman/listinfo/guile-user">Guile Users Mailing List</a></strong><br>Join the Guile mailing list to ask questions and engage with the Guile Scheme community.</p>
|
</li>
|
||||||
</li>
|
<li><p><strong><a href="https://github.com/artyom-poptsov/guile-cookbook">Guile Cookbook</a></strong><br>An unofficial GitHub repository with practical code snippets and tips for Guile Scheme, covering various common use cases and tasks.</p>
|
||||||
<li><p><strong><a href="https://github.com/artyom-poptsov/guile-cookbook">Guile Cookbook</a></strong><br>An unofficial GitHub repository with practical code snippets and tips for Guile Scheme, covering various common use cases and tasks.</p>
|
</li>
|
||||||
</li>
|
<li><p><strong><a href="https://libera.chat/">#guile and #scheme on Libera Chat IRC</a></strong><br>A helpful IRC channel where you can connect with other Guile users for real-time support and advice.</p>
|
||||||
<li><p><strong><a href="https://libera.chat/">#guile and #scheme on Libera Chat IRC</a></strong><br>A helpful IRC channel where you can connect with other Guile users for real-time support and advice.</p>
|
</li>
|
||||||
</li>
|
<li><p><strong><a href="https://Libera.chat/">#systemcrafters on Libera Chat IRC</a></strong><br>A <em>SUPER</em> helpful IRC channel not only for guile and scheme, there are a huge variety of different people here. Tell them glenneth sent you.</p>
|
||||||
<li><p><strong><a href="https://Libera.chat/">#systemcrafters on Libera Chat IRC</a></strong><br>A <em>SUPER</em> helpful IRC channel not only for guile and scheme, there are a huge variety of different people here. Tell them glenneth sent you.</p>
|
</li>
|
||||||
</li>
|
</ol>
|
||||||
</ol>
|
<h2>Next Steps</h2>
|
||||||
<h2>Next Steps</h2>
|
<p>I am still refining <code>stash</code>, especially around its conflict resolution system and the way it handles symbolic links. But it's in a usable state, and I'm excited to continue iterating on it. You can check out the code <a href="https://codeberg.org/glenneth/stash">on Codeberg</a>.</p>
|
||||||
<p>I am still refining <code>stash</code>, especially around its conflict resolution system and the way it handles symbolic links. But it's in a usable state, and I'm excited to continue iterating on it. You can check out the code <a href="https://codeberg.org/glenneth/stash">on Codeberg</a>.</p>
|
<p>If you're curious about Scheme and how it can be used practically, I highly recommend checking out David Wilson's course. It's been instrumental in helping me grasp the concepts I needed to build this tool. Here's the link, again :) <a href="https://systemcrafters.net/courses/hands-on-guile-scheme-beginners/">"Hands-On Guile Scheme for Beginners"</a></p>
|
||||||
<p>If you're curious about Scheme and how it can be used practically, I highly recommend checking out David Wilson's course. It's been instrumental in helping me grasp the concepts I needed to build this tool. Here's the link, again :) <a href="https://systemcrafters.net/courses/hands-on-guile-scheme-beginners/">"Hands-On Guile Scheme for Beginners"</a></p>
|
|
||||||
|
</article>
|
||||||
</article>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</main>
|
||||||
</main>
|
<footer class="bg-base-darker text-palenight-200 py-12 border-t border-palenight-400/20">
|
||||||
<footer class="bg-base-darker text-palenight-200 py-12 border-t border-palenight-400/20">
|
<div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
<div class="text-center">
|
||||||
<div class="text-center">
|
<p class="text-palenight-300">© 2026 Glenn Thompson. All rights reserved.</p>
|
||||||
<p class="text-palenight-300">© 2024 Glenn Thompson. All rights reserved.</p>
|
<div class="webring-text mt-6">
|
||||||
<div class="webring-text mt-6">
|
<p class="text-palenight-300">I am part of the <a href="https://systemcrafters.net" target="_blank" class="text-accent-blue hover:text-accent-cyan">System Crafters</a> webring:</p>
|
||||||
<p class="text-palenight-300">I am part of the <a href="https://systemcrafters.net" target="_blank" class="text-accent-blue hover:text-accent-cyan">System Crafters</a> webring:</p>
|
</div>
|
||||||
</div>
|
<div class="craftering mt-2 flex items-center justify-center gap-4 text-accent-blue">
|
||||||
<div class="craftering mt-2 flex items-center justify-center gap-4 text-accent-blue">
|
<a href="https://craftering.systemcrafters.net/@glenneth/previous" class="hover:text-accent-cyan">Previous</a>
|
||||||
<a href="https://craftering.systemcrafters.net/@glenneth/previous" class="hover:text-accent-cyan">Previous</a>
|
<a href="https://craftering.systemcrafters.net/@glenneth" class="hover:text-accent-cyan">Random</a>
|
||||||
<a href="https://craftering.systemcrafters.net/@glenneth" class="hover:text-accent-cyan">Random</a>
|
<a href="https://craftering.systemcrafters.net/@glenneth/next" class="hover:text-accent-cyan">Next</a>
|
||||||
<a href="https://craftering.systemcrafters.net/@glenneth/next" class="hover:text-accent-cyan">Next</a>
|
</div>
|
||||||
</div>
|
<p class="text-palenight-300 mt-2">
|
||||||
<p class="text-palenight-300 mt-2">
|
<a href="mailto:glenn@glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenn@glenneth.org</a> |
|
||||||
<a href="mailto:glenn@glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenn@glenneth.org</a> |
|
<a href="https://glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenneth.org</a>
|
||||||
<a href="https://glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenneth.org</a>
|
</p>
|
||||||
</p>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</footer>
|
||||||
</footer>
|
</body>
|
||||||
</body>
|
|
||||||
</html>
|
</html>
|
||||||
|
|
@ -1,268 +1,267 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en" class="bg-base-bg">
|
<html lang="en" class="bg-base-bg">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<meta name="description" content="">
|
<meta name="description" content="">
|
||||||
<meta property="og:title" content="Beyond Theory: Building Practical Tools with Guile Scheme">
|
<meta property="og:title" content="Blog Post">
|
||||||
<meta property="og:description" content="">
|
<meta property="og:description" content="">
|
||||||
<meta property="og:url" content="https://glenneth.orgcontent/posts/2024-12-03-practical-scheme">
|
<meta property="og:url" content="https://glenneth.orgcontent/posts/2024-12-03-practical-scheme">
|
||||||
<title>Beyond Theory: Building Practical Tools with Guile Scheme - Glenn Thompson</title>
|
<title>Blog Post - Glenn Thompson</title>
|
||||||
<link rel="alternate" type="application/rss+xml" title="Glenn Thompson's Blog" href="/feed.xml" />
|
<link rel="alternate" type="application/rss+xml" title="Glenn Thompson's Blog" href="/feed.xml" />
|
||||||
<link href="../../dist/styles.css" rel="stylesheet">
|
<link href="/dist/styles.css" rel="stylesheet">
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Merriweather:wght@400;700&family=JetBrains+Mono:wght@400;700&display=swap" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Merriweather:wght@400;700&family=JetBrains+Mono:wght@400;700&display=swap" rel="stylesheet">
|
||||||
<style>
|
<style>
|
||||||
.prose-palenight {
|
.prose-palenight {
|
||||||
--tw-prose-body: #bfc7d5;
|
--tw-prose-body: #bfc7d5;
|
||||||
--tw-prose-headings: #ffd580;
|
--tw-prose-headings: #ffd580;
|
||||||
--tw-prose-links: #82aaff;
|
--tw-prose-links: #82aaff;
|
||||||
--tw-prose-code: #c792ea;
|
--tw-prose-code: #c792ea;
|
||||||
--tw-prose-pre-bg: #1b1e2b;
|
--tw-prose-pre-bg: #1b1e2b;
|
||||||
}
|
}
|
||||||
.prose h2 {
|
.prose h2 {
|
||||||
color: var(--tw-prose-headings);
|
color: var(--tw-prose-headings);
|
||||||
font-family: Merriweather, serif;
|
font-family: Merriweather, serif;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
font-size: 1.5rem;
|
font-size: 1.5rem;
|
||||||
margin-top: 2rem;
|
margin-top: 2rem;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
}
|
}
|
||||||
.prose p {
|
.prose p {
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
line-height: 1.625;
|
line-height: 1.625;
|
||||||
}
|
}
|
||||||
.prose a {
|
.prose a {
|
||||||
color: var(--tw-prose-links);
|
color: var(--tw-prose-links);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
.prose a:hover {
|
.prose a:hover {
|
||||||
color: #89ddff;
|
color: #89ddff;
|
||||||
}
|
}
|
||||||
.prose code {
|
.prose code {
|
||||||
color: var(--tw-prose-code);
|
color: var(--tw-prose-code);
|
||||||
font-family: 'JetBrains Mono', monospace;
|
font-family: 'JetBrains Mono', monospace;
|
||||||
}
|
}
|
||||||
.prose pre {
|
.prose pre {
|
||||||
background-color: var(--tw-prose-pre-bg);
|
background-color: var(--tw-prose-pre-bg);
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
}
|
}
|
||||||
.prose ul, .prose ol {
|
.prose ul, .prose ol {
|
||||||
margin-top: 0.5rem;
|
margin-top: 0.5rem;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
padding-left: 1.5rem;
|
padding-left: 1.5rem;
|
||||||
}
|
}
|
||||||
.prose ul {
|
.prose ul {
|
||||||
list-style-type: disc;
|
list-style-type: disc;
|
||||||
}
|
}
|
||||||
.prose ol {
|
.prose ol {
|
||||||
list-style-type: decimal;
|
list-style-type: decimal;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body class="bg-base-bg text-palenight-50">
|
<body class="bg-base-bg text-palenight-50">
|
||||||
<nav class="bg-base-darker/80 backdrop-blur-sm shadow-sm border-b border-palenight-400/20 mb-8">
|
<nav class="bg-base-darker/80 backdrop-blur-sm shadow-sm border-b border-palenight-400/20 mb-8">
|
||||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<div class="flex items-center justify-between h-16">
|
<div class="flex items-center justify-between h-16">
|
||||||
<a href="/" class="text-accent-yellow font-serif text-xl font-bold">Glenn Thompson</a>
|
<a href="/" class="text-accent-yellow font-serif text-xl font-bold">Glenn Thompson</a>
|
||||||
<div class="flex items-center gap-2 text-accent-yellow text-sm font-bold">
|
<div class="flex items-center gap-2 text-accent-yellow text-sm font-bold">
|
||||||
<span>tech, guile, scheme, development, functional-programming</span>
|
<span>Tech</span>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<time datetime="2024-12-03 10:00">December 3, 2024</time>
|
<time datetime="undefined">Invalid Date</time>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<span>5 min read</span>
|
<span>5 min read</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<main class="pt-24 pb-16 px-4">
|
<main class="pt-24 pb-16 px-4">
|
||||||
<div class="max-w-4xl mx-auto">
|
<div class="max-w-4xl mx-auto">
|
||||||
<div class="content text-palenight-100 space-y-6">
|
<div class="content text-palenight-100 space-y-6">
|
||||||
<header class="mb-8">
|
<header class="mb-8">
|
||||||
<h1 class="text-4xl font-serif font-bold text-accent-yellow">Beyond Theory: Building Practical Tools with Guile Scheme</h1>
|
<h1 class="text-4xl font-serif font-bold text-accent-yellow">Blog Post</h1>
|
||||||
<div class="flex items-center gap-4 text-palenight-300 mt-4">
|
<div class="flex items-center gap-4 text-palenight-300 mt-4">
|
||||||
<time datetime="2024-12-03 10:00">2024-12-03 10:00</time>
|
<time datetime=""></time>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<span>5 min read</span>
|
<span>5 min read</span>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<span>By Glenn Thompson</span>
|
<span>By Glenn Thompson</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-wrap gap-2 mt-4">
|
</header>
|
||||||
<span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">tech</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">guile</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">scheme</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">development</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">functional-programming</span>
|
|
||||||
</div>
|
<article class="prose prose-palenight max-w-none">
|
||||||
</header>
|
<hr>
|
||||||
|
<h2>title: Beyond Theory: Building Practical Tools with Guile Scheme<br>author: Glenn Thompson<br>date: 2024-12-03 10:00<br>tags: tech, guile, scheme, development, functional-programming</h2>
|
||||||
<article class="prose prose-palenight max-w-none">
|
<h1>Beyond Theory: Building Practical Tools with Guile Scheme</h1>
|
||||||
<h1>Beyond Theory: Building Practical Tools with Guile Scheme</h1>
|
<h2>Introduction</h2>
|
||||||
<h2>Introduction</h2>
|
<p>A few months ago, I shared my journey into learning Scheme through building <code>stash</code>, a symlink manager. Since then, I've discovered that the gap between learning Scheme and applying it to real-world problems is where the most valuable lessons emerge. This post explores what I've learned about building practical tools with Guile Scheme, sharing both successes and challenges along the way.</p>
|
||||||
<p>A few months ago, I shared my journey into learning Scheme through building <code>stash</code>, a symlink manager. Since then, I've discovered that the gap between learning Scheme and applying it to real-world problems is where the most valuable lessons emerge. This post explores what I've learned about building practical tools with Guile Scheme, sharing both successes and challenges along the way.</p>
|
<h2>The Power of Modular Design</h2>
|
||||||
<h2>The Power of Modular Design</h2>
|
<p>One of the most important lessons I learned was the value of modular design. Breaking down a program into focused, single-responsibility modules not only makes the code more maintainable but also helps in reasoning about the program's behavior. Here's how I structured <code>stash</code>:</p>
|
||||||
<p>One of the most important lessons I learned was the value of modular design. Breaking down a program into focused, single-responsibility modules not only makes the code more maintainable but also helps in reasoning about the program's behavior. Here's how I structured <code>stash</code>:</p>
|
<pre><code class="language-scheme">(use-modules (ice-9 getopt-long)
|
||||||
<pre><code class="language-scheme">(use-modules (ice-9 getopt-long)
|
(stash help) ;; Help module
|
||||||
(stash help) ;; Help module
|
(stash colors) ;; ANSI colors
|
||||||
(stash colors) ;; ANSI colors
|
(stash log) ;; Logging module
|
||||||
(stash log) ;; Logging module
|
(stash paths) ;; Path handling module
|
||||||
(stash paths) ;; Path handling module
|
(stash conflict) ;; Conflict resolution module
|
||||||
(stash conflict) ;; Conflict resolution module
|
(stash file-ops)) ;; File and symlink operations module
|
||||||
(stash file-ops)) ;; File and symlink operations module
|
</code></pre>
|
||||||
</code></pre>
|
<p>Each module has a specific responsibility:</p>
|
||||||
<p>Each module has a specific responsibility:</p>
|
<ul>
|
||||||
<ul>
|
<li><code>colors.scm</code>: Handles ANSI color formatting for terminal output</li>
|
||||||
<li><code>colors.scm</code>: Handles ANSI color formatting for terminal output</li>
|
<li><code>conflict.scm</code>: Manages conflict resolution when files already exist</li>
|
||||||
<li><code>conflict.scm</code>: Manages conflict resolution when files already exist</li>
|
<li><code>file-ops.scm</code>: Handles file system operations</li>
|
||||||
<li><code>file-ops.scm</code>: Handles file system operations</li>
|
<li><code>help.scm</code>: Provides usage information</li>
|
||||||
<li><code>help.scm</code>: Provides usage information</li>
|
<li><code>log.scm</code>: Manages logging operations</li>
|
||||||
<li><code>log.scm</code>: Manages logging operations</li>
|
<li><code>paths.scm</code>: Handles path manipulation and normalization</li>
|
||||||
<li><code>paths.scm</code>: Handles path manipulation and normalization</li>
|
</ul>
|
||||||
</ul>
|
<h2>Robust Path Handling</h2>
|
||||||
<h2>Robust Path Handling</h2>
|
<p>One of the first challenges in building a file management tool is handling paths correctly. Here's how I approached it:</p>
|
||||||
<p>One of the first challenges in building a file management tool is handling paths correctly. Here's how I approached it:</p>
|
<pre><code class="language-scheme">(define (expand-home path)
|
||||||
<pre><code class="language-scheme">(define (expand-home path)
|
"Expand ~ to the user's home directory."
|
||||||
"Expand ~ to the user's home directory."
|
(if (string-prefix? "~" path)
|
||||||
(if (string-prefix? "~" path)
|
(string-append (getenv "HOME") (substring path 1))
|
||||||
(string-append (getenv "HOME") (substring path 1))
|
path))
|
||||||
path))
|
|
||||||
|
(define (concat-path base path)
|
||||||
(define (concat-path base path)
|
"Concatenate two paths, ensuring there are no double slashes."
|
||||||
"Concatenate two paths, ensuring there are no double slashes."
|
(if (string-suffix? "/" base)
|
||||||
(if (string-suffix? "/" base)
|
(string-append (string-drop-right base 1) "/" path)
|
||||||
(string-append (string-drop-right base 1) "/" path)
|
(string-append base "/" path)))
|
||||||
(string-append base "/" path)))
|
|
||||||
|
(define (ensure-config-path target-dir)
|
||||||
(define (ensure-config-path target-dir)
|
"Ensure that the target directory has .config appended, avoiding double slashes."
|
||||||
"Ensure that the target directory has .config appended, avoiding double slashes."
|
(let ((target-dir (expand-home target-dir)))
|
||||||
(let ((target-dir (expand-home target-dir)))
|
(if (string-suffix? "/" target-dir)
|
||||||
(if (string-suffix? "/" target-dir)
|
(set! target-dir (string-drop-right target-dir 1)))
|
||||||
(set! target-dir (string-drop-right target-dir 1)))
|
(if (not (string-suffix? "/.config" target-dir))
|
||||||
(if (not (string-suffix? "/.config" target-dir))
|
(string-append target-dir "/.config")
|
||||||
(string-append target-dir "/.config")
|
target-dir)))
|
||||||
target-dir)))
|
</code></pre>
|
||||||
</code></pre>
|
<p>This approach ensures that:</p>
|
||||||
<p>This approach ensures that:</p>
|
<ul>
|
||||||
<ul>
|
<li>Home directory references (<code>~</code>) are properly expanded</li>
|
||||||
<li>Home directory references (<code>~</code>) are properly expanded</li>
|
<li>Path concatenation doesn't create double slashes</li>
|
||||||
<li>Path concatenation doesn't create double slashes</li>
|
<li>Configuration paths are consistently structured</li>
|
||||||
<li>Configuration paths are consistently structured</li>
|
</ul>
|
||||||
</ul>
|
<h2>Interactive Conflict Resolution</h2>
|
||||||
<h2>Interactive Conflict Resolution</h2>
|
<p>Real-world tools often need to handle conflicts. I implemented an interactive conflict resolution system:</p>
|
||||||
<p>Real-world tools often need to handle conflicts. I implemented an interactive conflict resolution system:</p>
|
<pre><code class="language-scheme">(define (prompt-user-for-action)
|
||||||
<pre><code class="language-scheme">(define (prompt-user-for-action)
|
"Prompt the user to decide how to handle a conflict: overwrite (o), skip (s), or cancel (c)."
|
||||||
"Prompt the user to decide how to handle a conflict: overwrite (o), skip (s), or cancel (c)."
|
(display (color-message
|
||||||
(display (color-message
|
"A conflict was detected. Choose action - Overwrite (o), Skip (s), or Cancel (c): "
|
||||||
"A conflict was detected. Choose action - Overwrite (o), Skip (s), or Cancel (c): "
|
yellow-text))
|
||||||
yellow-text))
|
(let ((response (read-line)))
|
||||||
(let ((response (read-line)))
|
(cond
|
||||||
(cond
|
((string-ci=? response "o") 'overwrite)
|
||||||
((string-ci=? response "o") 'overwrite)
|
((string-ci=? response "s") 'skip)
|
||||||
((string-ci=? response "s") 'skip)
|
((string-ci=? response "c") 'cancel)
|
||||||
((string-ci=? response "c") 'cancel)
|
(else
|
||||||
(else
|
(display "Invalid input. Please try again.\n")
|
||||||
(display "Invalid input. Please try again.\n")
|
(prompt-user-for-action)))))
|
||||||
(prompt-user-for-action)))))
|
</code></pre>
|
||||||
</code></pre>
|
<p>This provides a user-friendly interface for resolving conflicts while maintaining data safety.</p>
|
||||||
<p>This provides a user-friendly interface for resolving conflicts while maintaining data safety.</p>
|
<h2>Logging for Debugging and Auditing</h2>
|
||||||
<h2>Logging for Debugging and Auditing</h2>
|
<p>Proper logging is crucial for debugging and auditing. I implemented a simple but effective logging system:</p>
|
||||||
<p>Proper logging is crucial for debugging and auditing. I implemented a simple but effective logging system:</p>
|
<pre><code class="language-scheme">(define (current-timestamp)
|
||||||
<pre><code class="language-scheme">(define (current-timestamp)
|
"Return the current date and time as a formatted string."
|
||||||
"Return the current date and time as a formatted string."
|
(let* ((time (current-time))
|
||||||
(let* ((time (current-time))
|
(seconds (time-second time)))
|
||||||
(seconds (time-second time)))
|
(strftime "%Y-%m-%d-%H-%M-%S" (localtime seconds))))
|
||||||
(strftime "%Y-%m-%d-%H-%M-%S" (localtime seconds))))
|
|
||||||
|
(define (log-action message)
|
||||||
(define (log-action message)
|
"Log an action with a timestamp to the stash.log file."
|
||||||
"Log an action with a timestamp to the stash.log file."
|
(let ((log-port (open-file "stash.log" "a")))
|
||||||
(let ((log-port (open-file "stash.log" "a")))
|
(display (color-message
|
||||||
(display (color-message
|
(string-append "[" (current-timestamp) "] " message)
|
||||||
(string-append "[" (current-timestamp) "] " message)
|
green-text) log-port)
|
||||||
green-text) log-port)
|
(newline log-port)
|
||||||
(newline log-port)
|
(close-port log-port)))
|
||||||
(close-port log-port)))
|
</code></pre>
|
||||||
</code></pre>
|
<p>This logging system:</p>
|
||||||
<p>This logging system:</p>
|
<ul>
|
||||||
<ul>
|
<li>Timestamps each action</li>
|
||||||
<li>Timestamps each action</li>
|
<li>Uses color coding for better readability</li>
|
||||||
<li>Uses color coding for better readability</li>
|
<li>Maintains a persistent log file</li>
|
||||||
<li>Maintains a persistent log file</li>
|
<li>Properly handles file operations</li>
|
||||||
<li>Properly handles file operations</li>
|
</ul>
|
||||||
</ul>
|
<h2>File Operations with Safety</h2>
|
||||||
<h2>File Operations with Safety</h2>
|
<p>When dealing with file system operations, safety is paramount. Here's how I handle moving directories:</p>
|
||||||
<p>When dealing with file system operations, safety is paramount. Here's how I handle moving directories:</p>
|
<pre><code class="language-scheme">(define (move-source-to-target source-dir target-dir)
|
||||||
<pre><code class="language-scheme">(define (move-source-to-target source-dir target-dir)
|
"Move the entire source directory to the target directory, ensuring .config in the target path."
|
||||||
"Move the entire source directory to the target directory, ensuring .config in the target path."
|
(let* ((target-dir (ensure-config-path target-dir))
|
||||||
(let* ((target-dir (ensure-config-path target-dir))
|
(source-dir (expand-home source-dir))
|
||||||
(source-dir (expand-home source-dir))
|
(source-name (basename source-dir))
|
||||||
(source-name (basename source-dir))
|
(target-source-dir (concat-path target-dir source-name)))
|
||||||
(target-source-dir (concat-path target-dir source-name)))
|
(if (not (file-exists? target-dir))
|
||||||
(if (not (file-exists? target-dir))
|
(mkdir target-dir #o755))
|
||||||
(mkdir target-dir #o755))
|
(if (file-exists? target-source-dir)
|
||||||
(if (file-exists? target-source-dir)
|
(handle-conflict target-source-dir source-dir delete-directory log-action)
|
||||||
(handle-conflict target-source-dir source-dir delete-directory log-action)
|
(begin
|
||||||
(begin
|
(rename-file source-dir target-source-dir)
|
||||||
(rename-file source-dir target-source-dir)
|
(display (format #f "Moved ~a to ~a\n" source-dir target-source-dir))
|
||||||
(display (format #f "Moved ~a to ~a\n" source-dir target-source-dir))
|
(log-action (format #f "Moved ~a to ~a" source-dir target-source-dir))))
|
||||||
(log-action (format #f "Moved ~a to ~a" source-dir target-source-dir))))
|
target-source-dir))
|
||||||
target-source-dir))
|
</code></pre>
|
||||||
</code></pre>
|
<p>This implementation:</p>
|
||||||
<p>This implementation:</p>
|
<ul>
|
||||||
<ul>
|
<li>Ensures paths are properly formatted</li>
|
||||||
<li>Ensures paths are properly formatted</li>
|
<li>Creates necessary directories</li>
|
||||||
<li>Creates necessary directories</li>
|
<li>Handles conflicts gracefully</li>
|
||||||
<li>Handles conflicts gracefully</li>
|
<li>Logs all operations</li>
|
||||||
<li>Logs all operations</li>
|
<li>Returns the new path for further operations</li>
|
||||||
<li>Returns the new path for further operations</li>
|
</ul>
|
||||||
</ul>
|
<h2>Lessons Learned</h2>
|
||||||
<h2>Lessons Learned</h2>
|
<h3>What Worked Well</h3>
|
||||||
<h3>What Worked Well</h3>
|
<ol>
|
||||||
<ol>
|
<li><strong>Modular Design</strong>: Breaking the code into focused modules made it easier to maintain and test</li>
|
||||||
<li><strong>Modular Design</strong>: Breaking the code into focused modules made it easier to maintain and test</li>
|
<li><strong>Functional Approach</strong>: Using pure functions where possible made the code more predictable</li>
|
||||||
<li><strong>Functional Approach</strong>: Using pure functions where possible made the code more predictable</li>
|
<li><strong>Interactive Interface</strong>: Providing clear user prompts and colored output improved usability</li>
|
||||||
<li><strong>Interactive Interface</strong>: Providing clear user prompts and colored output improved usability</li>
|
<li><strong>Robust Logging</strong>: Detailed logging helped with debugging and understanding program flow</li>
|
||||||
<li><strong>Robust Logging</strong>: Detailed logging helped with debugging and understanding program flow</li>
|
</ol>
|
||||||
</ol>
|
<h3>Challenges Faced</h3>
|
||||||
<h3>Challenges Faced</h3>
|
<ol>
|
||||||
<ol>
|
<li><strong>Path Handling</strong>: Dealing with different path formats and edge cases required careful attention</li>
|
||||||
<li><strong>Path Handling</strong>: Dealing with different path formats and edge cases required careful attention</li>
|
<li><strong>Error States</strong>: Managing various error conditions while keeping the code clean</li>
|
||||||
<li><strong>Error States</strong>: Managing various error conditions while keeping the code clean</li>
|
<li><strong>User Interface</strong>: Balancing between automation and user control</li>
|
||||||
<li><strong>User Interface</strong>: Balancing between automation and user control</li>
|
<li><strong>Documentation</strong>: Writing clear documentation that helps users understand the tool</li>
|
||||||
<li><strong>Documentation</strong>: Writing clear documentation that helps users understand the tool</li>
|
</ol>
|
||||||
</ol>
|
<h2>Moving Forward</h2>
|
||||||
<h2>Moving Forward</h2>
|
<p>Building <code>stash</code> has taught me that while functional programming principles are valuable, pragmatism is equally important. The key is finding the right balance between elegant functional code and practical solutions.</p>
|
||||||
<p>Building <code>stash</code> has taught me that while functional programming principles are valuable, pragmatism is equally important. The key is finding the right balance between elegant functional code and practical solutions.</p>
|
<h2>Resources</h2>
|
||||||
<h2>Resources</h2>
|
<ol>
|
||||||
<ol>
|
<li><a href="https://www.gnu.org/software/guile/manual/">Guile Manual</a></li>
|
||||||
<li><a href="https://www.gnu.org/software/guile/manual/">Guile Manual</a></li>
|
<li><a href="/content/posts/scheme-journey.html">My Previous Scheme Journey Post</a></li>
|
||||||
<li><a href="/content/posts/scheme-journey.html">My Previous Scheme Journey Post</a></li>
|
<li><a href="https://systemcrafters.net/community">System Crafters Community</a></li>
|
||||||
<li><a href="https://systemcrafters.net/community">System Crafters Community</a></li>
|
<li><a href="https://codeberg.org/glenneth/stash">Stash on Codeberg</a></li>
|
||||||
<li><a href="https://codeberg.org/glenneth/stash">Stash on Codeberg</a></li>
|
</ol>
|
||||||
</ol>
|
<p>The code examples in this post are from my actual implementation of <code>stash</code>. Feel free to explore, use, and improve upon them!</p>
|
||||||
<p>The code examples in this post are from my actual implementation of <code>stash</code>. Feel free to explore, use, and improve upon them!</p>
|
|
||||||
|
</article>
|
||||||
</article>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</main>
|
||||||
</main>
|
<footer class="bg-base-darker text-palenight-200 py-12 border-t border-palenight-400/20">
|
||||||
<footer class="bg-base-darker text-palenight-200 py-12 border-t border-palenight-400/20">
|
<div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
<div class="text-center">
|
||||||
<div class="text-center">
|
<p class="text-palenight-300">© 2026 Glenn Thompson. All rights reserved.</p>
|
||||||
<p class="text-palenight-300">© 2024 Glenn Thompson. All rights reserved.</p>
|
<div class="webring-text mt-6">
|
||||||
<div class="webring-text mt-6">
|
<p class="text-palenight-300">I am part of the <a href="https://systemcrafters.net" target="_blank" class="text-accent-blue hover:text-accent-cyan">System Crafters</a> webring:</p>
|
||||||
<p class="text-palenight-300">I am part of the <a href="https://systemcrafters.net" target="_blank" class="text-accent-blue hover:text-accent-cyan">System Crafters</a> webring:</p>
|
</div>
|
||||||
</div>
|
<div class="craftering mt-2 flex items-center justify-center gap-4 text-accent-blue">
|
||||||
<div class="craftering mt-2 flex items-center justify-center gap-4 text-accent-blue">
|
<a href="https://craftering.systemcrafters.net/@glenneth/previous" class="hover:text-accent-cyan">Previous</a>
|
||||||
<a href="https://craftering.systemcrafters.net/@glenneth/previous" class="hover:text-accent-cyan">Previous</a>
|
<a href="https://craftering.systemcrafters.net/@glenneth" class="hover:text-accent-cyan">Random</a>
|
||||||
<a href="https://craftering.systemcrafters.net/@glenneth" class="hover:text-accent-cyan">Random</a>
|
<a href="https://craftering.systemcrafters.net/@glenneth/next" class="hover:text-accent-cyan">Next</a>
|
||||||
<a href="https://craftering.systemcrafters.net/@glenneth/next" class="hover:text-accent-cyan">Next</a>
|
</div>
|
||||||
</div>
|
<p class="text-palenight-300 mt-2">
|
||||||
<p class="text-palenight-300 mt-2">
|
<a href="mailto:glenn@glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenn@glenneth.org</a> |
|
||||||
<a href="mailto:glenn@glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenn@glenneth.org</a> |
|
<a href="https://glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenneth.org</a>
|
||||||
<a href="https://glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenneth.org</a>
|
</p>
|
||||||
</p>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</footer>
|
||||||
</footer>
|
</body>
|
||||||
</body>
|
|
||||||
</html>
|
</html>
|
||||||
|
|
@ -1,197 +1,196 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en" class="bg-base-bg">
|
<html lang="en" class="bg-base-bg">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<meta name="description" content="A reflection on my evolving journey through static site generators - from Hugo to Haunt, and finally to building my own custom solution, highlighting the valuable lessons learned along the way.">
|
<meta name="description" content="">
|
||||||
<meta property="og:title" content="From Hugo to Haunt to Custom: My Journey in Static Site Generation">
|
<meta property="og:title" content="Blog Post">
|
||||||
<meta property="og:description" content="A reflection on my evolving journey through static site generators - from Hugo to Haunt, and finally to building my own custom solution, highlighting the valuable lessons learned along the way.">
|
<meta property="og:description" content="">
|
||||||
<meta property="og:url" content="https://glenneth.orgcontent/posts/2025-01-02-from-haunt-to-custom">
|
<meta property="og:url" content="https://glenneth.orgcontent/posts/2025-01-02-from-haunt-to-custom">
|
||||||
<title>From Hugo to Haunt to Custom: My Journey in Static Site Generation - Glenn Thompson</title>
|
<title>Blog Post - Glenn Thompson</title>
|
||||||
<link rel="alternate" type="application/rss+xml" title="Glenn Thompson's Blog" href="/feed.xml" />
|
<link rel="alternate" type="application/rss+xml" title="Glenn Thompson's Blog" href="/feed.xml" />
|
||||||
<link href="/dist/styles.css" rel="stylesheet">
|
<link href="/dist/styles.css" rel="stylesheet">
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Merriweather:wght@400;700&family=JetBrains+Mono:wght@400;700&display=swap" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Merriweather:wght@400;700&family=JetBrains+Mono:wght@400;700&display=swap" rel="stylesheet">
|
||||||
<style>
|
<style>
|
||||||
.prose-palenight {
|
.prose-palenight {
|
||||||
--tw-prose-body: #bfc7d5;
|
--tw-prose-body: #bfc7d5;
|
||||||
--tw-prose-headings: #ffd580;
|
--tw-prose-headings: #ffd580;
|
||||||
--tw-prose-links: #82aaff;
|
--tw-prose-links: #82aaff;
|
||||||
--tw-prose-code: #c792ea;
|
--tw-prose-code: #c792ea;
|
||||||
--tw-prose-pre-bg: #1b1e2b;
|
--tw-prose-pre-bg: #1b1e2b;
|
||||||
}
|
}
|
||||||
.prose h2 {
|
.prose h2 {
|
||||||
color: var(--tw-prose-headings);
|
color: var(--tw-prose-headings);
|
||||||
font-family: Merriweather, serif;
|
font-family: Merriweather, serif;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
font-size: 1.5rem;
|
font-size: 1.5rem;
|
||||||
margin-top: 2rem;
|
margin-top: 2rem;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
}
|
}
|
||||||
.prose p {
|
.prose p {
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
line-height: 1.625;
|
line-height: 1.625;
|
||||||
}
|
}
|
||||||
.prose a {
|
.prose a {
|
||||||
color: var(--tw-prose-links);
|
color: var(--tw-prose-links);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
.prose a:hover {
|
.prose a:hover {
|
||||||
color: #89ddff;
|
color: #89ddff;
|
||||||
}
|
}
|
||||||
.prose code {
|
.prose code {
|
||||||
color: var(--tw-prose-code);
|
color: var(--tw-prose-code);
|
||||||
font-family: 'JetBrains Mono', monospace;
|
font-family: 'JetBrains Mono', monospace;
|
||||||
}
|
}
|
||||||
.prose pre {
|
.prose pre {
|
||||||
background-color: var(--tw-prose-pre-bg);
|
background-color: var(--tw-prose-pre-bg);
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
}
|
}
|
||||||
.prose ul, .prose ol {
|
.prose ul, .prose ol {
|
||||||
margin-top: 0.5rem;
|
margin-top: 0.5rem;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
padding-left: 1.5rem;
|
padding-left: 1.5rem;
|
||||||
}
|
}
|
||||||
.prose ul {
|
.prose ul {
|
||||||
list-style-type: disc;
|
list-style-type: disc;
|
||||||
}
|
}
|
||||||
.prose ol {
|
.prose ol {
|
||||||
list-style-type: decimal;
|
list-style-type: decimal;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body class="bg-base-bg text-palenight-50">
|
<body class="bg-base-bg text-palenight-50">
|
||||||
<nav class="bg-base-darker/80 backdrop-blur-sm shadow-sm border-b border-palenight-400/20 mb-8">
|
<nav class="bg-base-darker/80 backdrop-blur-sm shadow-sm border-b border-palenight-400/20 mb-8">
|
||||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<div class="flex items-center justify-between h-16">
|
<div class="flex items-center justify-between h-16">
|
||||||
<a href="/" class="text-accent-yellow font-serif text-xl font-bold">Glenn Thompson</a>
|
<a href="/" class="text-accent-yellow font-serif text-xl font-bold">Glenn Thompson</a>
|
||||||
<div class="flex items-center gap-2 text-accent-yellow text-sm font-bold">
|
<div class="flex items-center gap-2 text-accent-yellow text-sm font-bold">
|
||||||
<span>web, development, javascript, static-site, haunt, guile, hugo</span>
|
<span>Tech</span>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<time datetime="2025-01-02">January 2, 2025</time>
|
<time datetime="undefined">Invalid Date</time>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<span>4 min read</span>
|
<span>5 min read</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<main class="pt-24 pb-16 px-4">
|
<main class="pt-24 pb-16 px-4">
|
||||||
<div class="max-w-4xl mx-auto">
|
<div class="max-w-4xl mx-auto">
|
||||||
<div class="content text-palenight-100 space-y-6">
|
<div class="content text-palenight-100 space-y-6">
|
||||||
<header class="mb-8">
|
<header class="mb-8">
|
||||||
<h1 class="text-4xl font-serif font-bold text-accent-yellow">From Hugo to Haunt to Custom: My Journey in Static Site Generation</h1>
|
<h1 class="text-4xl font-serif font-bold text-accent-yellow">Blog Post</h1>
|
||||||
<div class="flex items-center gap-4 text-palenight-300 mt-4">
|
<div class="flex items-center gap-4 text-palenight-300 mt-4">
|
||||||
<time datetime="2025-01-02">2025-01-02</time>
|
<time datetime=""></time>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<span>4 min read</span>
|
<span>5 min read</span>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<span>By Glenn Thompson</span>
|
<span>By Glenn Thompson</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-wrap gap-2 mt-4">
|
</header>
|
||||||
<span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">web</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">development</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">javascript</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">static-site</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">haunt</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">guile</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">hugo</span>
|
|
||||||
</div>
|
<article class="prose prose-palenight max-w-none">
|
||||||
</header>
|
<hr>
|
||||||
|
<h2>title: From Hugo to Haunt to Custom: My Journey in Static Site Generation<br>date: 2025-01-02<br>tags: web, development, javascript, static-site, haunt, guile, hugo<br>description: A reflection on my evolving journey through static site generators - from Hugo to Haunt, and finally to building my own custom solution, highlighting the valuable lessons learned along the way.</h2>
|
||||||
<article class="prose prose-palenight max-w-none">
|
<p>My journey with static site generators has been one of continuous learning and evolution. It started with Hugo, transitioned through Haunt, and has now led me to build my own custom solution. Each step of this journey has taught me valuable lessons about web development, programming languages, and the importance of understanding the tools we use.</p>
|
||||||
<p>My journey with static site generators has been one of continuous learning and evolution. It started with Hugo, transitioned through Haunt, and has now led me to build my own custom solution. Each step of this journey has taught me valuable lessons about web development, programming languages, and the importance of understanding the tools we use.</p>
|
<h2>The Hugo Beginning</h2>
|
||||||
<h2>The Hugo Beginning</h2>
|
<p>Like many "bloggers", I started with Hugo, a popular static site generator known for its speed and extensive theme ecosystem. Hugo served its purpose well, providing a robust platform for my blog with ready-made themes and a strong community.</p>
|
||||||
<p>Like many "bloggers", I started with Hugo, a popular static site generator known for its speed and extensive theme ecosystem. Hugo served its purpose well, providing a robust platform for my blog with ready-made themes and a strong community.</p>
|
<h2>The Transition to Haunt</h2>
|
||||||
<h2>The Transition to Haunt</h2>
|
<p>My journey took an interesting turn when I joined the <a href="https://systemcrafters.net/community/">System Crafters Community</a>. Through David Wilson's excellent course, <a href="https://systemcrafters.net/courses/hands-on-guile-scheme-beginners/">Hands-On Guile Scheme for Beginners</a>, I was introduced to the world of Scheme programming. This led me to adopt GNU Guix as my operating system, which naturally led me to <a href="https://dthompson.us/projects/haunt.html">Haunt</a>, a static site generator written in Guile Scheme.</p>
|
||||||
<p>My journey took an interesting turn when I joined the <a href="https://systemcrafters.net/community/">System Crafters Community</a>. Through David Wilson's excellent course, <a href="https://systemcrafters.net/courses/hands-on-guile-scheme-beginners/">Hands-On Guile Scheme for Beginners</a>, I was introduced to the world of Scheme programming. This led me to adopt GNU Guix as my operating system, which naturally led me to <a href="https://dthompson.us/projects/haunt.html">Haunt</a>, a static site generator written in Guile Scheme.</p>
|
<p>The transition to Haunt was motivated by several factors:</p>
|
||||||
<p>The transition to Haunt was motivated by several factors:</p>
|
<ul>
|
||||||
<ul>
|
<li>Alignment with my growing interest in Scheme and functional programming</li>
|
||||||
<li>Alignment with my growing interest in Scheme and functional programming</li>
|
<li>Integration with the GNU Guix ecosystem</li>
|
||||||
<li>Integration with the GNU Guix ecosystem</li>
|
<li>The opportunity to write site configuration in Scheme</li>
|
||||||
<li>The opportunity to write site configuration in Scheme</li>
|
<li>A desire for a simpler, more controllable setup</li>
|
||||||
<li>A desire for a simpler, more controllable setup</li>
|
</ul>
|
||||||
</ul>
|
<h3>The Haunt Experience</h3>
|
||||||
<h3>The Haunt Experience</h3>
|
<p>Haunt offered a different perspective on site generation. Some highlights of my Haunt experience included:</p>
|
||||||
<p>Haunt offered a different perspective on site generation. Some highlights of my Haunt experience included:</p>
|
<ul>
|
||||||
<ul>
|
<li>Writing site configuration in Scheme, which felt natural after learning Guile</li>
|
||||||
<li>Writing site configuration in Scheme, which felt natural after learning Guile</li>
|
<li>Creating custom templates that matched my site's aesthetic needs</li>
|
||||||
<li>Creating custom templates that matched my site's aesthetic needs</li>
|
<li>Learning to leverage Scheme's flexibility for site customization</li>
|
||||||
<li>Learning to leverage Scheme's flexibility for site customization</li>
|
<li>Being part of a community that values simplicity and transparency</li>
|
||||||
<li>Being part of a community that values simplicity and transparency</li>
|
</ul>
|
||||||
</ul>
|
<p>However, working with Haunt also presented challenges:</p>
|
||||||
<p>However, working with Haunt also presented challenges:</p>
|
<ul>
|
||||||
<ul>
|
<li>Limited availability of ready-made templates</li>
|
||||||
<li>Limited availability of ready-made templates</li>
|
<li>Need to create custom solutions for common features</li>
|
||||||
<li>Need to create custom solutions for common features</li>
|
<li>Learning curve of Scheme for web development</li>
|
||||||
<li>Learning curve of Scheme for web development</li>
|
</ul>
|
||||||
</ul>
|
<h2>The Move to Custom Development</h2>
|
||||||
<h2>The Move to Custom Development</h2>
|
<p>As I became more comfortable with web development and gained a deeper understanding of static site generation, I felt ready for the next step: building my own static site generator. This decision wasn't about Haunt's limitations - it was about the desire to understand every aspect of my site's generation process and have complete control over its architecture.</p>
|
||||||
<p>As I became more comfortable with web development and gained a deeper understanding of static site generation, I felt ready for the next step: building my own static site generator. This decision wasn't about Haunt's limitations - it was about the desire to understand every aspect of my site's generation process and have complete control over its architecture.</p>
|
<h2>The New Architecture</h2>
|
||||||
<h2>The New Architecture</h2>
|
<p>My custom solution combines the lessons learned from both Hugo and Haunt with modern web development practices:</p>
|
||||||
<p>My custom solution combines the lessons learned from both Hugo and Haunt with modern web development practices:</p>
|
<ul>
|
||||||
<ul>
|
<li><strong>Modern JavaScript</strong>: Using Node.js and contemporary JavaScript tools</li>
|
||||||
<li><strong>Modern JavaScript</strong>: Using Node.js and contemporary JavaScript tools</li>
|
<li><strong>Markdown Processing</strong>: Leveraging the <code>marked</code> library for flexible content processing</li>
|
||||||
<li><strong>Markdown Processing</strong>: Leveraging the <code>marked</code> library for flexible content processing</li>
|
<li><strong>Tailwind CSS</strong>: Adopting a utility-first approach to styling</li>
|
||||||
<li><strong>Tailwind CSS</strong>: Adopting a utility-first approach to styling</li>
|
<li><strong>Simple Build Process</strong>: A straightforward build script that handles all aspects of site generation</li>
|
||||||
<li><strong>Simple Build Process</strong>: A straightforward build script that handles all aspects of site generation</li>
|
<li><strong>Development Server</strong>: Live reload functionality for immediate feedback</li>
|
||||||
<li><strong>Development Server</strong>: Live reload functionality for immediate feedback</li>
|
</ul>
|
||||||
</ul>
|
<h2>Benefits of the Custom Solution</h2>
|
||||||
<h2>Benefits of the Custom Solution</h2>
|
<p>Building my own solution has brought several advantages:</p>
|
||||||
<p>Building my own solution has brought several advantages:</p>
|
<ol>
|
||||||
<ol>
|
<li><strong>Complete Understanding</strong>: I now understand every aspect of my site's generation</li>
|
||||||
<li><strong>Complete Understanding</strong>: I now understand every aspect of my site's generation</li>
|
<li><strong>Faster Iterations</strong>: Quick implementation of new features</li>
|
||||||
<li><strong>Faster Iterations</strong>: Quick implementation of new features</li>
|
<li><strong>Modern Development</strong>: Integration with current web development tools</li>
|
||||||
<li><strong>Modern Development</strong>: Integration with current web development tools</li>
|
<li><strong>Simplified Deployment</strong>: Streamlined process for updates</li>
|
||||||
<li><strong>Simplified Deployment</strong>: Streamlined process for updates</li>
|
<li><strong>Better Performance</strong>: Only including features I actually need</li>
|
||||||
<li><strong>Better Performance</strong>: Only including features I actually need</li>
|
</ol>
|
||||||
</ol>
|
<h2>Learning Experience</h2>
|
||||||
<h2>Learning Experience</h2>
|
<p>This journey from Hugo through Haunt to a custom solution has taught me:</p>
|
||||||
<p>This journey from Hugo through Haunt to a custom solution has taught me:</p>
|
<ul>
|
||||||
<ul>
|
<li>The value of understanding different approaches to static site generation</li>
|
||||||
<li>The value of understanding different approaches to static site generation</li>
|
<li>The importance of choosing tools that align with your learning goals</li>
|
||||||
<li>The importance of choosing tools that align with your learning goals</li>
|
<li>How different programming paradigms (Go, Scheme, JavaScript) approach similar problems</li>
|
||||||
<li>How different programming paradigms (Go, Scheme, JavaScript) approach similar problems</li>
|
<li>The benefits of building your own tools when the learning opportunity outweighs convenience</li>
|
||||||
<li>The benefits of building your own tools when the learning opportunity outweighs convenience</li>
|
</ul>
|
||||||
</ul>
|
<h2>Future Improvements</h2>
|
||||||
<h2>Future Improvements</h2>
|
<p>While my custom solution meets my current needs, I'm excited about potential improvements:</p>
|
||||||
<p>While my custom solution meets my current needs, I'm excited about potential improvements:</p>
|
<ul>
|
||||||
<ul>
|
<li>Adding support for draft posts</li>
|
||||||
<li>Adding support for draft posts</li>
|
<li>Implementing a tag-based navigation system</li>
|
||||||
<li>Implementing a tag-based navigation system</li>
|
<li>Adding search functionality</li>
|
||||||
<li>Adding search functionality</li>
|
<li>Improving the build process</li>
|
||||||
<li>Improving the build process</li>
|
<li>Adding image optimization</li>
|
||||||
<li>Adding image optimization</li>
|
</ul>
|
||||||
</ul>
|
<h2>Conclusion</h2>
|
||||||
<h2>Conclusion</h2>
|
<p>My journey from Hugo through Haunt to a custom solution reflects a common pattern in software development - starting with established tools, learning their principles, and eventually building your own solutions. Each step has been valuable:</p>
|
||||||
<p>My journey from Hugo through Haunt to a custom solution reflects a common pattern in software development - starting with established tools, learning their principles, and eventually building your own solutions. Each step has been valuable:</p>
|
<ul>
|
||||||
<ul>
|
<li>Hugo taught me about static site generators and their capabilities</li>
|
||||||
<li>Hugo taught me about static site generators and their capabilities</li>
|
<li>Haunt introduced me to functional programming and the beauty of Scheme</li>
|
||||||
<li>Haunt introduced me to functional programming and the beauty of Scheme</li>
|
<li>Building my own solution has given me deep insights into web development</li>
|
||||||
<li>Building my own solution has given me deep insights into web development</li>
|
</ul>
|
||||||
</ul>
|
<p>The source code for my site generator is available on <a href="https://github.com/glenneth1/personal-website">GitHub</a>. While it may not be the most feature-rich static site generator, it's perfectly tailored to my needs and represents a significant learning journey.</p>
|
||||||
<p>The source code for my site generator is available on <a href="https://github.com/glenneth1/personal-website">GitHub</a>. While it may not be the most feature-rich static site generator, it's perfectly tailored to my needs and represents a significant learning journey.</p>
|
<p>Remember, the goal of building your own tools isn't always to create something better than existing solutions - sometimes it's about the learning experience and creating something that perfectly fits your specific needs. Whether you're using Hugo, Haunt, or considering building your own solution, the most important thing is that it serves your purposes and helps you grow.</p>
|
||||||
<p>Remember, the goal of building your own tools isn't always to create something better than existing solutions - sometimes it's about the learning experience and creating something that perfectly fits your specific needs. Whether you're using Hugo, Haunt, or considering building your own solution, the most important thing is that it serves your purposes and helps you grow.</p>
|
|
||||||
|
</article>
|
||||||
</article>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</main>
|
||||||
</main>
|
<footer class="bg-base-darker text-palenight-200 py-12 border-t border-palenight-400/20">
|
||||||
<footer class="bg-base-darker text-palenight-200 py-12 border-t border-palenight-400/20">
|
<div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
<div class="text-center">
|
||||||
<div class="text-center">
|
<p class="text-palenight-300">© 2026 Glenn Thompson. All rights reserved.</p>
|
||||||
<p class="text-palenight-300">© 2024 Glenn Thompson. All rights reserved.</p>
|
<div class="webring-text mt-6">
|
||||||
<div class="webring-text mt-6">
|
<p class="text-palenight-300">I am part of the <a href="https://systemcrafters.net" target="_blank" class="text-accent-blue hover:text-accent-cyan">System Crafters</a> webring:</p>
|
||||||
<p class="text-palenight-300">I am part of the <a href="https://systemcrafters.net" target="_blank" class="text-accent-blue hover:text-accent-cyan">System Crafters</a> webring:</p>
|
</div>
|
||||||
</div>
|
<div class="craftering mt-2 flex items-center justify-center gap-4 text-accent-blue">
|
||||||
<div class="craftering mt-2 flex items-center justify-center gap-4 text-accent-blue">
|
<a href="https://craftering.systemcrafters.net/@glenneth/previous" class="hover:text-accent-cyan">Previous</a>
|
||||||
<a href="https://craftering.systemcrafters.net/@glenneth/previous" class="hover:text-accent-cyan">Previous</a>
|
<a href="https://craftering.systemcrafters.net/@glenneth" class="hover:text-accent-cyan">Random</a>
|
||||||
<a href="https://craftering.systemcrafters.net/@glenneth" class="hover:text-accent-cyan">Random</a>
|
<a href="https://craftering.systemcrafters.net/@glenneth/next" class="hover:text-accent-cyan">Next</a>
|
||||||
<a href="https://craftering.systemcrafters.net/@glenneth/next" class="hover:text-accent-cyan">Next</a>
|
</div>
|
||||||
</div>
|
<p class="text-palenight-300 mt-2">
|
||||||
<p class="text-palenight-300 mt-2">
|
<a href="mailto:glenn@glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenn@glenneth.org</a> |
|
||||||
<a href="mailto:glenn@glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenn@glenneth.org</a> |
|
<a href="https://glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenneth.org</a>
|
||||||
<a href="https://glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenneth.org</a>
|
</p>
|
||||||
</p>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</footer>
|
||||||
</footer>
|
</body>
|
||||||
</body>
|
|
||||||
</html>
|
</html>
|
||||||
|
|
@ -1,323 +1,322 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en" class="bg-base-bg">
|
<html lang="en" class="bg-base-bg">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<meta name="description" content="A comprehensive look at my current development setup in 2025, covering everything from my GNU Guix system foundation to editor configurations, terminal tools, and deployment processes.">
|
<meta name="description" content="">
|
||||||
<meta property="og:title" content="My Development Environment in 2025: From Editor to Deployment">
|
<meta property="og:title" content="Blog Post">
|
||||||
<meta property="og:description" content="A comprehensive look at my current development setup in 2025, covering everything from my GNU Guix system foundation to editor configurations, terminal tools, and deployment processes.">
|
<meta property="og:description" content="">
|
||||||
<meta property="og:url" content="https://glenneth.orgcontent/posts/2025-03-08-my-dev-environment-2025">
|
<meta property="og:url" content="https://glenneth.orgcontent/posts/2025-03-08-my-dev-environment-2025">
|
||||||
<title>My Development Environment in 2025: From Editor to Deployment - Glenn Thompson</title>
|
<title>Blog Post - Glenn Thompson</title>
|
||||||
<link rel="alternate" type="application/rss+xml" title="Glenn Thompson's Blog" href="/feed.xml" />
|
<link rel="alternate" type="application/rss+xml" title="Glenn Thompson's Blog" href="/feed.xml" />
|
||||||
<link href="/dist/styles.css" rel="stylesheet">
|
<link href="/dist/styles.css" rel="stylesheet">
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Merriweather:wght@400;700&family=JetBrains+Mono:wght@400;700&display=swap" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Merriweather:wght@400;700&family=JetBrains+Mono:wght@400;700&display=swap" rel="stylesheet">
|
||||||
<style>
|
<style>
|
||||||
.prose-palenight {
|
.prose-palenight {
|
||||||
--tw-prose-body: #bfc7d5;
|
--tw-prose-body: #bfc7d5;
|
||||||
--tw-prose-headings: #ffd580;
|
--tw-prose-headings: #ffd580;
|
||||||
--tw-prose-links: #82aaff;
|
--tw-prose-links: #82aaff;
|
||||||
--tw-prose-code: #c792ea;
|
--tw-prose-code: #c792ea;
|
||||||
--tw-prose-pre-bg: #1b1e2b;
|
--tw-prose-pre-bg: #1b1e2b;
|
||||||
}
|
}
|
||||||
.prose h2 {
|
.prose h2 {
|
||||||
color: var(--tw-prose-headings);
|
color: var(--tw-prose-headings);
|
||||||
font-family: Merriweather, serif;
|
font-family: Merriweather, serif;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
font-size: 1.5rem;
|
font-size: 1.5rem;
|
||||||
margin-top: 2rem;
|
margin-top: 2rem;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
}
|
}
|
||||||
.prose p {
|
.prose p {
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
line-height: 1.625;
|
line-height: 1.625;
|
||||||
}
|
}
|
||||||
.prose a {
|
.prose a {
|
||||||
color: var(--tw-prose-links);
|
color: var(--tw-prose-links);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
.prose a:hover {
|
.prose a:hover {
|
||||||
color: #89ddff;
|
color: #89ddff;
|
||||||
}
|
}
|
||||||
.prose code {
|
.prose code {
|
||||||
color: var(--tw-prose-code);
|
color: var(--tw-prose-code);
|
||||||
font-family: 'JetBrains Mono', monospace;
|
font-family: 'JetBrains Mono', monospace;
|
||||||
}
|
}
|
||||||
.prose pre {
|
.prose pre {
|
||||||
background-color: var(--tw-prose-pre-bg);
|
background-color: var(--tw-prose-pre-bg);
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
}
|
}
|
||||||
.prose ul, .prose ol {
|
.prose ul, .prose ol {
|
||||||
margin-top: 0.5rem;
|
margin-top: 0.5rem;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
padding-left: 1.5rem;
|
padding-left: 1.5rem;
|
||||||
}
|
}
|
||||||
.prose ul {
|
.prose ul {
|
||||||
list-style-type: disc;
|
list-style-type: disc;
|
||||||
}
|
}
|
||||||
.prose ol {
|
.prose ol {
|
||||||
list-style-type: decimal;
|
list-style-type: decimal;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body class="bg-base-bg text-palenight-50">
|
<body class="bg-base-bg text-palenight-50">
|
||||||
<nav class="bg-base-darker/80 backdrop-blur-sm shadow-sm border-b border-palenight-400/20 mb-8">
|
<nav class="bg-base-darker/80 backdrop-blur-sm shadow-sm border-b border-palenight-400/20 mb-8">
|
||||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<div class="flex items-center justify-between h-16">
|
<div class="flex items-center justify-between h-16">
|
||||||
<a href="/" class="text-accent-yellow font-serif text-xl font-bold">Glenn Thompson</a>
|
<a href="/" class="text-accent-yellow font-serif text-xl font-bold">Glenn Thompson</a>
|
||||||
<div class="flex items-center gap-2 text-accent-yellow text-sm font-bold">
|
<div class="flex items-center gap-2 text-accent-yellow text-sm font-bold">
|
||||||
<span>development, guix, tools, workflow, productivity, web</span>
|
<span>Tech</span>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<time datetime="2025-03-08">March 8, 2025</time>
|
<time datetime="undefined">Invalid Date</time>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<span>6 min read</span>
|
<span>6 min read</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<main class="pt-24 pb-16 px-4">
|
<main class="pt-24 pb-16 px-4">
|
||||||
<div class="max-w-4xl mx-auto">
|
<div class="max-w-4xl mx-auto">
|
||||||
<div class="content text-palenight-100 space-y-6">
|
<div class="content text-palenight-100 space-y-6">
|
||||||
<header class="mb-8">
|
<header class="mb-8">
|
||||||
<h1 class="text-4xl font-serif font-bold text-accent-yellow">My Development Environment in 2025: From Editor to Deployment</h1>
|
<h1 class="text-4xl font-serif font-bold text-accent-yellow">Blog Post</h1>
|
||||||
<div class="flex items-center gap-4 text-palenight-300 mt-4">
|
<div class="flex items-center gap-4 text-palenight-300 mt-4">
|
||||||
<time datetime="2025-03-08">2025-03-08</time>
|
<time datetime=""></time>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<span>6 min read</span>
|
<span>6 min read</span>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<span>By Glenn Thompson</span>
|
<span>By Glenn Thompson</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-wrap gap-2 mt-4">
|
</header>
|
||||||
<span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">development</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">guix</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">tools</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">workflow</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">productivity</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">web</span>
|
|
||||||
</div>
|
<article class="prose prose-palenight max-w-none">
|
||||||
</header>
|
<hr>
|
||||||
|
<h2>title: My Development Environment in 2025: From Editor to Deployment<br>date: 2025-03-08<br>tags: development, guix, tools, workflow, productivity, web<br>description: A comprehensive look at my current development setup in 2025, covering everything from my GNU Guix system foundation to editor configurations, terminal tools, and deployment processes.</h2>
|
||||||
<article class="prose prose-palenight max-w-none">
|
<h2>Introduction</h2>
|
||||||
<h2>Introduction</h2>
|
<p>The tools we use shape how we work. Over the years, my development environment has evolved alongside my technical journey through different programming languages, paradigms, and projects. This post offers a snapshot of my current setup in early 2025, detailing the choices I've made and why they work for me.</p>
|
||||||
<p>The tools we use shape how we work. Over the years, my development environment has evolved alongside my technical journey through different programming languages, paradigms, and projects. This post offers a snapshot of my current setup in early 2025, detailing the choices I've made and why they work for me.</p>
|
<h2>System Foundation: ArcoLinux with GNU Guix</h2>
|
||||||
<h2>System Foundation: ArcoLinux with GNU Guix</h2>
|
<p>My journey to <a href="https://guix.gnu.org/">GNU Guix</a> began through my exploration of Scheme programming, as I detailed in my <a href="/content/posts/2024-07-26-gnu-guix-journey.html">GNU Guix Journey</a> post. While I initially experimented with Guix System, I've settled on a hybrid approach: running Guix as a package manager on top of ArcoLinux (an Arch-based distribution).</p>
|
||||||
<p>My journey to <a href="https://guix.gnu.org/">GNU Guix</a> began through my exploration of Scheme programming, as I detailed in my <a href="/content/posts/2024-07-26-gnu-guix-journey.html">GNU Guix Journey</a> post. While I initially experimented with Guix System, I've settled on a hybrid approach: running Guix as a package manager on top of ArcoLinux (an Arch-based distribution).</p>
|
<h3>Current Configuration Approach</h3>
|
||||||
<h3>Current Configuration Approach</h3>
|
<p>I manage my development environment using a combination of Arch's pacman, AUR, and Guix's declarative package management. My Guix configuration lives in a Git repository, allowing me to:</p>
|
||||||
<p>I manage my development environment using a combination of Arch's pacman, AUR, and Guix's declarative package management. My Guix configuration lives in a Git repository, allowing me to:</p>
|
<ul>
|
||||||
<ul>
|
<li>Track changes to my development environment over time</li>
|
||||||
<li>Track changes to my development environment over time</li>
|
<li>Reproduce my development setup on new hardware</li>
|
||||||
<li>Reproduce my development setup on new hardware</li>
|
<li>Roll back to previous package states when needed</li>
|
||||||
<li>Roll back to previous package states when needed</li>
|
<li>Share configuration snippets with the community</li>
|
||||||
<li>Share configuration snippets with the community</li>
|
</ul>
|
||||||
</ul>
|
<h3>Key Packages and Tools</h3>
|
||||||
<h3>Key Packages and Tools</h3>
|
<p>I maintain a hybrid package approach:</p>
|
||||||
<p>I maintain a hybrid package approach:</p>
|
<p><strong>System packages (via pacman/AUR):</strong></p>
|
||||||
<p><strong>System packages (via pacman/AUR):</strong></p>
|
<ul>
|
||||||
<ul>
|
<li>Base system utilities and desktop environment</li>
|
||||||
<li>Base system utilities and desktop environment</li>
|
<li>Graphics drivers and hardware support</li>
|
||||||
<li>Graphics drivers and hardware support</li>
|
<li>Some GUI applications</li>
|
||||||
<li>Some GUI applications</li>
|
</ul>
|
||||||
</ul>
|
<p><strong>Development tools (via Guix):</strong></p>
|
||||||
<p><strong>Development tools (via Guix):</strong></p>
|
<pre><code class="language-scheme">;; My primary development tools managed by Guix
|
||||||
<pre><code class="language-scheme">;; My primary development tools managed by Guix
|
(specifications->manifest
|
||||||
(specifications->manifest
|
'("emacs" "git" "openssh" "ripgrep" "fd" "exa" "bat"
|
||||||
'("emacs" "git" "openssh" "ripgrep" "fd" "exa" "bat"
|
"guile" "node" "python" "gcc-toolchain" "make"
|
||||||
"guile" "node" "python" "gcc-toolchain" "make"
|
"nss-certs" "glibc-locales"))
|
||||||
"nss-certs" "glibc-locales"))
|
</code></pre>
|
||||||
</code></pre>
|
<p>This hybrid approach gives me the best of both worlds: Arch's extensive package repository and up-to-date system packages, combined with Guix's reproducible development environments.</p>
|
||||||
<p>This hybrid approach gives me the best of both worlds: Arch's extensive package repository and up-to-date system packages, combined with Guix's reproducible development environments.</p>
|
<h3>Reproducibility Benefits</h3>
|
||||||
<h3>Reproducibility Benefits</h3>
|
<p>The reproducibility of Guix for development environments has been invaluable. I can:</p>
|
||||||
<p>The reproducibility of Guix for development environments has been invaluable. I can:</p>
|
<ul>
|
||||||
<ul>
|
<li>Spin up development environments with precise dependencies</li>
|
||||||
<li>Spin up development environments with precise dependencies</li>
|
<li>Ensure consistent behavior across machines</li>
|
||||||
<li>Ensure consistent behavior across machines</li>
|
<li>Isolate project-specific dependencies using Guix environments</li>
|
||||||
<li>Isolate project-specific dependencies using Guix environments</li>
|
<li>Share exact environment specifications with collaborators</li>
|
||||||
<li>Share exact environment specifications with collaborators</li>
|
</ul>
|
||||||
</ul>
|
<h3>Challenges and Solutions</h3>
|
||||||
<h3>Challenges and Solutions</h3>
|
<p>Working with this hybrid approach isn't without challenges:</p>
|
||||||
<p>Working with this hybrid approach isn't without challenges:</p>
|
<ul>
|
||||||
<ul>
|
<li><p><strong>Challenge</strong>: Keeping Guix packages in sync with system libraries<br><strong>Solution</strong>: Careful management of library paths and containerization when needed</p>
|
||||||
<li><p><strong>Challenge</strong>: Keeping Guix packages in sync with system libraries<br><strong>Solution</strong>: Careful management of library paths and containerization when needed</p>
|
</li>
|
||||||
</li>
|
<li><p><strong>Challenge</strong>: Learning curve for Guix's declarative configuration<br><strong>Solution</strong>: Incremental adoption and community resources</p>
|
||||||
<li><p><strong>Challenge</strong>: Learning curve for Guix's declarative configuration<br><strong>Solution</strong>: Incremental adoption and community resources</p>
|
</li>
|
||||||
</li>
|
<li><p><strong>Challenge</strong>: Occasional conflicts between package managers<br><strong>Solution</strong>: Clear separation of responsibilities (system vs. development tools)</p>
|
||||||
<li><p><strong>Challenge</strong>: Occasional conflicts between package managers<br><strong>Solution</strong>: Clear separation of responsibilities (system vs. development tools)</p>
|
</li>
|
||||||
</li>
|
</ul>
|
||||||
</ul>
|
<h2>Editor Environment: Emacs</h2>
|
||||||
<h2>Editor Environment: Emacs</h2>
|
<p>After experimenting with various editors, I've settled on Emacs as my primary development environment. Its extensibility and Scheme-based configuration language (Emacs Lisp) align well with my interests.</p>
|
||||||
<p>After experimenting with various editors, I've settled on Emacs as my primary development environment. Its extensibility and Scheme-based configuration language (Emacs Lisp) align well with my interests.</p>
|
<h3>Configuration Approach</h3>
|
||||||
<h3>Configuration Approach</h3>
|
<p>I use a literate configuration with Org mode, which allows me to:</p>
|
||||||
<p>I use a literate configuration with Org mode, which allows me to:</p>
|
<ul>
|
||||||
<ul>
|
<li>Document my configuration choices</li>
|
||||||
<li>Document my configuration choices</li>
|
<li>Organize settings by purpose rather than file</li>
|
||||||
<li>Organize settings by purpose rather than file</li>
|
<li>Selectively load components based on context</li>
|
||||||
<li>Selectively load components based on context</li>
|
<li>Share readable documentation with others</li>
|
||||||
<li>Share readable documentation with others</li>
|
</ul>
|
||||||
</ul>
|
<h3>Key Extensions</h3>
|
||||||
<h3>Key Extensions</h3>
|
<p>My most valuable Emacs extensions include:</p>
|
||||||
<p>My most valuable Emacs extensions include:</p>
|
<ul>
|
||||||
<ul>
|
<li><strong>Magit</strong>: Git interface that has transformed my version control workflow</li>
|
||||||
<li><strong>Magit</strong>: Git interface that has transformed my version control workflow</li>
|
<li><strong>LSP Mode</strong>: Language server integration for intelligent code assistance</li>
|
||||||
<li><strong>LSP Mode</strong>: Language server integration for intelligent code assistance</li>
|
<li><strong>Org Mode</strong>: For notes, task management, and literate programming</li>
|
||||||
<li><strong>Org Mode</strong>: For notes, task management, and literate programming</li>
|
<li><strong>Projectile</strong>: Project navigation and management</li>
|
||||||
<li><strong>Projectile</strong>: Project navigation and management</li>
|
<li><strong>Company</strong>: Completion framework</li>
|
||||||
<li><strong>Company</strong>: Completion framework</li>
|
<li><strong>Consult/Vertico/Marginalia</strong>: Modern completion UI</li>
|
||||||
<li><strong>Consult/Vertico/Marginalia</strong>: Modern completion UI</li>
|
<li><strong>Tree-sitter</strong>: Improved syntax highlighting and structural editing</li>
|
||||||
<li><strong>Tree-sitter</strong>: Improved syntax highlighting and structural editing</li>
|
</ul>
|
||||||
</ul>
|
<h3>Language-Specific Setups</h3>
|
||||||
<h3>Language-Specific Setups</h3>
|
<p>For my primary languages:</p>
|
||||||
<p>For my primary languages:</p>
|
<ul>
|
||||||
<ul>
|
<li><strong>Scheme/Guile</strong>: Geiser for REPL integration</li>
|
||||||
<li><strong>Scheme/Guile</strong>: Geiser for REPL integration</li>
|
<li><strong>JavaScript/TypeScript</strong>: TypeScript LSP, prettier, eslint integration</li>
|
||||||
<li><strong>JavaScript/TypeScript</strong>: TypeScript LSP, prettier, eslint integration</li>
|
<li><strong>Python</strong>: Pyright LSP, black formatting</li>
|
||||||
<li><strong>Python</strong>: Pyright LSP, black formatting</li>
|
<li><strong>Web Development</strong>: Web mode, emmet, css-mode</li>
|
||||||
<li><strong>Web Development</strong>: Web mode, emmet, css-mode</li>
|
</ul>
|
||||||
</ul>
|
<h3>Productivity Enhancements</h3>
|
||||||
<h3>Productivity Enhancements</h3>
|
<p>Some productivity boosters in my setup:</p>
|
||||||
<p>Some productivity boosters in my setup:</p>
|
<ul>
|
||||||
<ul>
|
<li>Custom keybindings for frequent operations</li>
|
||||||
<li>Custom keybindings for frequent operations</li>
|
<li>Snippets for common code patterns</li>
|
||||||
<li>Snippets for common code patterns</li>
|
<li>Template generation for new projects</li>
|
||||||
<li>Template generation for new projects</li>
|
<li>Integration with system notifications</li>
|
||||||
<li>Integration with system notifications</li>
|
</ul>
|
||||||
</ul>
|
<h2>Terminal and CLI Tools</h2>
|
||||||
<h2>Terminal and CLI Tools</h2>
|
<p>While Emacs handles many tasks, I still rely heavily on terminal tools for specific workflows.</p>
|
||||||
<p>While Emacs handles many tasks, I still rely heavily on terminal tools for specific workflows.</p>
|
<h3>Shell Configuration</h3>
|
||||||
<h3>Shell Configuration</h3>
|
<p>I use Zsh with a custom configuration that provides:</p>
|
||||||
<p>I use Zsh with a custom configuration that provides:</p>
|
<ul>
|
||||||
<ul>
|
<li>Intuitive aliases</li>
|
||||||
<li>Intuitive aliases</li>
|
<li>Helpful prompts with Git integration</li>
|
||||||
<li>Helpful prompts with Git integration</li>
|
<li>Command history management</li>
|
||||||
<li>Command history management</li>
|
<li>Directory navigation shortcuts</li>
|
||||||
<li>Directory navigation shortcuts</li>
|
</ul>
|
||||||
</ul>
|
<h3>Custom Scripts and Utilities</h3>
|
||||||
<h3>Custom Scripts and Utilities</h3>
|
<p>I've developed several custom scripts to streamline repetitive tasks:</p>
|
||||||
<p>I've developed several custom scripts to streamline repetitive tasks:</p>
|
<ul>
|
||||||
<ul>
|
<li>Project initialization templates</li>
|
||||||
<li>Project initialization templates</li>
|
<li>Deployment automation</li>
|
||||||
<li>Deployment automation</li>
|
<li>System maintenance routines</li>
|
||||||
<li>System maintenance routines</li>
|
<li>Content management for this blog</li>
|
||||||
<li>Content management for this blog</li>
|
</ul>
|
||||||
</ul>
|
<h3>Task Automation</h3>
|
||||||
<h3>Task Automation</h3>
|
<p>For task automation, I use a combination of:</p>
|
||||||
<p>For task automation, I use a combination of:</p>
|
<ul>
|
||||||
<ul>
|
<li>Shell scripts for simple operations</li>
|
||||||
<li>Shell scripts for simple operations</li>
|
<li>Guile scripts for more complex logic</li>
|
||||||
<li>Guile scripts for more complex logic</li>
|
<li>Make for build processes</li>
|
||||||
<li>Make for build processes</li>
|
<li>Cron for scheduled tasks</li>
|
||||||
<li>Cron for scheduled tasks</li>
|
</ul>
|
||||||
</ul>
|
<h3>Version Control Workflow</h3>
|
||||||
<h3>Version Control Workflow</h3>
|
<p>My Git workflow relies on:</p>
|
||||||
<p>My Git workflow relies on:</p>
|
<ul>
|
||||||
<ul>
|
<li>Branch-per-feature approach</li>
|
||||||
<li>Branch-per-feature approach</li>
|
<li>Interactive rebasing for clean history</li>
|
||||||
<li>Interactive rebasing for clean history</li>
|
<li>Commit message templates</li>
|
||||||
<li>Commit message templates</li>
|
<li>Hooks for quality checks</li>
|
||||||
<li>Hooks for quality checks</li>
|
</ul>
|
||||||
</ul>
|
<h2>Web Development Stack</h2>
|
||||||
<h2>Web Development Stack</h2>
|
<p>As the creator of this website, my web development setup has been refined through experience.</p>
|
||||||
<p>As the creator of this website, my web development setup has been refined through experience.</p>
|
<h3>Local Development Server</h3>
|
||||||
<h3>Local Development Server</h3>
|
<p>For local development, I use:</p>
|
||||||
<p>For local development, I use:</p>
|
<ul>
|
||||||
<ul>
|
<li>Live-server for static sites</li>
|
||||||
<li>Live-server for static sites</li>
|
<li>Custom Node.js servers for API development</li>
|
||||||
<li>Custom Node.js servers for API development</li>
|
<li>Docker containers for complex dependencies</li>
|
||||||
<li>Docker containers for complex dependencies</li>
|
</ul>
|
||||||
</ul>
|
<h3>Build Tools and Processes</h3>
|
||||||
<h3>Build Tools and Processes</h3>
|
<p>My build process typically involves:</p>
|
||||||
<p>My build process typically involves:</p>
|
<ul>
|
||||||
<ul>
|
<li>Tailwind CSS for styling</li>
|
||||||
<li>Tailwind CSS for styling</li>
|
<li>Minimal JavaScript bundling</li>
|
||||||
<li>Minimal JavaScript bundling</li>
|
<li>Custom static site generation (as detailed in my <a href="/content/posts/2025-01-02-from-haunt-to-custom.html">previous post</a>)</li>
|
||||||
<li>Custom static site generation (as detailed in my <a href="/content/posts/2025-01-02-from-haunt-to-custom.html">previous post</a>)</li>
|
<li>Automated optimization steps</li>
|
||||||
<li>Automated optimization steps</li>
|
</ul>
|
||||||
</ul>
|
<h3>Testing Approach</h3>
|
||||||
<h3>Testing Approach</h3>
|
<p>For testing, I employ:</p>
|
||||||
<p>For testing, I employ:</p>
|
<ul>
|
||||||
<ul>
|
<li>Jest for JavaScript unit tests</li>
|
||||||
<li>Jest for JavaScript unit tests</li>
|
<li>Cypress for end-to-end testing</li>
|
||||||
<li>Cypress for end-to-end testing</li>
|
<li>Manual testing across devices and browsers</li>
|
||||||
<li>Manual testing across devices and browsers</li>
|
<li>Accessibility validation tools</li>
|
||||||
<li>Accessibility validation tools</li>
|
</ul>
|
||||||
</ul>
|
<h3>Browser Tools and Extensions</h3>
|
||||||
<h3>Browser Tools and Extensions</h3>
|
<p>Essential browser tools include:</p>
|
||||||
<p>Essential browser tools include:</p>
|
<ul>
|
||||||
<ul>
|
<li>Firefox Developer Edition as my primary browser</li>
|
||||||
<li>Firefox Developer Edition as my primary browser</li>
|
<li>Chrome for cross-browser testing</li>
|
||||||
<li>Chrome for cross-browser testing</li>
|
<li>DevTools for performance analysis</li>
|
||||||
<li>DevTools for performance analysis</li>
|
<li>React and Redux DevTools</li>
|
||||||
<li>React and Redux DevTools</li>
|
<li>Accessibility checkers</li>
|
||||||
<li>Accessibility checkers</li>
|
</ul>
|
||||||
</ul>
|
<h2>Deployment Pipeline</h2>
|
||||||
<h2>Deployment Pipeline</h2>
|
<p>My approach to deployment emphasizes security and reliability.</p>
|
||||||
<p>My approach to deployment emphasizes security and reliability.</p>
|
<h3>Secure Deployment Process</h3>
|
||||||
<h3>Secure Deployment Process</h3>
|
<p>As you might have noticed from my <a href="/content/posts/2025-03-08-my-dev-environment-2025.html">.env.gpg file</a>, I take security seriously:</p>
|
||||||
<p>As you might have noticed from my <a href="/content/posts/2025-03-08-my-dev-environment-2025.html">.env.gpg file</a>, I take security seriously:</p>
|
<ul>
|
||||||
<ul>
|
<li>Credentials stored in GPG-encrypted files</li>
|
||||||
<li>Credentials stored in GPG-encrypted files</li>
|
<li>Separate development and production configurations</li>
|
||||||
<li>Separate development and production configurations</li>
|
<li>Principle of least privilege for service accounts</li>
|
||||||
<li>Principle of least privilege for service accounts</li>
|
<li>Regular security audits</li>
|
||||||
<li>Regular security audits</li>
|
</ul>
|
||||||
</ul>
|
<h3>Automation Scripts</h3>
|
||||||
<h3>Automation Scripts</h3>
|
<p>My deployment is automated through:</p>
|
||||||
<p>My deployment is automated through:</p>
|
<ul>
|
||||||
<ul>
|
<li>Custom shell scripts for build and deploy</li>
|
||||||
<li>Custom shell scripts for build and deploy</li>
|
<li>Validation steps before deployment</li>
|
||||||
<li>Validation steps before deployment</li>
|
<li>Rollback capabilities</li>
|
||||||
<li>Rollback capabilities</li>
|
<li>Notification systems for success/failure</li>
|
||||||
<li>Notification systems for success/failure</li>
|
</ul>
|
||||||
</ul>
|
<h3>CI/CD Considerations</h3>
|
||||||
<h3>CI/CD Considerations</h3>
|
<p>While not using a formal CI/CD pipeline for this personal site, I follow similar principles:</p>
|
||||||
<p>While not using a formal CI/CD pipeline for this personal site, I follow similar principles:</p>
|
<ul>
|
||||||
<ul>
|
<li>Pre-commit checks for code quality</li>
|
||||||
<li>Pre-commit checks for code quality</li>
|
<li>Automated testing before deployment</li>
|
||||||
<li>Automated testing before deployment</li>
|
<li>Consistent build environments</li>
|
||||||
<li>Consistent build environments</li>
|
<li>Deployment approval steps</li>
|
||||||
<li>Deployment approval steps</li>
|
</ul>
|
||||||
</ul>
|
<h3>Monitoring and Analytics</h3>
|
||||||
<h3>Monitoring and Analytics</h3>
|
<p>For site monitoring, I use:</p>
|
||||||
<p>For site monitoring, I use:</p>
|
<ul>
|
||||||
<ul>
|
<li>Simple analytics for privacy-respecting visitor tracking</li>
|
||||||
<li>Simple analytics for privacy-respecting visitor tracking</li>
|
<li>Uptime monitoring</li>
|
||||||
<li>Uptime monitoring</li>
|
<li>Performance metrics collection</li>
|
||||||
<li>Performance metrics collection</li>
|
<li>Error logging and alerting</li>
|
||||||
<li>Error logging and alerting</li>
|
</ul>
|
||||||
</ul>
|
<h2>Future Improvements</h2>
|
||||||
<h2>Future Improvements</h2>
|
<p>My environment continues to evolve. Areas I'm exploring include:</p>
|
||||||
<p>My environment continues to evolve. Areas I'm exploring include:</p>
|
<ul>
|
||||||
<ul>
|
<li>Further integration between Emacs and system tools</li>
|
||||||
<li>Further integration between Emacs and system tools</li>
|
<li>More comprehensive test automation</li>
|
||||||
<li>More comprehensive test automation</li>
|
<li>Expanded use of Guix channels for package management</li>
|
||||||
<li>Expanded use of Guix channels for package management</li>
|
<li>Improved mobile development workflow</li>
|
||||||
<li>Improved mobile development workflow</li>
|
</ul>
|
||||||
</ul>
|
<h2>Conclusion</h2>
|
||||||
<h2>Conclusion</h2>
|
<p>A development environment is deeply personal, reflecting both technical needs and individual preferences. Mine has evolved through years of experimentation, learning, and refinement.</p>
|
||||||
<p>A development environment is deeply personal, reflecting both technical needs and individual preferences. Mine has evolved through years of experimentation, learning, and refinement.</p>
|
<p>The most important lesson I've learned is that tools should serve your workflow, not dictate it. Be willing to experiment, but also recognize when a tool is working well enough that further optimization yields diminishing returns.</p>
|
||||||
<p>The most important lesson I've learned is that tools should serve your workflow, not dictate it. Be willing to experiment, but also recognize when a tool is working well enough that further optimization yields diminishing returns.</p>
|
<p>I hope sharing my setup provides some inspiration for your own environment. I'd love to hear about your setup and what tools have made the biggest difference in your workflow.</p>
|
||||||
<p>I hope sharing my setup provides some inspiration for your own environment. I'd love to hear about your setup and what tools have made the biggest difference in your workflow.</p>
|
<p>What aspects of your development environment have you found most valuable? Are there tools or approaches you think I should consider? Let me know!</p>
|
||||||
<p>What aspects of your development environment have you found most valuable? Are there tools or approaches you think I should consider? Let me know!</p>
|
|
||||||
|
</article>
|
||||||
</article>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</main>
|
||||||
</main>
|
<footer class="bg-base-darker text-palenight-200 py-12 border-t border-palenight-400/20">
|
||||||
<footer class="bg-base-darker text-palenight-200 py-12 border-t border-palenight-400/20">
|
<div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
<div class="text-center">
|
||||||
<div class="text-center">
|
<p class="text-palenight-300">© 2026 Glenn Thompson. All rights reserved.</p>
|
||||||
<p class="text-palenight-300">© 2024 Glenn Thompson. All rights reserved.</p>
|
<div class="webring-text mt-6">
|
||||||
<div class="webring-text mt-6">
|
<p class="text-palenight-300">I am part of the <a href="https://systemcrafters.net" target="_blank" class="text-accent-blue hover:text-accent-cyan">System Crafters</a> webring:</p>
|
||||||
<p class="text-palenight-300">I am part of the <a href="https://systemcrafters.net" target="_blank" class="text-accent-blue hover:text-accent-cyan">System Crafters</a> webring:</p>
|
</div>
|
||||||
</div>
|
<div class="craftering mt-2 flex items-center justify-center gap-4 text-accent-blue">
|
||||||
<div class="craftering mt-2 flex items-center justify-center gap-4 text-accent-blue">
|
<a href="https://craftering.systemcrafters.net/@glenneth/previous" class="hover:text-accent-cyan">Previous</a>
|
||||||
<a href="https://craftering.systemcrafters.net/@glenneth/previous" class="hover:text-accent-cyan">Previous</a>
|
<a href="https://craftering.systemcrafters.net/@glenneth" class="hover:text-accent-cyan">Random</a>
|
||||||
<a href="https://craftering.systemcrafters.net/@glenneth" class="hover:text-accent-cyan">Random</a>
|
<a href="https://craftering.systemcrafters.net/@glenneth/next" class="hover:text-accent-cyan">Next</a>
|
||||||
<a href="https://craftering.systemcrafters.net/@glenneth/next" class="hover:text-accent-cyan">Next</a>
|
</div>
|
||||||
</div>
|
<p class="text-palenight-300 mt-2">
|
||||||
<p class="text-palenight-300 mt-2">
|
<a href="mailto:glenn@glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenn@glenneth.org</a> |
|
||||||
<a href="mailto:glenn@glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenn@glenneth.org</a> |
|
<a href="https://glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenneth.org</a>
|
||||||
<a href="https://glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenneth.org</a>
|
</p>
|
||||||
</p>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</footer>
|
||||||
</footer>
|
</body>
|
||||||
</body>
|
|
||||||
</html>
|
</html>
|
||||||
|
|
@ -1,196 +1,195 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en" class="bg-base-bg">
|
<html lang="en" class="bg-base-bg">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<meta name="description" content="">
|
<meta name="description" content="">
|
||||||
<meta property="og:title" content=""Lessons Learned: One Year with a Custom Static Site Generator"">
|
<meta property="og:title" content="Blog Post">
|
||||||
<meta property="og:description" content="">
|
<meta property="og:description" content="">
|
||||||
<meta property="og:url" content="https://glenneth.orgcontent/posts/2025-03-12-lessons-learned-custom-ssg">
|
<meta property="og:url" content="https://glenneth.orgcontent/posts/2025-03-12-lessons-learned-custom-ssg">
|
||||||
<title>"Lessons Learned: One Year with a Custom Static Site Generator" - Glenn Thompson</title>
|
<title>Blog Post - Glenn Thompson</title>
|
||||||
<link rel="alternate" type="application/rss+xml" title="Glenn Thompson's Blog" href="/feed.xml" />
|
<link rel="alternate" type="application/rss+xml" title="Glenn Thompson's Blog" href="/feed.xml" />
|
||||||
<link href="/dist/styles.css" rel="stylesheet">
|
<link href="/dist/styles.css" rel="stylesheet">
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Merriweather:wght@400;700&family=JetBrains+Mono:wght@400;700&display=swap" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Merriweather:wght@400;700&family=JetBrains+Mono:wght@400;700&display=swap" rel="stylesheet">
|
||||||
<style>
|
<style>
|
||||||
.prose-palenight {
|
.prose-palenight {
|
||||||
--tw-prose-body: #bfc7d5;
|
--tw-prose-body: #bfc7d5;
|
||||||
--tw-prose-headings: #ffd580;
|
--tw-prose-headings: #ffd580;
|
||||||
--tw-prose-links: #82aaff;
|
--tw-prose-links: #82aaff;
|
||||||
--tw-prose-code: #c792ea;
|
--tw-prose-code: #c792ea;
|
||||||
--tw-prose-pre-bg: #1b1e2b;
|
--tw-prose-pre-bg: #1b1e2b;
|
||||||
}
|
}
|
||||||
.prose h2 {
|
.prose h2 {
|
||||||
color: var(--tw-prose-headings);
|
color: var(--tw-prose-headings);
|
||||||
font-family: Merriweather, serif;
|
font-family: Merriweather, serif;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
font-size: 1.5rem;
|
font-size: 1.5rem;
|
||||||
margin-top: 2rem;
|
margin-top: 2rem;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
}
|
}
|
||||||
.prose p {
|
.prose p {
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
line-height: 1.625;
|
line-height: 1.625;
|
||||||
}
|
}
|
||||||
.prose a {
|
.prose a {
|
||||||
color: var(--tw-prose-links);
|
color: var(--tw-prose-links);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
.prose a:hover {
|
.prose a:hover {
|
||||||
color: #89ddff;
|
color: #89ddff;
|
||||||
}
|
}
|
||||||
.prose code {
|
.prose code {
|
||||||
color: var(--tw-prose-code);
|
color: var(--tw-prose-code);
|
||||||
font-family: 'JetBrains Mono', monospace;
|
font-family: 'JetBrains Mono', monospace;
|
||||||
}
|
}
|
||||||
.prose pre {
|
.prose pre {
|
||||||
background-color: var(--tw-prose-pre-bg);
|
background-color: var(--tw-prose-pre-bg);
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
}
|
}
|
||||||
.prose ul, .prose ol {
|
.prose ul, .prose ol {
|
||||||
margin-top: 0.5rem;
|
margin-top: 0.5rem;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
padding-left: 1.5rem;
|
padding-left: 1.5rem;
|
||||||
}
|
}
|
||||||
.prose ul {
|
.prose ul {
|
||||||
list-style-type: disc;
|
list-style-type: disc;
|
||||||
}
|
}
|
||||||
.prose ol {
|
.prose ol {
|
||||||
list-style-type: decimal;
|
list-style-type: decimal;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body class="bg-base-bg text-palenight-50">
|
<body class="bg-base-bg text-palenight-50">
|
||||||
<nav class="bg-base-darker/80 backdrop-blur-sm shadow-sm border-b border-palenight-400/20 mb-8">
|
<nav class="bg-base-darker/80 backdrop-blur-sm shadow-sm border-b border-palenight-400/20 mb-8">
|
||||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<div class="flex items-center justify-between h-16">
|
<div class="flex items-center justify-between h-16">
|
||||||
<a href="/" class="text-accent-yellow font-serif text-xl font-bold">Glenn Thompson</a>
|
<a href="/" class="text-accent-yellow font-serif text-xl font-bold">Glenn Thompson</a>
|
||||||
<div class="flex items-center gap-2 text-accent-yellow text-sm font-bold">
|
<div class="flex items-center gap-2 text-accent-yellow text-sm font-bold">
|
||||||
<span>[web, development, javascript, static-site, lessons]</span>
|
<span>Tech</span>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<time datetime="2025-03-13">March 13, 2025</time>
|
<time datetime="undefined">Invalid Date</time>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<span>6 min read</span>
|
<span>6 min read</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<main class="pt-24 pb-16 px-4">
|
<main class="pt-24 pb-16 px-4">
|
||||||
<div class="max-w-4xl mx-auto">
|
<div class="max-w-4xl mx-auto">
|
||||||
<div class="content text-palenight-100 space-y-6">
|
<div class="content text-palenight-100 space-y-6">
|
||||||
<header class="mb-8">
|
<header class="mb-8">
|
||||||
<h1 class="text-4xl font-serif font-bold text-accent-yellow">"Lessons Learned: One Year with a Custom Static Site Generator"</h1>
|
<h1 class="text-4xl font-serif font-bold text-accent-yellow">Blog Post</h1>
|
||||||
<div class="flex items-center gap-4 text-palenight-300 mt-4">
|
<div class="flex items-center gap-4 text-palenight-300 mt-4">
|
||||||
<time datetime="2025-03-13">2025-03-13</time>
|
<time datetime=""></time>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<span>6 min read</span>
|
<span>6 min read</span>
|
||||||
<span>•</span>
|
<span>•</span>
|
||||||
<span>By Glenn Thompson</span>
|
<span>By Glenn Thompson</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-wrap gap-2 mt-4">
|
</header>
|
||||||
<span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">[web</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">development</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">javascript</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">static-site</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">lessons]</span>
|
|
||||||
</div>
|
<article class="prose prose-palenight max-w-none">
|
||||||
</header>
|
<hr>
|
||||||
|
<h2>title: "Lessons Learned: One Year with a Custom Static Site Generator"<br>date: 2025-03-13<br>tags: [web, development, javascript, static-site, lessons]</h2>
|
||||||
<article class="prose prose-palenight max-w-none">
|
<p>It's been just over a year since I <a href="/content/posts/2025-01-02-from-haunt-to-custom.html">transitioned from Haunt to my own custom static site generator</a> for this website. What started as an experiment to gain more control over my publishing workflow has evolved into a valuable learning experience that has shaped how I approach web development projects.</p>
|
||||||
<p>It's been just over a year since I <a href="/content/posts/2025-01-02-from-haunt-to-custom.html">transitioned from Haunt to my own custom static site generator</a> for this website. What started as an experiment to gain more control over my publishing workflow has evolved into a valuable learning experience that has shaped how I approach web development projects.</p>
|
<p>In this post, I'll share the key lessons I've learned and insights I've gained from building and maintaining my own static site generator. While the technical details are interesting, the real value has been in the broader lessons about software development, user experience, and the balance between complexity and simplicity.</p>
|
||||||
<p>In this post, I'll share the key lessons I've learned and insights I've gained from building and maintaining my own static site generator. While the technical details are interesting, the real value has been in the broader lessons about software development, user experience, and the balance between complexity and simplicity.</p>
|
<h2>The Journey of Evolution</h2>
|
||||||
<h2>The Journey of Evolution</h2>
|
<h3>From Simple Beginnings</h3>
|
||||||
<h3>From Simple Beginnings</h3>
|
<p>When I first built my static site generator, it was remarkably simple - just the essential features needed to convert my writing into a website. No extra features, no complex configurations, just the basics.</p>
|
||||||
<p>When I first built my static site generator, it was remarkably simple - just the essential features needed to convert my writing into a website. No extra features, no complex configurations, just the basics.</p>
|
<p>Today, the system has evolved considerably, but not through grand design or elaborate planning. Instead, it grew organically based on real needs and actual usage. This organic growth taught me valuable lessons about software development.</p>
|
||||||
<p>Today, the system has evolved considerably, but not through grand design or elaborate planning. Instead, it grew organically based on real needs and actual usage. This organic growth taught me valuable lessons about software development.</p>
|
<h3>Lesson 1: Features Should Emerge from Usage</h3>
|
||||||
<h3>Lesson 1: Features Should Emerge from Usage</h3>
|
<p>Many of the features in my static site generator emerged from actual writing and publishing needs:</p>
|
||||||
<p>Many of the features in my static site generator emerged from actual writing and publishing needs:</p>
|
<ol>
|
||||||
<ol>
|
<li><p><strong>The Draft System</strong><br>When I found myself working on multiple posts simultaneously, I needed a way to keep unfinished posts separate from published content. This led to the draft system, which now helps me manage my writing workflow effectively.</p>
|
||||||
<li><p><strong>The Draft System</strong><br>When I found myself working on multiple posts simultaneously, I needed a way to keep unfinished posts separate from published content. This led to the draft system, which now helps me manage my writing workflow effectively.</p>
|
</li>
|
||||||
</li>
|
<li><p><strong>Tag Organization</strong><br>As my collection of posts grew, I needed a way to organize related content. The tag system emerged naturally from this need, rather than being built upfront based on assumptions about how I might want to organize content.</p>
|
||||||
<li><p><strong>Tag Organization</strong><br>As my collection of posts grew, I needed a way to organize related content. The tag system emerged naturally from this need, rather than being built upfront based on assumptions about how I might want to organize content.</p>
|
</li>
|
||||||
</li>
|
<li><p><strong>Content Validation</strong><br>After accidentally publishing a post with a malformed date and another with a duplicate title, I added validation checks. These weren't part of the initial design but came from real-world publishing mishaps.</p>
|
||||||
<li><p><strong>Content Validation</strong><br>After accidentally publishing a post with a malformed date and another with a duplicate title, I added validation checks. These weren't part of the initial design but came from real-world publishing mishaps.</p>
|
</li>
|
||||||
</li>
|
</ol>
|
||||||
</ol>
|
<h3>Lesson 2: Simplicity Drives Performance</h3>
|
||||||
<h3>Lesson 2: Simplicity Drives Performance</h3>
|
<p>One of the most surprising lessons was how simplicity led to better performance:</p>
|
||||||
<p>One of the most surprising lessons was how simplicity led to better performance:</p>
|
<ol>
|
||||||
<ol>
|
<li><p><strong>Static HTML Generation</strong><br>By generating plain HTML files, the site loads quickly without any client-side processing. There's no JavaScript framework, no hydration, and no complex build process - just simple, fast HTML.</p>
|
||||||
<li><p><strong>Static HTML Generation</strong><br>By generating plain HTML files, the site loads quickly without any client-side processing. There's no JavaScript framework, no hydration, and no complex build process - just simple, fast HTML.</p>
|
</li>
|
||||||
</li>
|
<li><p><strong>Incremental Builds</strong><br>The build system only processes files that have changed. This means that even with hundreds of posts, updates are nearly instantaneous because only the necessary files are rebuilt.</p>
|
||||||
<li><p><strong>Incremental Builds</strong><br>The build system only processes files that have changed. This means that even with hundreds of posts, updates are nearly instantaneous because only the necessary files are rebuilt.</p>
|
</li>
|
||||||
</li>
|
<li><p><strong>Minimal JavaScript</strong><br>By keeping JavaScript to a minimum and focusing on progressive enhancement, the site remains fast and accessible, even on slower connections.</p>
|
||||||
<li><p><strong>Minimal JavaScript</strong><br>By keeping JavaScript to a minimum and focusing on progressive enhancement, the site remains fast and accessible, even on slower connections.</p>
|
</li>
|
||||||
</li>
|
</ol>
|
||||||
</ol>
|
<h3>Lesson 3: Developer Experience Matters</h3>
|
||||||
<h3>Lesson 3: Developer Experience Matters</h3>
|
<p>A good developer experience has proven crucial for maintaining motivation to write and publish:</p>
|
||||||
<p>A good developer experience has proven crucial for maintaining motivation to write and publish:</p>
|
<ol>
|
||||||
<ol>
|
<li><p><strong>Smart Port Management</strong><br>After encountering port conflicts with other services, I added automatic port detection and fallback. The system now checks if a port is in use and automatically finds the next available one, eliminating the frustration of manual port configuration.</p>
|
||||||
<li><p><strong>Smart Port Management</strong><br>After encountering port conflicts with other services, I added automatic port detection and fallback. The system now checks if a port is in use and automatically finds the next available one, eliminating the frustration of manual port configuration.</p>
|
</li>
|
||||||
</li>
|
<li><p><strong>Clear Error Messages</strong><br>When something goes wrong (like a failed CSS build or HTML conversion), the system provides clear, actionable error messages. This immediate feedback helps quickly identify and fix issues during the development process.</p>
|
||||||
<li><p><strong>Clear Error Messages</strong><br>When something goes wrong (like a failed CSS build or HTML conversion), the system provides clear, actionable error messages. This immediate feedback helps quickly identify and fix issues during the development process.</p>
|
</li>
|
||||||
</li>
|
<li><p><strong>Automated Validation</strong><br>The build system validates the environment before starting, checking for required directories and dependencies. These checks catch common setup issues early, making the development process smoother.</p>
|
||||||
<li><p><strong>Automated Validation</strong><br>The build system validates the environment before starting, checking for required directories and dependencies. These checks catch common setup issues early, making the development process smoother.</p>
|
</li>
|
||||||
</li>
|
</ol>
|
||||||
</ol>
|
<h3>Lesson 4: Content Drives Development</h3>
|
||||||
<h3>Lesson 4: Content Drives Development</h3>
|
<p>Perhaps the most important lesson has been letting content needs drive development:</p>
|
||||||
<p>Perhaps the most important lesson has been letting content needs drive development:</p>
|
<ol>
|
||||||
<ol>
|
<li><p><strong>Markdown Features</strong><br>I only added support for additional Markdown features (like tables and task lists) when I actually needed them in my writing. This prevented feature bloat and kept the system focused.</p>
|
||||||
<li><p><strong>Markdown Features</strong><br>I only added support for additional Markdown features (like tables and task lists) when I actually needed them in my writing. This prevented feature bloat and kept the system focused.</p>
|
</li>
|
||||||
</li>
|
<li><p><strong>RSS Feed</strong><br>The RSS feed wasn't part of the initial design but was added when the content volume grew enough to warrant it. This is a pattern I've seen repeatedly - features are most valuable when they solve real, existing needs.</p>
|
||||||
<li><p><strong>RSS Feed</strong><br>The RSS feed wasn't part of the initial design but was added when the content volume grew enough to warrant it. This is a pattern I've seen repeatedly - features are most valuable when they solve real, existing needs.</p>
|
</li>
|
||||||
</li>
|
<li><p><strong>Summary Generation</strong><br>The way post summaries are generated has evolved based on the actual content I write. Initially, it was a simple character count, but it now intelligently extracts meaningful previews based on content structure.</p>
|
||||||
<li><p><strong>Summary Generation</strong><br>The way post summaries are generated has evolved based on the actual content I write. Initially, it was a simple character count, but it now intelligently extracts meaningful previews based on content structure.</p>
|
</li>
|
||||||
</li>
|
</ol>
|
||||||
</ol>
|
<h2>Looking Forward</h2>
|
||||||
<h2>Looking Forward</h2>
|
<p>This project has taught me that the best software often evolves gradually in response to real needs rather than being built all at once from a grand design. It's a lesson that applies well beyond static site generators - it's about building software that serves actual needs rather than imagined ones.</p>
|
||||||
<p>This project has taught me that the best software often evolves gradually in response to real needs rather than being built all at once from a grand design. It's a lesson that applies well beyond static site generators - it's about building software that serves actual needs rather than imagined ones.</p>
|
<p>Just today, while writing this post, I encountered and solved several development workflow issues. Instead of being frustrated by these challenges, I saw them as opportunities to improve the system. The resulting changes - like automatic port detection and better error handling - weren't part of any grand plan. They emerged naturally from real usage and made the system better in practical, meaningful ways.</p>
|
||||||
<p>Just today, while writing this post, I encountered and solved several development workflow issues. Instead of being frustrated by these challenges, I saw them as opportunities to improve the system. The resulting changes - like automatic port detection and better error handling - weren't part of any grand plan. They emerged naturally from real usage and made the system better in practical, meaningful ways.</p>
|
<p>The system isn't perfect, and it probably never will be. But it's continuously improving in ways that matter for my writing and publishing workflow. That, I've learned, is far more valuable than technical perfection.</p>
|
||||||
<p>The system isn't perfect, and it probably never will be. But it's continuously improving in ways that matter for my writing and publishing workflow. That, I've learned, is far more valuable than technical perfection.</p>
|
<p>If you're considering building your own tools, remember:</p>
|
||||||
<p>If you're considering building your own tools, remember:</p>
|
<ol>
|
||||||
<ol>
|
<li>Start simple and let features emerge from actual usage</li>
|
||||||
<li>Start simple and let features emerge from actual usage</li>
|
<li>Focus on the experience - both for users and developers</li>
|
||||||
<li>Focus on the experience - both for users and developers</li>
|
<li>Let real needs guide development</li>
|
||||||
<li>Let real needs guide development</li>
|
<li>Embrace incremental improvements</li>
|
||||||
<li>Embrace incremental improvements</li>
|
<li>Value simplicity - it often leads to better performance and maintainability</li>
|
||||||
<li>Value simplicity - it often leads to better performance and maintainability</li>
|
<li>Use real-world problems as opportunities for improvement</li>
|
||||||
<li>Use real-world problems as opportunities for improvement</li>
|
</ol>
|
||||||
</ol>
|
<p>These lessons have influenced not just how I approach this project, but how I think about software development in general. Sometimes, the best insights come from the simplest projects - and often, they come right in the middle of writing about them.</p>
|
||||||
<p>These lessons have influenced not just how I approach this project, but how I think about software development in general. Sometimes, the best insights come from the simplest projects - and often, they come right in the middle of writing about them.</p>
|
<h2>Looking Back and Forward</h2>
|
||||||
<h2>Looking Back and Forward</h2>
|
<p>Reflecting on this journey, the most valuable insight has been understanding that great software evolves naturally from real needs. Every feature in my static site generator—from the draft system to the validation checks—emerged from actual usage rather than upfront planning.</p>
|
||||||
<p>Reflecting on this journey, the most valuable insight has been understanding that great software evolves naturally from real needs. Every feature in my static site generator—from the draft system to the validation checks—emerged from actual usage rather than upfront planning.</p>
|
<p>This experience has fundamentally changed how I approach software development. Instead of trying to build the perfect system from the start, I've learned to:</p>
|
||||||
<p>This experience has fundamentally changed how I approach software development. Instead of trying to build the perfect system from the start, I've learned to:</p>
|
<ol>
|
||||||
<ol>
|
<li>Start with the simplest solution that works</li>
|
||||||
<li>Start with the simplest solution that works</li>
|
<li>Let real usage guide feature development</li>
|
||||||
<li>Let real usage guide feature development</li>
|
<li>Focus on maintainability over complexity</li>
|
||||||
<li>Focus on maintainability over complexity</li>
|
<li>Prioritize the developer experience</li>
|
||||||
<li>Prioritize the developer experience</li>
|
<li>Keep performance in mind at every step</li>
|
||||||
<li>Keep performance in mind at every step</li>
|
</ol>
|
||||||
</ol>
|
<p>These principles have not only made my static site generator better but have also influenced how I approach every new project. Sometimes the best insights come from the simplest projects, and often they come right in the middle of writing about them.</p>
|
||||||
<p>These principles have not only made my static site generator better but have also influenced how I approach every new project. Sometimes the best insights come from the simplest projects, and often they come right in the middle of writing about them.</p>
|
|
||||||
|
</article>
|
||||||
</article>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</main>
|
||||||
</main>
|
<footer class="bg-base-darker text-palenight-200 py-12 border-t border-palenight-400/20">
|
||||||
<footer class="bg-base-darker text-palenight-200 py-12 border-t border-palenight-400/20">
|
<div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
<div class="text-center">
|
||||||
<div class="text-center">
|
<p class="text-palenight-300">© 2026 Glenn Thompson. All rights reserved.</p>
|
||||||
<p class="text-palenight-300">© 2024 Glenn Thompson. All rights reserved.</p>
|
<div class="webring-text mt-6">
|
||||||
<div class="webring-text mt-6">
|
<p class="text-palenight-300">I am part of the <a href="https://systemcrafters.net" target="_blank" class="text-accent-blue hover:text-accent-cyan">System Crafters</a> webring:</p>
|
||||||
<p class="text-palenight-300">I am part of the <a href="https://systemcrafters.net" target="_blank" class="text-accent-blue hover:text-accent-cyan">System Crafters</a> webring:</p>
|
</div>
|
||||||
</div>
|
<div class="craftering mt-2 flex items-center justify-center gap-4 text-accent-blue">
|
||||||
<div class="craftering mt-2 flex items-center justify-center gap-4 text-accent-blue">
|
<a href="https://craftering.systemcrafters.net/@glenneth/previous" class="hover:text-accent-cyan">Previous</a>
|
||||||
<a href="https://craftering.systemcrafters.net/@glenneth/previous" class="hover:text-accent-cyan">Previous</a>
|
<a href="https://craftering.systemcrafters.net/@glenneth" class="hover:text-accent-cyan">Random</a>
|
||||||
<a href="https://craftering.systemcrafters.net/@glenneth" class="hover:text-accent-cyan">Random</a>
|
<a href="https://craftering.systemcrafters.net/@glenneth/next" class="hover:text-accent-cyan">Next</a>
|
||||||
<a href="https://craftering.systemcrafters.net/@glenneth/next" class="hover:text-accent-cyan">Next</a>
|
</div>
|
||||||
</div>
|
<p class="text-palenight-300 mt-2">
|
||||||
<p class="text-palenight-300 mt-2">
|
<a href="mailto:glenn@glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenn@glenneth.org</a> |
|
||||||
<a href="mailto:glenn@glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenn@glenneth.org</a> |
|
<a href="https://glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenneth.org</a>
|
||||||
<a href="https://glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenneth.org</a>
|
</p>
|
||||||
</p>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</footer>
|
||||||
</footer>
|
</body>
|
||||||
</body>
|
|
||||||
</html>
|
</html>
|
||||||
|
|
@ -126,9 +126,9 @@
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
<footer class="bg-base-darker text-palenight-200 py-12 border-t border-palenight-400/20">
|
<footer class="bg-base-darker text-palenight-200 py-12 border-t border-palenight-400/20">
|
||||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
<div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
<p class="text-palenight-300">© 2024 Glenn Thompson. All rights reserved.</p>
|
<p class="text-palenight-300">© 2026 Glenn Thompson. All rights reserved.</p>
|
||||||
<div class="webring-text mt-6">
|
<div class="webring-text mt-6">
|
||||||
<p class="text-palenight-300">I am part of the <a href="https://systemcrafters.net" target="_blank" class="text-accent-blue hover:text-accent-cyan">System Crafters</a> webring:</p>
|
<p class="text-palenight-300">I am part of the <a href="https://systemcrafters.net" target="_blank" class="text-accent-blue hover:text-accent-cyan">System Crafters</a> webring:</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -251,9 +251,9 @@
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
<footer class="bg-base-darker text-palenight-200 py-12 border-t border-palenight-400/20">
|
<footer class="bg-base-darker text-palenight-200 py-12 border-t border-palenight-400/20">
|
||||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
<div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
<p class="text-palenight-300">© 2024 Glenn Thompson. All rights reserved.</p>
|
<p class="text-palenight-300">© 2026 Glenn Thompson. All rights reserved.</p>
|
||||||
<div class="webring-text mt-6">
|
<div class="webring-text mt-6">
|
||||||
<p class="text-palenight-300">I am part of the <a href="https://systemcrafters.net" target="_blank" class="text-accent-blue hover:text-accent-cyan">System Crafters</a> webring:</p>
|
<p class="text-palenight-300">I am part of the <a href="https://systemcrafters.net" target="_blank" class="text-accent-blue hover:text-accent-cyan">System Crafters</a> webring:</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,144 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en" class="bg-base-bg">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<meta name="description" content=""After over a year of conversations with Fade on IRC, I'm excited to be contributing to asteroid.radio - a broadcasting station for asteroid music, designed to help you get into that deep workflow."">
|
||||||
|
<meta property="og:title" content=""Contributing to asteroid.radio: Broadcasting Asteroid Music for Deep Work"">
|
||||||
|
<meta property="og:description" content=""After over a year of conversations with Fade on IRC, I'm excited to be contributing to asteroid.radio - a broadcasting station for asteroid music, designed to help you get into that deep workflow."">
|
||||||
|
<meta property="og:url" content="https://glenneth.orgcontent/posts/2026-01-12-asteroid-radio">
|
||||||
|
<title>"Contributing to asteroid.radio: Broadcasting Asteroid Music for Deep Work" - Glenn Thompson</title>
|
||||||
|
<link rel="alternate" type="application/rss+xml" title="Glenn Thompson's Blog" href="/feed.xml" />
|
||||||
|
<link href="/dist/styles.css" rel="stylesheet">
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Merriweather:wght@400;700&family=JetBrains+Mono:wght@400;700&display=swap" rel="stylesheet">
|
||||||
|
<style>
|
||||||
|
.prose-palenight {
|
||||||
|
--tw-prose-body: #bfc7d5;
|
||||||
|
--tw-prose-headings: #ffd580;
|
||||||
|
--tw-prose-links: #82aaff;
|
||||||
|
--tw-prose-code: #c792ea;
|
||||||
|
--tw-prose-pre-bg: #1b1e2b;
|
||||||
|
}
|
||||||
|
.prose h2 {
|
||||||
|
color: var(--tw-prose-headings);
|
||||||
|
font-family: Merriweather, serif;
|
||||||
|
font-weight: 700;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
margin-top: 2rem;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
.prose p {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
line-height: 1.625;
|
||||||
|
}
|
||||||
|
.prose a {
|
||||||
|
color: var(--tw-prose-links);
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
.prose a:hover {
|
||||||
|
color: #89ddff;
|
||||||
|
}
|
||||||
|
.prose code {
|
||||||
|
color: var(--tw-prose-code);
|
||||||
|
font-family: 'JetBrains Mono', monospace;
|
||||||
|
}
|
||||||
|
.prose pre {
|
||||||
|
background-color: var(--tw-prose-pre-bg);
|
||||||
|
padding: 1rem;
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
overflow-x: auto;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
.prose ul, .prose ol {
|
||||||
|
margin-top: 0.5rem;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
padding-left: 1.5rem;
|
||||||
|
}
|
||||||
|
.prose ul {
|
||||||
|
list-style-type: disc;
|
||||||
|
}
|
||||||
|
.prose ol {
|
||||||
|
list-style-type: decimal;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body class="bg-base-bg text-palenight-50">
|
||||||
|
<nav class="bg-base-darker/80 backdrop-blur-sm shadow-sm border-b border-palenight-400/20 mb-8">
|
||||||
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
|
<div class="flex items-center justify-between h-16">
|
||||||
|
<a href="/" class="text-accent-yellow font-serif text-xl font-bold">Glenn Thompson</a>
|
||||||
|
<div class="flex items-center gap-2 text-accent-yellow text-sm font-bold">
|
||||||
|
<span>[community, radio, open-source, irc, music]</span>
|
||||||
|
<span>•</span>
|
||||||
|
<time datetime="2026-01-12">January 12, 2026</time>
|
||||||
|
<span>•</span>
|
||||||
|
<span>3 min read</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<main class="pt-24 pb-16 px-4">
|
||||||
|
<div class="max-w-4xl mx-auto">
|
||||||
|
<div class="content text-palenight-100 space-y-6">
|
||||||
|
<header class="mb-8">
|
||||||
|
<h1 class="text-4xl font-serif font-bold text-accent-yellow">"Contributing to asteroid.radio: Broadcasting Asteroid Music for Deep Work"</h1>
|
||||||
|
<div class="flex items-center gap-4 text-palenight-300 mt-4">
|
||||||
|
<time datetime="2026-01-12">2026-01-12</time>
|
||||||
|
<span>•</span>
|
||||||
|
<span>3 min read</span>
|
||||||
|
<span>•</span>
|
||||||
|
<span>By Glenn Thompson</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex flex-wrap gap-2 mt-4">
|
||||||
|
<span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">[community</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">radio</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">open-source</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">irc</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">music]</span>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<article class="prose prose-palenight max-w-none">
|
||||||
|
<h2>Introduction</h2>
|
||||||
|
<p>Sometimes the best projects emerge from casual conversations that span months or even years. That's exactly how my involvement with <a href="https://asteroid.radio">asteroid.radio</a> came about - through countless discussions with Fade on IRC, stretching back over a couple of years.</p>
|
||||||
|
<p>Fade is the development lead on asteroid.radio, and our conversations about the project have been a recurring thread in our IRC interactions. What started as occasional mentions evolved into deeper technical discussions, and eventually into an opportunity to contribute. I did bend Fades' arm a little bit to get us started, but I hope he appreciates the push.</p>
|
||||||
|
<h2>What is asteroid.radio?</h2>
|
||||||
|
<p><a href="https://asteroid.radio">asteroid.radio</a> is a broadcasting station dedicated to what Fade has dubbed "asteroid music" - that particular genre of sound that helps you slip into a deep workflow when hacking or deeply engaged at the computer. The moment Fade coined the term, I knew exactly what he was referencing. It's that music that fades into the background while simultaneously sharpening your focus.</p>
|
||||||
|
<p>We're attempting to build a community around this concept - a space for people who understand that the right soundtrack can transform a coding session from distracted fumbling into hours of productive flow. The project is open source, and you can find the code at <a href="https://github.com/fade/asteroid">github.com/fade/asteroid</a>.</p>
|
||||||
|
<h2>The IRC Connection</h2>
|
||||||
|
<p>My involvement with asteroid.radio is deeply rooted in IRC culture. Fade and easilok are both active in the IRC community, and it's through these channels that the project has grown and evolved.</p>
|
||||||
|
<p>There's something special about IRC as a medium for project collaboration. The asynchronous nature of conversations allows ideas to percolate over time. Fade and I would discuss asteroid.radio concepts, then return to them weeks or months later with fresh perspectives. This slow-burn approach to project development has its own rhythm - one that I've come to appreciate.</p>
|
||||||
|
<h2>Getting Involved</h2>
|
||||||
|
<p>After over a couple of years of these on-and-off conversations, I'm now actively contributing to the project. Working with Fade as the dev lead has been a great experience - there's a "clear" vision for what asteroid.radio should become (don't mention Autechre), while still leaving room for contributors to bring their own ideas and expertise.</p>
|
||||||
|
<p>The project represents exactly the kind of work I find most rewarding: community-focused, technically interesting, and aligned with the values of open source that I care about.</p>
|
||||||
|
<h2>Looking Forward</h2>
|
||||||
|
<p>I'm excited to see where <a href="https://asteroid.radio">asteroid.radio</a> goes from here. Projects like this demonstrate what's possible when communities come together to build something meaningful.</p>
|
||||||
|
<p>If you're interested in asteroid music, deep work soundtracks, or just want to see what we're building, tune in to <a href="https://asteroid.radio">asteroid.radio</a> and check out the <a href="https://github.com/fade/asteroid">source code on GitHub</a>. And if you're on IRC, come say hello - you might find yourself drawn into a years-long conversation that leads somewhere unexpected.</p>
|
||||||
|
<h2>Community Matters</h2>
|
||||||
|
<p>This experience has reinforced something I've come to believe strongly: the best open source contributions often come from genuine community connections. Whether it's the <a href="https://systemcrafters.net/">System Crafters</a> community, the <a href="https://craftering.systemcrafters.net/">Craftering webring</a>, or the IRC channels where projects like <a href="https://asteroid.radio">asteroid.radio</a> take shape, these spaces matter.</p>
|
||||||
|
<p>Thanks to Fade for the leadership on this project, to easilok for being part of the community, and to everyone who makes IRC such a valuable space for collaboration.</p>
|
||||||
|
<p>Happy Hacking!</p>
|
||||||
|
|
||||||
|
</article>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
<footer class="bg-base-darker text-palenight-200 py-12 border-t border-palenight-400/20">
|
||||||
|
<div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
|
<div class="text-center">
|
||||||
|
<p class="text-palenight-300">© 2026 Glenn Thompson. All rights reserved.</p>
|
||||||
|
<div class="webring-text mt-6">
|
||||||
|
<p class="text-palenight-300">I am part of the <a href="https://systemcrafters.net" target="_blank" class="text-accent-blue hover:text-accent-cyan">System Crafters</a> webring:</p>
|
||||||
|
</div>
|
||||||
|
<div class="craftering mt-2 flex items-center justify-center gap-4 text-accent-blue">
|
||||||
|
<a href="https://craftering.systemcrafters.net/@glenneth/previous" class="hover:text-accent-cyan">Previous</a>
|
||||||
|
<a href="https://craftering.systemcrafters.net/@glenneth" class="hover:text-accent-cyan">Random</a>
|
||||||
|
<a href="https://craftering.systemcrafters.net/@glenneth/next" class="hover:text-accent-cyan">Next</a>
|
||||||
|
</div>
|
||||||
|
<p class="text-palenight-300 mt-2">
|
||||||
|
<a href="mailto:glenn@glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenn@glenneth.org</a> |
|
||||||
|
<a href="https://glenneth.org" class="text-accent-blue hover:text-accent-cyan transition-colors">glenneth.org</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
<link>https://glenneth.org</link>
|
<link>https://glenneth.org</link>
|
||||||
<atom:link href="https://glenneth.org/feed.xml" rel="self" type="application/rss+xml" />
|
<atom:link href="https://glenneth.org/feed.xml" rel="self" type="application/rss+xml" />
|
||||||
<language>en-us</language>
|
<language>en-us</language>
|
||||||
<lastBuildDate>Sun, 28 Sep 2025 08:21:15 GMT</lastBuildDate>
|
<lastBuildDate>Mon, 12 Jan 2026 04:08:56 GMT</lastBuildDate>
|
||||||
|
|
||||||
<item>
|
<item>
|
||||||
<title>Development Environment Evolution: Embracing Guix Home and Enhanced Emacs Workflow</title>
|
<title>Development Environment Evolution: Embracing Guix Home and Enhanced Emacs Workflow</title>
|
||||||
|
|
@ -166,5 +166,35 @@
|
||||||
<author>Glenn Thompson</author>
|
<author>Glenn Thompson</author>
|
||||||
<category>["development", "guix", "guix-home", "emacs", "workflow", "productivity", "evolution"]</category>
|
<category>["development", "guix", "guix-home", "emacs", "workflow", "productivity", "evolution"]</category>
|
||||||
</item>
|
</item>
|
||||||
|
|
||||||
|
<item>
|
||||||
|
<title>Contributing to asteroid.radio: Broadcasting Asteroid Music for Deep Work</title>
|
||||||
|
<description>"After over a year of conversations with Fade on IRC, I'm excited to be contributing to asteroid.radio - a broadcasting station for asteroid music, designed to help you get into that deep workflow."</description>
|
||||||
|
<content:encoded><![CDATA[<h2>Introduction</h2>
|
||||||
|
<p>Sometimes the best projects emerge from casual conversations that span months or even years. That's exactly how my involvement with <a href="https://asteroid.radio">asteroid.radio</a> came about - through countless discussions with Fade on IRC, stretching back over a couple of years.</p>
|
||||||
|
<p>Fade is the development lead on asteroid.radio, and our conversations about the project have been a recurring thread in our IRC interactions. What started as occasional mentions evolved into deeper technical discussions, and eventually into an opportunity to contribute. I did bend Fades' arm a little bit to get us started, but I hope he appreciates the push.</p>
|
||||||
|
<h2>What is asteroid.radio?</h2>
|
||||||
|
<p><a href="https://asteroid.radio">asteroid.radio</a> is a broadcasting station dedicated to what Fade has dubbed "asteroid music" - that particular genre of sound that helps you slip into a deep workflow when hacking or deeply engaged at the computer. The moment Fade coined the term, I knew exactly what he was referencing. It's that music that fades into the background while simultaneously sharpening your focus.</p>
|
||||||
|
<p>We're attempting to build a community around this concept - a space for people who understand that the right soundtrack can transform a coding session from distracted fumbling into hours of productive flow. The project is open source, and you can find the code at <a href="https://github.com/fade/asteroid">github.com/fade/asteroid</a>.</p>
|
||||||
|
<h2>The IRC Connection</h2>
|
||||||
|
<p>My involvement with asteroid.radio is deeply rooted in IRC culture. Fade and easilok are both active in the IRC community, and it's through these channels that the project has grown and evolved.</p>
|
||||||
|
<p>There's something special about IRC as a medium for project collaboration. The asynchronous nature of conversations allows ideas to percolate over time. Fade and I would discuss asteroid.radio concepts, then return to them weeks or months later with fresh perspectives. This slow-burn approach to project development has its own rhythm - one that I've come to appreciate.</p>
|
||||||
|
<h2>Getting Involved</h2>
|
||||||
|
<p>After over a couple of years of these on-and-off conversations, I'm now actively contributing to the project. Working with Fade as the dev lead has been a great experience - there's a "clear" vision for what asteroid.radio should become (don't mention Autechre), while still leaving room for contributors to bring their own ideas and expertise.</p>
|
||||||
|
<p>The project represents exactly the kind of work I find most rewarding: community-focused, technically interesting, and aligned with the values of open source that I care about.</p>
|
||||||
|
<h2>Looking Forward</h2>
|
||||||
|
<p>I'm excited to see where <a href="https://asteroid.radio">asteroid.radio</a> goes from here. Projects like this demonstrate what's possible when communities come together to build something meaningful.</p>
|
||||||
|
<p>If you're interested in asteroid music, deep work soundtracks, or just want to see what we're building, tune in to <a href="https://asteroid.radio">asteroid.radio</a> and check out the <a href="https://github.com/fade/asteroid">source code on GitHub</a>. And if you're on IRC, come say hello - you might find yourself drawn into a years-long conversation that leads somewhere unexpected.</p>
|
||||||
|
<h2>Community Matters</h2>
|
||||||
|
<p>This experience has reinforced something I've come to believe strongly: the best open source contributions often come from genuine community connections. Whether it's the <a href="https://systemcrafters.net/">System Crafters</a> community, the <a href="https://craftering.systemcrafters.net/">Craftering webring</a>, or the IRC channels where projects like <a href="https://asteroid.radio">asteroid.radio</a> take shape, these spaces matter.</p>
|
||||||
|
<p>Thanks to Fade for the leadership on this project, to easilok for being part of the community, and to everyone who makes IRC such a valuable space for collaboration.</p>
|
||||||
|
<p>Happy Hacking!</p>
|
||||||
|
]]></content:encoded>
|
||||||
|
<link>https://glenneth.org/content/posts/2026-01-12-asteroid-radio.html</link>
|
||||||
|
<guid isPermaLink="true">https://glenneth.org/content/posts/2026-01-12-asteroid-radio.html</guid>
|
||||||
|
<pubDate>Mon, 12 Jan 2026 00:00:00 GMT</pubDate>
|
||||||
|
<author>Glenn Thompson</author>
|
||||||
|
<category>[community, radio, open-source, irc, music]</category>
|
||||||
|
</item>
|
||||||
</channel>
|
</channel>
|
||||||
</rss>
|
</rss>
|
||||||
|
|
@ -1,65 +1,84 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en" class="bg-base-bg">
|
<html lang="en" class="bg-base-bg">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<meta name="description"
|
<meta name="description"
|
||||||
content="Glenn Thompson's personal blog about technology, engineering, and travel experiences in the Middle East">
|
content="Glenn Thompson's personal blog about technology, engineering, and travel experiences in the Middle East">
|
||||||
<meta property="og:title" content="Glenn Thompson - Technology, Engineering & Travel">
|
<meta property="og:title" content="Glenn Thompson - Technology, Engineering & Travel">
|
||||||
<meta property="og:description"
|
<meta property="og:description"
|
||||||
content="Exploring the intersection of electrical engineering, technology, and cultural experiences from two decades in the Middle East">
|
content="Exploring the intersection of electrical engineering, technology, and cultural experiences from two decades in the Middle East">
|
||||||
<meta property="og:url" content="https://glenneth.org">
|
<meta property="og:url" content="https://glenneth.org">
|
||||||
<title>Glenn Thompson - Technology, Engineering & Travel</title>
|
<title>Glenn Thompson - Technology, Engineering & Travel</title>
|
||||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg">
|
<link rel="icon" type="image/svg+xml" href="/favicon.svg">
|
||||||
<link rel="alternate" type="application/rss+xml" title="Glenn Thompson's Blog" href="/feed.xml" />
|
<link rel="alternate" type="application/rss+xml" title="Glenn Thompson's Blog" href="/feed.xml" />
|
||||||
<link href="./dist/styles.css" rel="stylesheet">
|
<link href="./dist/styles.css" rel="stylesheet">
|
||||||
<link
|
<link
|
||||||
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Merriweather:wght@400;700&family=JetBrains+Mono:wght@400;700&display=swap"
|
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Merriweather:wght@400;700&family=JetBrains+Mono:wght@400;700&display=swap"
|
||||||
rel="stylesheet">
|
rel="stylesheet">
|
||||||
<script defer src="./src/js/main.js"></script>
|
<script defer src="./src/js/main.js"></script>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="bg-base-bg text-palenight-50">
|
<body class="bg-base-bg text-palenight-50">
|
||||||
<nav class="fixed w-full bg-base-darker/80 backdrop-blur-sm shadow-sm z-50 border-b border-palenight-400/20">
|
<nav class="fixed w-full bg-base-darker/80 backdrop-blur-sm shadow-sm z-50 border-b border-palenight-400/20">
|
||||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<div class="flex justify-between h-16">
|
<div class="flex justify-between h-16">
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<a href="#" class="flex items-center font-serif text-xl font-bold text-accent-purple">Glenn
|
<a href="#" class="flex items-center font-serif text-xl font-bold text-accent-purple">Glenn
|
||||||
Thompson</a>
|
Thompson</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="hidden sm:ml-6 sm:flex sm:space-x-8">
|
<div class="hidden sm:ml-6 sm:flex sm:space-x-8">
|
||||||
<a href="#about" class="nav-link text-accent-blue hover:text-accent-cyan">About</a>
|
<a href="#about" class="nav-link text-accent-blue hover:text-accent-cyan">About</a>
|
||||||
<a href="#blog" class="nav-link text-accent-blue hover:text-accent-cyan">Blog</a>
|
<a href="#blog" class="nav-link text-accent-blue hover:text-accent-cyan">Blog</a>
|
||||||
<a href="#projects" class="nav-link text-accent-blue hover:text-accent-cyan">Projects</a>
|
<a href="#projects" class="nav-link text-accent-blue hover:text-accent-cyan">Projects</a>
|
||||||
<a href="#contact" class="nav-link text-accent-blue hover:text-accent-cyan">Contact</a>
|
<a href="#contact" class="nav-link text-accent-blue hover:text-accent-cyan">Contact</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<main>
|
<main>
|
||||||
<!-- Hero Section -->
|
<!-- Hero Section -->
|
||||||
<section class="pt-24 pb-16 px-4 sm:pt-32 sm:pb-24 bg-base-bg">
|
<section class="pt-24 pb-16 px-4 sm:pt-32 sm:pb-24 bg-base-bg">
|
||||||
<div class="max-w-7xl mx-auto">
|
<div class="max-w-7xl mx-auto">
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
<h1 class="text-4xl font-serif font-bold tracking-tight text-accent-yellow sm:text-6xl">
|
<h1 class="text-4xl font-serif font-bold tracking-tight text-accent-yellow sm:text-6xl">
|
||||||
Technology, Engineering & Travel
|
Technology, Engineering & Travel
|
||||||
</h1>
|
</h1>
|
||||||
<p class="mt-6 text-lg leading-8 text-palenight-100 max-w-2xl mx-auto">
|
<p class="mt-6 text-lg leading-8 text-palenight-100 max-w-2xl mx-auto">
|
||||||
Exploring the intersection of electrical engineering, technology, and cultural experiences from
|
Exploring the intersection of electrical engineering, technology, and cultural experiences from
|
||||||
two decades in the Middle East.
|
two decades in the Middle East.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<!-- Featured Posts -->
|
<!-- Featured Posts -->
|
||||||
<section id="blog" class="py-16">
|
<section id="blog" class="py-16">
|
||||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<h2 class="text-3xl font-serif font-bold text-accent-yellow mb-8">Blog Posts</h2>
|
<h2 class="text-3xl font-serif font-bold text-accent-yellow mb-8">Blog Posts</h2>
|
||||||
<div class="grid gap-8 md:grid-cols-2">
|
<div class="grid gap-8 md:grid-cols-2">
|
||||||
|
|
||||||
|
<article class="bg-base-darker p-6 rounded-lg shadow-lg border border-palenight-400/20 hover:border-accent-purple/40 transition-colors">
|
||||||
|
<div class="flex flex-wrap items-center gap-2 text-accent-yellow text-sm mb-2 font-bold">
|
||||||
|
<span>Tech</span>
|
||||||
|
<span>•</span><span>community</span><span>•</span><span>radio</span><span>•</span><span>open-source</span><span>•</span><span>irc</span><span>•</span><span>music</span>
|
||||||
|
<span>•</span>
|
||||||
|
<time datetime="2026-01-12">January 12, 2026</time>
|
||||||
|
</div>
|
||||||
|
<h3 class="text-xl font-serif font-bold text-accent-yellow mb-3">
|
||||||
|
<a href="/content/posts/2026-01-12-asteroid-radio.html" class="hover:text-accent-cyan transition-colors">
|
||||||
|
Contributing to asteroid.radio: Broadcasting Asteroid Music for Deep Work
|
||||||
|
</a>
|
||||||
|
</h3>
|
||||||
|
<p class="text-palenight-100 mb-4">Sometimes the best projects emerge from casual conversations that span months or even years. That's exactly how my involvement with asteroid.radio came about - through countless discussions with Fade...</p>
|
||||||
|
<div class="flex flex-wrap gap-2">
|
||||||
|
<span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">community</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">radio</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">open-source</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">irc</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">music</span>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
|
||||||
<article class="bg-base-darker p-6 rounded-lg shadow-lg border border-palenight-400/20 hover:border-accent-purple/40 transition-colors">
|
<article class="bg-base-darker p-6 rounded-lg shadow-lg border border-palenight-400/20 hover:border-accent-purple/40 transition-colors">
|
||||||
<div class="flex flex-wrap items-center gap-2 text-accent-yellow text-sm mb-2 font-bold">
|
<div class="flex flex-wrap items-center gap-2 text-accent-yellow text-sm mb-2 font-bold">
|
||||||
<span>Tech</span>
|
<span>Tech</span>
|
||||||
|
|
@ -268,156 +287,156 @@
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
|
|
||||||
</div><!-- End blog posts -->
|
</div><!-- End blog posts -->
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<!-- Projects Section -->
|
<!-- Projects Section -->
|
||||||
<section id="projects" class="py-16 bg-base-darker">
|
<section id="projects" class="py-16 bg-base-darker">
|
||||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<h2 class="text-3xl font-serif font-bold text-accent-yellow mb-8">Projects</h2>
|
<h2 class="text-3xl font-serif font-bold text-accent-yellow mb-8">Projects</h2>
|
||||||
<div class="grid gap-8 md:grid-cols-2 lg:grid-cols-3">
|
<div class="grid gap-8 md:grid-cols-2 lg:grid-cols-3">
|
||||||
<!-- Personal Website Project -->
|
<!-- Personal Website Project -->
|
||||||
<article
|
<article
|
||||||
class="bg-base-bg p-6 rounded-lg shadow-lg border border-palenight-400/20 hover:border-accent-purple/40 transition-colors">
|
class="bg-base-bg p-6 rounded-lg shadow-lg border border-palenight-400/20 hover:border-accent-purple/40 transition-colors">
|
||||||
<h3 class="text-xl font-serif font-bold text-accent-yellow mb-3">Personal Website</h3>
|
<h3 class="text-xl font-serif font-bold text-accent-yellow mb-3">Personal Website</h3>
|
||||||
<p class="text-palenight-100 mb-4">A modern, responsive personal website built with HTML,
|
<p class="text-palenight-100 mb-4">A modern, responsive personal website built with HTML,
|
||||||
TailwindCSS, and JavaScript. Features a dark theme and blog functionality.</p>
|
TailwindCSS, and JavaScript. Features a dark theme and blog functionality.</p>
|
||||||
<div class="flex gap-2 mb-4">
|
<div class="flex gap-2 mb-4">
|
||||||
<span class="text-accent-yellow px-2 py-1 rounded-full bg-base-darker text-xs">HTML</span>
|
<span class="text-accent-yellow px-2 py-1 rounded-full bg-base-darker text-xs">HTML</span>
|
||||||
<span class="text-accent-yellow px-2 py-1 rounded-full bg-base-darker text-xs">TailwindCSS</span>
|
<span class="text-accent-yellow px-2 py-1 rounded-full bg-base-darker text-xs">TailwindCSS</span>
|
||||||
<span class="text-accent-yellow px-2 py-1 rounded-full bg-base-darker text-xs">JavaScript</span>
|
<span class="text-accent-yellow px-2 py-1 rounded-full bg-base-darker text-xs">JavaScript</span>
|
||||||
</div>
|
</div>
|
||||||
<a href="https://github.com/glenneth1/personal-website"
|
<a href="https://github.com/glenneth1/personal-website"
|
||||||
class="text-accent-cyan hover:text-accent-purple transition-colors">View Source →</a>
|
class="text-accent-cyan hover:text-accent-purple transition-colors">View Source →</a>
|
||||||
</article>
|
</article>
|
||||||
|
|
||||||
<!-- Symlink Manager Project -->
|
<!-- Symlink Manager Project -->
|
||||||
<article
|
<article
|
||||||
class="bg-base-bg p-6 rounded-lg shadow-lg border border-palenight-400/20 hover:border-accent-purple/40 transition-colors">
|
class="bg-base-bg p-6 rounded-lg shadow-lg border border-palenight-400/20 hover:border-accent-purple/40 transition-colors">
|
||||||
<h3 class="text-xl font-serif font-bold text-accent-yellow mb-3">Scheme Symlink Manager</h3>
|
<h3 class="text-xl font-serif font-bold text-accent-yellow mb-3">Scheme Symlink Manager</h3>
|
||||||
<p class="text-palenight-100 mb-4">A command-line tool built with Guile Scheme for managing
|
<p class="text-palenight-100 mb-4">A command-line tool built with Guile Scheme for managing
|
||||||
symbolic links in Unix-like systems. Simplifies dotfile management.</p>
|
symbolic links in Unix-like systems. Simplifies dotfile management.</p>
|
||||||
<div class="flex gap-2 mb-4">
|
<div class="flex gap-2 mb-4">
|
||||||
<span class="text-accent-yellow px-2 py-1 rounded-full bg-base-darker text-xs">Scheme</span>
|
<span class="text-accent-yellow px-2 py-1 rounded-full bg-base-darker text-xs">Scheme</span>
|
||||||
<span class="text-accent-yellow px-2 py-1 rounded-full bg-base-darker text-xs">Guile</span>
|
<span class="text-accent-yellow px-2 py-1 rounded-full bg-base-darker text-xs">Guile</span>
|
||||||
<span class="text-accent-yellow px-2 py-1 rounded-full bg-base-darker text-xs">CLI</span>
|
<span class="text-accent-yellow px-2 py-1 rounded-full bg-base-darker text-xs">CLI</span>
|
||||||
</div>
|
</div>
|
||||||
<a href="#" class="text-accent-cyan hover:text-accent-purple transition-colors">Coming Soon
|
<a href="#" class="text-accent-cyan hover:text-accent-purple transition-colors">Coming Soon
|
||||||
→</a>
|
→</a>
|
||||||
</article>
|
</article>
|
||||||
|
|
||||||
<!-- Add Project Card -->
|
<!-- Add Project Card -->
|
||||||
<article
|
<article
|
||||||
class="bg-base-bg p-6 rounded-lg shadow-lg border border-palenight-400/20 hover:border-accent-purple/40 transition-colors flex items-center justify-center">
|
class="bg-base-bg p-6 rounded-lg shadow-lg border border-palenight-400/20 hover:border-accent-purple/40 transition-colors flex items-center justify-center">
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
<p class="text-palenight-100 mb-2">More projects coming soon!</p>
|
<p class="text-palenight-100 mb-2">More projects coming soon!</p>
|
||||||
<p class="text-accent-cyan">Stay tuned...</p>
|
<p class="text-accent-cyan">Stay tuned...</p>
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<!-- About Section -->
|
<!-- About Section -->
|
||||||
<section id="about" class="py-16 bg-base-bg">
|
<section id="about" class="py-16 bg-base-bg">
|
||||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
|
<div class="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
|
||||||
<div>
|
<div>
|
||||||
<h2 class="text-3xl font-serif font-bold text-accent-yellow mb-6">About Me</h2>
|
<h2 class="text-3xl font-serif font-bold text-accent-yellow mb-6">About Me</h2>
|
||||||
<p class="text-palenight-100 mb-4">
|
<p class="text-palenight-100 mb-4">
|
||||||
With over 20 years in the electrical engineering field, I've had the privilege of working on
|
With over 20 years in the electrical engineering field, I've had the privilege of working on
|
||||||
groundbreaking projects across the Middle East. My journey has been marked by continuous
|
groundbreaking projects across the Middle East. My journey has been marked by continuous
|
||||||
learning, cultural exploration, and technological innovation.
|
learning, cultural exploration, and technological innovation.
|
||||||
</p>
|
</p>
|
||||||
<p class="text-palenight-100 mb-4">
|
<p class="text-palenight-100 mb-4">
|
||||||
Beyond my professional work, I'm passionate about technology, particularly static site
|
Beyond my professional work, I'm passionate about technology, particularly static site
|
||||||
generation, Scheme programming, and tools like GNU Guix and Haunt. This blog is where I
|
generation, Scheme programming, and tools like GNU Guix and Haunt. This blog is where I
|
||||||
share my experiences, insights, and the lessons learned along the way.
|
share my experiences, insights, and the lessons learned along the way.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="bg-base-darker p-8 rounded-lg shadow-md border border-palenight-400/20">
|
<div class="bg-base-darker p-8 rounded-lg shadow-md border border-palenight-400/20">
|
||||||
<h3 class="text-xl font-bold text-accent-yellow mb-4">Areas of Focus</h3>
|
<h3 class="text-xl font-bold text-accent-yellow mb-4">Areas of Focus</h3>
|
||||||
<ul class="space-y-3">
|
<ul class="space-y-3">
|
||||||
<li class="flex items-center text-palenight-100">
|
<li class="flex items-center text-palenight-100">
|
||||||
<svg class="w-5 h-5 text-accent-blue mr-2" fill="currentColor" viewBox="0 0 20 20">
|
<svg class="w-5 h-5 text-accent-blue mr-2" fill="currentColor" viewBox="0 0 20 20">
|
||||||
<path fill-rule="evenodd"
|
<path fill-rule="evenodd"
|
||||||
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"
|
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"
|
||||||
clip-rule="evenodd"></path>
|
clip-rule="evenodd"></path>
|
||||||
</svg>
|
</svg>
|
||||||
Electrical Engineering
|
Electrical Engineering
|
||||||
</li>
|
</li>
|
||||||
<li class="flex items-center text-palenight-100">
|
<li class="flex items-center text-palenight-100">
|
||||||
<svg class="w-5 h-5 text-accent-blue mr-2" fill="currentColor" viewBox="0 0 20 20">
|
<svg class="w-5 h-5 text-accent-blue mr-2" fill="currentColor" viewBox="0 0 20 20">
|
||||||
<path fill-rule="evenodd"
|
<path fill-rule="evenodd"
|
||||||
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"
|
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"
|
||||||
clip-rule="evenodd"></path>
|
clip-rule="evenodd"></path>
|
||||||
</svg>
|
</svg>
|
||||||
Static Site Generation
|
Static Site Generation
|
||||||
</li>
|
</li>
|
||||||
<li class="flex items-center text-palenight-100">
|
<li class="flex items-center text-palenight-100">
|
||||||
<svg class="w-5 h-5 text-accent-blue mr-2" fill="currentColor" viewBox="0 0 20 20">
|
<svg class="w-5 h-5 text-accent-blue mr-2" fill="currentColor" viewBox="0 0 20 20">
|
||||||
<path fill-rule="evenodd"
|
<path fill-rule="evenodd"
|
||||||
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"
|
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"
|
||||||
clip-rule="evenodd"></path>
|
clip-rule="evenodd"></path>
|
||||||
</svg>
|
</svg>
|
||||||
Scheme Programming
|
Scheme Programming
|
||||||
</li>
|
</li>
|
||||||
<li class="flex items-center text-palenight-100">
|
<li class="flex items-center text-palenight-100">
|
||||||
<svg class="w-5 h-5 text-accent-blue mr-2" fill="currentColor" viewBox="0 0 20 20">
|
<svg class="w-5 h-5 text-accent-blue mr-2" fill="currentColor" viewBox="0 0 20 20">
|
||||||
<path fill-rule="evenodd"
|
<path fill-rule="evenodd"
|
||||||
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"
|
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"
|
||||||
clip-rule="evenodd"></path>
|
clip-rule="evenodd"></path>
|
||||||
</svg>
|
</svg>
|
||||||
Middle Eastern Culture
|
Middle Eastern Culture
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<!-- Contact Section -->
|
<!-- Contact Section -->
|
||||||
<section id="contact" class="py-16 bg-base-darker">
|
<section id="contact" class="py-16 bg-base-darker">
|
||||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
<h2 class="text-3xl font-serif font-bold text-accent-yellow mb-6">Get in Touch</h2>
|
<h2 class="text-3xl font-serif font-bold text-accent-yellow mb-6">Get in Touch</h2>
|
||||||
<p class="text-palenight-100 mb-8">
|
<p class="text-palenight-100 mb-8">
|
||||||
Interested in connecting? Feel free to reach out for discussions about technology, engineering,
|
Interested in connecting? Feel free to reach out for discussions about technology, engineering,
|
||||||
or sharing travel stories.
|
or sharing travel stories.
|
||||||
</p>
|
</p>
|
||||||
<a href="mailto:glenn@glenneth.org"
|
<a href="mailto:glenn@glenneth.org"
|
||||||
class="inline-flex items-center px-6 py-3 border border-accent-blue text-base font-medium rounded-md text-accent-blue hover:bg-accent-blue hover:text-base-bg transition-colors">
|
class="inline-flex items-center px-6 py-3 border border-accent-blue text-base font-medium rounded-md text-accent-blue hover:bg-accent-blue hover:text-base-bg transition-colors">
|
||||||
Send a Message
|
Send a Message
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<footer class="bg-base-darker text-palenight-200 py-12 border-t border-palenight-400/20">
|
<footer class="bg-base-darker text-palenight-200 py-12 border-t border-palenight-400/20">
|
||||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
<p class="text-palenight-300">© 2024 Glenn Thompson. All rights reserved.</p>
|
<p class="text-palenight-300">© 2026 Glenn Thompson. All rights reserved.</p>
|
||||||
<div class="webring-text mt-6">
|
<div class="webring-text mt-6">
|
||||||
<p class="text-palenight-300">I am part of the <a href="https://systemcrafters.net" target="_blank"
|
<p class="text-palenight-300">I am part of the <a href="https://systemcrafters.net" target="_blank"
|
||||||
class="text-accent-blue hover:text-accent-cyan">System Crafters</a> webring:</p>
|
class="text-accent-blue hover:text-accent-cyan">System Crafters</a> webring:</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="craftering mt-2 flex items-center justify-center gap-4 text-accent-blue">
|
<div class="craftering mt-2 flex items-center justify-center gap-4 text-accent-blue">
|
||||||
<a href="https://craftering.systemcrafters.net/@glenneth/previous"
|
<a href="https://craftering.systemcrafters.net/@glenneth/previous"
|
||||||
class="hover:text-accent-cyan">←</a>
|
class="hover:text-accent-cyan">←</a>
|
||||||
<a href="https://craftering.systemcrafters.net/" class="hover:text-accent-cyan">craftering</a>
|
<a href="https://craftering.systemcrafters.net/" class="hover:text-accent-cyan">craftering</a>
|
||||||
<a href="https://craftering.systemcrafters.net/@glenneth/next" class="hover:text-accent-cyan">→</a>
|
<a href="https://craftering.systemcrafters.net/@glenneth/next" class="hover:text-accent-cyan">→</a>
|
||||||
</div>
|
</div>
|
||||||
<p class="text-palenight-300 mt-2">
|
<p class="text-palenight-300 mt-2">
|
||||||
<a href="mailto:glenn@glenneth.org"
|
<a href="mailto:glenn@glenneth.org"
|
||||||
class="text-accent-blue hover:text-accent-cyan transition-colors">glenn@glenneth.org</a> |
|
class="text-accent-blue hover:text-accent-cyan transition-colors">glenn@glenneth.org</a> |
|
||||||
<a href="https://glenneth.org"
|
<a href="https://glenneth.org"
|
||||||
class="text-accent-blue hover:text-accent-cyan transition-colors">glenneth.org</a>
|
class="text-accent-blue hover:text-accent-cyan transition-colors">glenneth.org</a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|
@ -12,9 +12,9 @@ const options = {
|
||||||
// Footer template
|
// Footer template
|
||||||
const footer = `
|
const footer = `
|
||||||
<footer class="bg-base-darker text-palenight-200 py-12 border-t border-palenight-400/20">
|
<footer class="bg-base-darker text-palenight-200 py-12 border-t border-palenight-400/20">
|
||||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
<div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
<p class="text-palenight-300">© 2024 Glenn Thompson. All rights reserved.</p>
|
<p class="text-palenight-300">© 2026 Glenn Thompson. All rights reserved.</p>
|
||||||
<div class="webring-text mt-6">
|
<div class="webring-text mt-6">
|
||||||
<p class="text-palenight-300">I am part of the <a href="https://systemcrafters.net" target="_blank" class="text-accent-blue hover:text-accent-cyan">System Crafters</a> webring:</p>
|
<p class="text-palenight-300">I am part of the <a href="https://systemcrafters.net" target="_blank" class="text-accent-blue hover:text-accent-cyan">System Crafters</a> webring:</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
32
feed.xml
32
feed.xml
|
|
@ -6,7 +6,7 @@
|
||||||
<link>https://glenneth.org</link>
|
<link>https://glenneth.org</link>
|
||||||
<atom:link href="https://glenneth.org/feed.xml" rel="self" type="application/rss+xml" />
|
<atom:link href="https://glenneth.org/feed.xml" rel="self" type="application/rss+xml" />
|
||||||
<language>en-us</language>
|
<language>en-us</language>
|
||||||
<lastBuildDate>Sun, 28 Sep 2025 08:21:15 GMT</lastBuildDate>
|
<lastBuildDate>Mon, 12 Jan 2026 04:08:56 GMT</lastBuildDate>
|
||||||
|
|
||||||
<item>
|
<item>
|
||||||
<title>Development Environment Evolution: Embracing Guix Home and Enhanced Emacs Workflow</title>
|
<title>Development Environment Evolution: Embracing Guix Home and Enhanced Emacs Workflow</title>
|
||||||
|
|
@ -166,5 +166,35 @@
|
||||||
<author>Glenn Thompson</author>
|
<author>Glenn Thompson</author>
|
||||||
<category>["development", "guix", "guix-home", "emacs", "workflow", "productivity", "evolution"]</category>
|
<category>["development", "guix", "guix-home", "emacs", "workflow", "productivity", "evolution"]</category>
|
||||||
</item>
|
</item>
|
||||||
|
|
||||||
|
<item>
|
||||||
|
<title>Contributing to asteroid.radio: Broadcasting Asteroid Music for Deep Work</title>
|
||||||
|
<description>"After over a year of conversations with Fade on IRC, I'm excited to be contributing to asteroid.radio - a broadcasting station for asteroid music, designed to help you get into that deep workflow."</description>
|
||||||
|
<content:encoded><![CDATA[<h2>Introduction</h2>
|
||||||
|
<p>Sometimes the best projects emerge from casual conversations that span months or even years. That's exactly how my involvement with <a href="https://asteroid.radio">asteroid.radio</a> came about - through countless discussions with Fade on IRC, stretching back over a couple of years.</p>
|
||||||
|
<p>Fade is the development lead on asteroid.radio, and our conversations about the project have been a recurring thread in our IRC interactions. What started as occasional mentions evolved into deeper technical discussions, and eventually into an opportunity to contribute. I did bend Fades' arm a little bit to get us started, but I hope he appreciates the push.</p>
|
||||||
|
<h2>What is asteroid.radio?</h2>
|
||||||
|
<p><a href="https://asteroid.radio">asteroid.radio</a> is a broadcasting station dedicated to what Fade has dubbed "asteroid music" - that particular genre of sound that helps you slip into a deep workflow when hacking or deeply engaged at the computer. The moment Fade coined the term, I knew exactly what he was referencing. It's that music that fades into the background while simultaneously sharpening your focus.</p>
|
||||||
|
<p>We're attempting to build a community around this concept - a space for people who understand that the right soundtrack can transform a coding session from distracted fumbling into hours of productive flow. The project is open source, and you can find the code at <a href="https://github.com/fade/asteroid">github.com/fade/asteroid</a>.</p>
|
||||||
|
<h2>The IRC Connection</h2>
|
||||||
|
<p>My involvement with asteroid.radio is deeply rooted in IRC culture. Fade and easilok are both active in the IRC community, and it's through these channels that the project has grown and evolved.</p>
|
||||||
|
<p>There's something special about IRC as a medium for project collaboration. The asynchronous nature of conversations allows ideas to percolate over time. Fade and I would discuss asteroid.radio concepts, then return to them weeks or months later with fresh perspectives. This slow-burn approach to project development has its own rhythm - one that I've come to appreciate.</p>
|
||||||
|
<h2>Getting Involved</h2>
|
||||||
|
<p>After over a couple of years of these on-and-off conversations, I'm now actively contributing to the project. Working with Fade as the dev lead has been a great experience - there's a "clear" vision for what asteroid.radio should become (don't mention Autechre), while still leaving room for contributors to bring their own ideas and expertise.</p>
|
||||||
|
<p>The project represents exactly the kind of work I find most rewarding: community-focused, technically interesting, and aligned with the values of open source that I care about.</p>
|
||||||
|
<h2>Looking Forward</h2>
|
||||||
|
<p>I'm excited to see where <a href="https://asteroid.radio">asteroid.radio</a> goes from here. Projects like this demonstrate what's possible when communities come together to build something meaningful.</p>
|
||||||
|
<p>If you're interested in asteroid music, deep work soundtracks, or just want to see what we're building, tune in to <a href="https://asteroid.radio">asteroid.radio</a> and check out the <a href="https://github.com/fade/asteroid">source code on GitHub</a>. And if you're on IRC, come say hello - you might find yourself drawn into a years-long conversation that leads somewhere unexpected.</p>
|
||||||
|
<h2>Community Matters</h2>
|
||||||
|
<p>This experience has reinforced something I've come to believe strongly: the best open source contributions often come from genuine community connections. Whether it's the <a href="https://systemcrafters.net/">System Crafters</a> community, the <a href="https://craftering.systemcrafters.net/">Craftering webring</a>, or the IRC channels where projects like <a href="https://asteroid.radio">asteroid.radio</a> take shape, these spaces matter.</p>
|
||||||
|
<p>Thanks to Fade for the leadership on this project, to easilok for being part of the community, and to everyone who makes IRC such a valuable space for collaboration.</p>
|
||||||
|
<p>Happy Hacking!</p>
|
||||||
|
]]></content:encoded>
|
||||||
|
<link>https://glenneth.org/content/posts/2026-01-12-asteroid-radio.html</link>
|
||||||
|
<guid isPermaLink="true">https://glenneth.org/content/posts/2026-01-12-asteroid-radio.html</guid>
|
||||||
|
<pubDate>Mon, 12 Jan 2026 00:00:00 GMT</pubDate>
|
||||||
|
<author>Glenn Thompson</author>
|
||||||
|
<category>[community, radio, open-source, irc, music]</category>
|
||||||
|
</item>
|
||||||
</channel>
|
</channel>
|
||||||
</rss>
|
</rss>
|
||||||
443
index.html
443
index.html
|
|
@ -1,65 +1,84 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en" class="bg-base-bg">
|
<html lang="en" class="bg-base-bg">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<meta name="description"
|
<meta name="description"
|
||||||
content="Glenn Thompson's personal blog about technology, engineering, and travel experiences in the Middle East">
|
content="Glenn Thompson's personal blog about technology, engineering, and travel experiences in the Middle East">
|
||||||
<meta property="og:title" content="Glenn Thompson - Technology, Engineering & Travel">
|
<meta property="og:title" content="Glenn Thompson - Technology, Engineering & Travel">
|
||||||
<meta property="og:description"
|
<meta property="og:description"
|
||||||
content="Exploring the intersection of electrical engineering, technology, and cultural experiences from two decades in the Middle East">
|
content="Exploring the intersection of electrical engineering, technology, and cultural experiences from two decades in the Middle East">
|
||||||
<meta property="og:url" content="https://glenneth.org">
|
<meta property="og:url" content="https://glenneth.org">
|
||||||
<title>Glenn Thompson - Technology, Engineering & Travel</title>
|
<title>Glenn Thompson - Technology, Engineering & Travel</title>
|
||||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg">
|
<link rel="icon" type="image/svg+xml" href="/favicon.svg">
|
||||||
<link rel="alternate" type="application/rss+xml" title="Glenn Thompson's Blog" href="/feed.xml" />
|
<link rel="alternate" type="application/rss+xml" title="Glenn Thompson's Blog" href="/feed.xml" />
|
||||||
<link href="./dist/styles.css" rel="stylesheet">
|
<link href="./dist/styles.css" rel="stylesheet">
|
||||||
<link
|
<link
|
||||||
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Merriweather:wght@400;700&family=JetBrains+Mono:wght@400;700&display=swap"
|
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Merriweather:wght@400;700&family=JetBrains+Mono:wght@400;700&display=swap"
|
||||||
rel="stylesheet">
|
rel="stylesheet">
|
||||||
<script defer src="./src/js/main.js"></script>
|
<script defer src="./src/js/main.js"></script>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="bg-base-bg text-palenight-50">
|
<body class="bg-base-bg text-palenight-50">
|
||||||
<nav class="fixed w-full bg-base-darker/80 backdrop-blur-sm shadow-sm z-50 border-b border-palenight-400/20">
|
<nav class="fixed w-full bg-base-darker/80 backdrop-blur-sm shadow-sm z-50 border-b border-palenight-400/20">
|
||||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<div class="flex justify-between h-16">
|
<div class="flex justify-between h-16">
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<a href="#" class="flex items-center font-serif text-xl font-bold text-accent-purple">Glenn
|
<a href="#" class="flex items-center font-serif text-xl font-bold text-accent-purple">Glenn
|
||||||
Thompson</a>
|
Thompson</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="hidden sm:ml-6 sm:flex sm:space-x-8">
|
<div class="hidden sm:ml-6 sm:flex sm:space-x-8">
|
||||||
<a href="#about" class="nav-link text-accent-blue hover:text-accent-cyan">About</a>
|
<a href="#about" class="nav-link text-accent-blue hover:text-accent-cyan">About</a>
|
||||||
<a href="#blog" class="nav-link text-accent-blue hover:text-accent-cyan">Blog</a>
|
<a href="#blog" class="nav-link text-accent-blue hover:text-accent-cyan">Blog</a>
|
||||||
<a href="#projects" class="nav-link text-accent-blue hover:text-accent-cyan">Projects</a>
|
<a href="#projects" class="nav-link text-accent-blue hover:text-accent-cyan">Projects</a>
|
||||||
<a href="#contact" class="nav-link text-accent-blue hover:text-accent-cyan">Contact</a>
|
<a href="#contact" class="nav-link text-accent-blue hover:text-accent-cyan">Contact</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<main>
|
<main>
|
||||||
<!-- Hero Section -->
|
<!-- Hero Section -->
|
||||||
<section class="pt-24 pb-16 px-4 sm:pt-32 sm:pb-24 bg-base-bg">
|
<section class="pt-24 pb-16 px-4 sm:pt-32 sm:pb-24 bg-base-bg">
|
||||||
<div class="max-w-7xl mx-auto">
|
<div class="max-w-7xl mx-auto">
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
<h1 class="text-4xl font-serif font-bold tracking-tight text-accent-yellow sm:text-6xl">
|
<h1 class="text-4xl font-serif font-bold tracking-tight text-accent-yellow sm:text-6xl">
|
||||||
Technology, Engineering & Travel
|
Technology, Engineering & Travel
|
||||||
</h1>
|
</h1>
|
||||||
<p class="mt-6 text-lg leading-8 text-palenight-100 max-w-2xl mx-auto">
|
<p class="mt-6 text-lg leading-8 text-palenight-100 max-w-2xl mx-auto">
|
||||||
Exploring the intersection of electrical engineering, technology, and cultural experiences from
|
Exploring the intersection of electrical engineering, technology, and cultural experiences from
|
||||||
two decades in the Middle East.
|
two decades in the Middle East.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<!-- Featured Posts -->
|
<!-- Featured Posts -->
|
||||||
<section id="blog" class="py-16">
|
<section id="blog" class="py-16">
|
||||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<h2 class="text-3xl font-serif font-bold text-accent-yellow mb-8">Blog Posts</h2>
|
<h2 class="text-3xl font-serif font-bold text-accent-yellow mb-8">Blog Posts</h2>
|
||||||
<div class="grid gap-8 md:grid-cols-2">
|
<div class="grid gap-8 md:grid-cols-2">
|
||||||
|
|
||||||
|
<article class="bg-base-darker p-6 rounded-lg shadow-lg border border-palenight-400/20 hover:border-accent-purple/40 transition-colors">
|
||||||
|
<div class="flex flex-wrap items-center gap-2 text-accent-yellow text-sm mb-2 font-bold">
|
||||||
|
<span>Tech</span>
|
||||||
|
<span>•</span><span>community</span><span>•</span><span>radio</span><span>•</span><span>open-source</span><span>•</span><span>irc</span><span>•</span><span>music</span>
|
||||||
|
<span>•</span>
|
||||||
|
<time datetime="2026-01-12">January 12, 2026</time>
|
||||||
|
</div>
|
||||||
|
<h3 class="text-xl font-serif font-bold text-accent-yellow mb-3">
|
||||||
|
<a href="/content/posts/2026-01-12-asteroid-radio.html" class="hover:text-accent-cyan transition-colors">
|
||||||
|
Contributing to asteroid.radio: Broadcasting Asteroid Music for Deep Work
|
||||||
|
</a>
|
||||||
|
</h3>
|
||||||
|
<p class="text-palenight-100 mb-4">Sometimes the best projects emerge from casual conversations that span months or even years. That's exactly how my involvement with asteroid.radio came about - through countless discussions with Fade...</p>
|
||||||
|
<div class="flex flex-wrap gap-2">
|
||||||
|
<span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">community</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">radio</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">open-source</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">irc</span><span class="text-accent-yellow px-2 py-1 rounded-full bg-base-bg text-xs">music</span>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
|
||||||
<article class="bg-base-darker p-6 rounded-lg shadow-lg border border-palenight-400/20 hover:border-accent-purple/40 transition-colors">
|
<article class="bg-base-darker p-6 rounded-lg shadow-lg border border-palenight-400/20 hover:border-accent-purple/40 transition-colors">
|
||||||
<div class="flex flex-wrap items-center gap-2 text-accent-yellow text-sm mb-2 font-bold">
|
<div class="flex flex-wrap items-center gap-2 text-accent-yellow text-sm mb-2 font-bold">
|
||||||
<span>Tech</span>
|
<span>Tech</span>
|
||||||
|
|
@ -268,156 +287,156 @@
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
|
|
||||||
</div><!-- End blog posts -->
|
</div><!-- End blog posts -->
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<!-- Projects Section -->
|
<!-- Projects Section -->
|
||||||
<section id="projects" class="py-16 bg-base-darker">
|
<section id="projects" class="py-16 bg-base-darker">
|
||||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<h2 class="text-3xl font-serif font-bold text-accent-yellow mb-8">Projects</h2>
|
<h2 class="text-3xl font-serif font-bold text-accent-yellow mb-8">Projects</h2>
|
||||||
<div class="grid gap-8 md:grid-cols-2 lg:grid-cols-3">
|
<div class="grid gap-8 md:grid-cols-2 lg:grid-cols-3">
|
||||||
<!-- Personal Website Project -->
|
<!-- Personal Website Project -->
|
||||||
<article
|
<article
|
||||||
class="bg-base-bg p-6 rounded-lg shadow-lg border border-palenight-400/20 hover:border-accent-purple/40 transition-colors">
|
class="bg-base-bg p-6 rounded-lg shadow-lg border border-palenight-400/20 hover:border-accent-purple/40 transition-colors">
|
||||||
<h3 class="text-xl font-serif font-bold text-accent-yellow mb-3">Personal Website</h3>
|
<h3 class="text-xl font-serif font-bold text-accent-yellow mb-3">Personal Website</h3>
|
||||||
<p class="text-palenight-100 mb-4">A modern, responsive personal website built with HTML,
|
<p class="text-palenight-100 mb-4">A modern, responsive personal website built with HTML,
|
||||||
TailwindCSS, and JavaScript. Features a dark theme and blog functionality.</p>
|
TailwindCSS, and JavaScript. Features a dark theme and blog functionality.</p>
|
||||||
<div class="flex gap-2 mb-4">
|
<div class="flex gap-2 mb-4">
|
||||||
<span class="text-accent-yellow px-2 py-1 rounded-full bg-base-darker text-xs">HTML</span>
|
<span class="text-accent-yellow px-2 py-1 rounded-full bg-base-darker text-xs">HTML</span>
|
||||||
<span class="text-accent-yellow px-2 py-1 rounded-full bg-base-darker text-xs">TailwindCSS</span>
|
<span class="text-accent-yellow px-2 py-1 rounded-full bg-base-darker text-xs">TailwindCSS</span>
|
||||||
<span class="text-accent-yellow px-2 py-1 rounded-full bg-base-darker text-xs">JavaScript</span>
|
<span class="text-accent-yellow px-2 py-1 rounded-full bg-base-darker text-xs">JavaScript</span>
|
||||||
</div>
|
</div>
|
||||||
<a href="https://github.com/glenneth1/personal-website"
|
<a href="https://github.com/glenneth1/personal-website"
|
||||||
class="text-accent-cyan hover:text-accent-purple transition-colors">View Source →</a>
|
class="text-accent-cyan hover:text-accent-purple transition-colors">View Source →</a>
|
||||||
</article>
|
</article>
|
||||||
|
|
||||||
<!-- Symlink Manager Project -->
|
<!-- Symlink Manager Project -->
|
||||||
<article
|
<article
|
||||||
class="bg-base-bg p-6 rounded-lg shadow-lg border border-palenight-400/20 hover:border-accent-purple/40 transition-colors">
|
class="bg-base-bg p-6 rounded-lg shadow-lg border border-palenight-400/20 hover:border-accent-purple/40 transition-colors">
|
||||||
<h3 class="text-xl font-serif font-bold text-accent-yellow mb-3">Scheme Symlink Manager</h3>
|
<h3 class="text-xl font-serif font-bold text-accent-yellow mb-3">Scheme Symlink Manager</h3>
|
||||||
<p class="text-palenight-100 mb-4">A command-line tool built with Guile Scheme for managing
|
<p class="text-palenight-100 mb-4">A command-line tool built with Guile Scheme for managing
|
||||||
symbolic links in Unix-like systems. Simplifies dotfile management.</p>
|
symbolic links in Unix-like systems. Simplifies dotfile management.</p>
|
||||||
<div class="flex gap-2 mb-4">
|
<div class="flex gap-2 mb-4">
|
||||||
<span class="text-accent-yellow px-2 py-1 rounded-full bg-base-darker text-xs">Scheme</span>
|
<span class="text-accent-yellow px-2 py-1 rounded-full bg-base-darker text-xs">Scheme</span>
|
||||||
<span class="text-accent-yellow px-2 py-1 rounded-full bg-base-darker text-xs">Guile</span>
|
<span class="text-accent-yellow px-2 py-1 rounded-full bg-base-darker text-xs">Guile</span>
|
||||||
<span class="text-accent-yellow px-2 py-1 rounded-full bg-base-darker text-xs">CLI</span>
|
<span class="text-accent-yellow px-2 py-1 rounded-full bg-base-darker text-xs">CLI</span>
|
||||||
</div>
|
</div>
|
||||||
<a href="#" class="text-accent-cyan hover:text-accent-purple transition-colors">Coming Soon
|
<a href="#" class="text-accent-cyan hover:text-accent-purple transition-colors">Coming Soon
|
||||||
→</a>
|
→</a>
|
||||||
</article>
|
</article>
|
||||||
|
|
||||||
<!-- Add Project Card -->
|
<!-- Add Project Card -->
|
||||||
<article
|
<article
|
||||||
class="bg-base-bg p-6 rounded-lg shadow-lg border border-palenight-400/20 hover:border-accent-purple/40 transition-colors flex items-center justify-center">
|
class="bg-base-bg p-6 rounded-lg shadow-lg border border-palenight-400/20 hover:border-accent-purple/40 transition-colors flex items-center justify-center">
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
<p class="text-palenight-100 mb-2">More projects coming soon!</p>
|
<p class="text-palenight-100 mb-2">More projects coming soon!</p>
|
||||||
<p class="text-accent-cyan">Stay tuned...</p>
|
<p class="text-accent-cyan">Stay tuned...</p>
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<!-- About Section -->
|
<!-- About Section -->
|
||||||
<section id="about" class="py-16 bg-base-bg">
|
<section id="about" class="py-16 bg-base-bg">
|
||||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
|
<div class="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
|
||||||
<div>
|
<div>
|
||||||
<h2 class="text-3xl font-serif font-bold text-accent-yellow mb-6">About Me</h2>
|
<h2 class="text-3xl font-serif font-bold text-accent-yellow mb-6">About Me</h2>
|
||||||
<p class="text-palenight-100 mb-4">
|
<p class="text-palenight-100 mb-4">
|
||||||
With over 20 years in the electrical engineering field, I've had the privilege of working on
|
With over 20 years in the electrical engineering field, I've had the privilege of working on
|
||||||
groundbreaking projects across the Middle East. My journey has been marked by continuous
|
groundbreaking projects across the Middle East. My journey has been marked by continuous
|
||||||
learning, cultural exploration, and technological innovation.
|
learning, cultural exploration, and technological innovation.
|
||||||
</p>
|
</p>
|
||||||
<p class="text-palenight-100 mb-4">
|
<p class="text-palenight-100 mb-4">
|
||||||
Beyond my professional work, I'm passionate about technology, particularly static site
|
Beyond my professional work, I'm passionate about technology, particularly static site
|
||||||
generation, Scheme programming, and tools like GNU Guix and Haunt. This blog is where I
|
generation, Scheme programming, and tools like GNU Guix and Haunt. This blog is where I
|
||||||
share my experiences, insights, and the lessons learned along the way.
|
share my experiences, insights, and the lessons learned along the way.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="bg-base-darker p-8 rounded-lg shadow-md border border-palenight-400/20">
|
<div class="bg-base-darker p-8 rounded-lg shadow-md border border-palenight-400/20">
|
||||||
<h3 class="text-xl font-bold text-accent-yellow mb-4">Areas of Focus</h3>
|
<h3 class="text-xl font-bold text-accent-yellow mb-4">Areas of Focus</h3>
|
||||||
<ul class="space-y-3">
|
<ul class="space-y-3">
|
||||||
<li class="flex items-center text-palenight-100">
|
<li class="flex items-center text-palenight-100">
|
||||||
<svg class="w-5 h-5 text-accent-blue mr-2" fill="currentColor" viewBox="0 0 20 20">
|
<svg class="w-5 h-5 text-accent-blue mr-2" fill="currentColor" viewBox="0 0 20 20">
|
||||||
<path fill-rule="evenodd"
|
<path fill-rule="evenodd"
|
||||||
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"
|
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"
|
||||||
clip-rule="evenodd"></path>
|
clip-rule="evenodd"></path>
|
||||||
</svg>
|
</svg>
|
||||||
Electrical Engineering
|
Electrical Engineering
|
||||||
</li>
|
</li>
|
||||||
<li class="flex items-center text-palenight-100">
|
<li class="flex items-center text-palenight-100">
|
||||||
<svg class="w-5 h-5 text-accent-blue mr-2" fill="currentColor" viewBox="0 0 20 20">
|
<svg class="w-5 h-5 text-accent-blue mr-2" fill="currentColor" viewBox="0 0 20 20">
|
||||||
<path fill-rule="evenodd"
|
<path fill-rule="evenodd"
|
||||||
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"
|
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"
|
||||||
clip-rule="evenodd"></path>
|
clip-rule="evenodd"></path>
|
||||||
</svg>
|
</svg>
|
||||||
Static Site Generation
|
Static Site Generation
|
||||||
</li>
|
</li>
|
||||||
<li class="flex items-center text-palenight-100">
|
<li class="flex items-center text-palenight-100">
|
||||||
<svg class="w-5 h-5 text-accent-blue mr-2" fill="currentColor" viewBox="0 0 20 20">
|
<svg class="w-5 h-5 text-accent-blue mr-2" fill="currentColor" viewBox="0 0 20 20">
|
||||||
<path fill-rule="evenodd"
|
<path fill-rule="evenodd"
|
||||||
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"
|
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"
|
||||||
clip-rule="evenodd"></path>
|
clip-rule="evenodd"></path>
|
||||||
</svg>
|
</svg>
|
||||||
Scheme Programming
|
Scheme Programming
|
||||||
</li>
|
</li>
|
||||||
<li class="flex items-center text-palenight-100">
|
<li class="flex items-center text-palenight-100">
|
||||||
<svg class="w-5 h-5 text-accent-blue mr-2" fill="currentColor" viewBox="0 0 20 20">
|
<svg class="w-5 h-5 text-accent-blue mr-2" fill="currentColor" viewBox="0 0 20 20">
|
||||||
<path fill-rule="evenodd"
|
<path fill-rule="evenodd"
|
||||||
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"
|
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"
|
||||||
clip-rule="evenodd"></path>
|
clip-rule="evenodd"></path>
|
||||||
</svg>
|
</svg>
|
||||||
Middle Eastern Culture
|
Middle Eastern Culture
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<!-- Contact Section -->
|
<!-- Contact Section -->
|
||||||
<section id="contact" class="py-16 bg-base-darker">
|
<section id="contact" class="py-16 bg-base-darker">
|
||||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
<h2 class="text-3xl font-serif font-bold text-accent-yellow mb-6">Get in Touch</h2>
|
<h2 class="text-3xl font-serif font-bold text-accent-yellow mb-6">Get in Touch</h2>
|
||||||
<p class="text-palenight-100 mb-8">
|
<p class="text-palenight-100 mb-8">
|
||||||
Interested in connecting? Feel free to reach out for discussions about technology, engineering,
|
Interested in connecting? Feel free to reach out for discussions about technology, engineering,
|
||||||
or sharing travel stories.
|
or sharing travel stories.
|
||||||
</p>
|
</p>
|
||||||
<a href="mailto:glenn@glenneth.org"
|
<a href="mailto:glenn@glenneth.org"
|
||||||
class="inline-flex items-center px-6 py-3 border border-accent-blue text-base font-medium rounded-md text-accent-blue hover:bg-accent-blue hover:text-base-bg transition-colors">
|
class="inline-flex items-center px-6 py-3 border border-accent-blue text-base font-medium rounded-md text-accent-blue hover:bg-accent-blue hover:text-base-bg transition-colors">
|
||||||
Send a Message
|
Send a Message
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<footer class="bg-base-darker text-palenight-200 py-12 border-t border-palenight-400/20">
|
<footer class="bg-base-darker text-palenight-200 py-12 border-t border-palenight-400/20">
|
||||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
<p class="text-palenight-300">© 2024 Glenn Thompson. All rights reserved.</p>
|
<p class="text-palenight-300">© 2026 Glenn Thompson. All rights reserved.</p>
|
||||||
<div class="webring-text mt-6">
|
<div class="webring-text mt-6">
|
||||||
<p class="text-palenight-300">I am part of the <a href="https://systemcrafters.net" target="_blank"
|
<p class="text-palenight-300">I am part of the <a href="https://systemcrafters.net" target="_blank"
|
||||||
class="text-accent-blue hover:text-accent-cyan">System Crafters</a> webring:</p>
|
class="text-accent-blue hover:text-accent-cyan">System Crafters</a> webring:</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="craftering mt-2 flex items-center justify-center gap-4 text-accent-blue">
|
<div class="craftering mt-2 flex items-center justify-center gap-4 text-accent-blue">
|
||||||
<a href="https://craftering.systemcrafters.net/@glenneth/previous"
|
<a href="https://craftering.systemcrafters.net/@glenneth/previous"
|
||||||
class="hover:text-accent-cyan">←</a>
|
class="hover:text-accent-cyan">←</a>
|
||||||
<a href="https://craftering.systemcrafters.net/" class="hover:text-accent-cyan">craftering</a>
|
<a href="https://craftering.systemcrafters.net/" class="hover:text-accent-cyan">craftering</a>
|
||||||
<a href="https://craftering.systemcrafters.net/@glenneth/next" class="hover:text-accent-cyan">→</a>
|
<a href="https://craftering.systemcrafters.net/@glenneth/next" class="hover:text-accent-cyan">→</a>
|
||||||
</div>
|
</div>
|
||||||
<p class="text-palenight-300 mt-2">
|
<p class="text-palenight-300 mt-2">
|
||||||
<a href="mailto:glenn@glenneth.org"
|
<a href="mailto:glenn@glenneth.org"
|
||||||
class="text-accent-blue hover:text-accent-cyan transition-colors">glenn@glenneth.org</a> |
|
class="text-accent-blue hover:text-accent-cyan transition-colors">glenn@glenneth.org</a> |
|
||||||
<a href="https://glenneth.org"
|
<a href="https://glenneth.org"
|
||||||
class="text-accent-blue hover:text-accent-cyan transition-colors">glenneth.org</a>
|
class="text-accent-blue hover:text-accent-cyan transition-colors">glenneth.org</a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|
@ -223,15 +223,28 @@ async function updateIndexWithSummaries() {
|
||||||
|
|
||||||
// Extract metadata
|
// Extract metadata
|
||||||
const metadata = {};
|
const metadata = {};
|
||||||
content.replace(/^---\n([\s\S]*?)\n---\n/, (_, frontMatter) => {
|
// More flexible regex to handle different line endings
|
||||||
frontMatter.split('\n').forEach(line => {
|
const frontMatterMatch = content.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n/);
|
||||||
const [key, ...valueParts] = line.split(':');
|
if (frontMatterMatch) {
|
||||||
if (key && valueParts.length > 0) {
|
const frontMatter = frontMatterMatch[1];
|
||||||
metadata[key.trim()] = valueParts.join(':').trim();
|
frontMatter.split(/\r?\n/).forEach(line => {
|
||||||
|
const colonIndex = line.indexOf(':');
|
||||||
|
if (colonIndex > 0) {
|
||||||
|
const key = line.substring(0, colonIndex).trim();
|
||||||
|
let value = line.substring(colonIndex + 1).trim();
|
||||||
|
|
||||||
|
// Remove quotes if present
|
||||||
|
if ((value.startsWith('"') && value.endsWith('"')) ||
|
||||||
|
(value.startsWith("'") && value.endsWith("'"))) {
|
||||||
|
value = value.slice(1, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key && value) {
|
||||||
|
metadata[key] = value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return '';
|
}
|
||||||
});
|
|
||||||
|
|
||||||
// Extract summary
|
// Extract summary
|
||||||
const summary = extractSummary(content);
|
const summary = extractSummary(content);
|
||||||
|
|
@ -239,18 +252,45 @@ async function updateIndexWithSummaries() {
|
||||||
// Parse and format the date
|
// Parse and format the date
|
||||||
let formattedDate = '';
|
let formattedDate = '';
|
||||||
let isoDate = '';
|
let isoDate = '';
|
||||||
|
|
||||||
|
if (!metadata.date) {
|
||||||
|
console.warn(`No date found for ${file}`);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Handle date formats like "2024-04-08 16:50" or "2024-04-08"
|
let dateStr = '';
|
||||||
const dateStr = metadata.date.split(' ')[0];
|
|
||||||
|
// Handle different date formats
|
||||||
|
if (typeof metadata.date === 'string') {
|
||||||
|
// String format: "2024-04-08 16:50" or "2024-04-08"
|
||||||
|
dateStr = metadata.date.split(' ')[0];
|
||||||
|
} else if (typeof metadata.date === 'number') {
|
||||||
|
// Number format: 2025-04-02 (YAML parsed as number)
|
||||||
|
dateStr = metadata.date.toString();
|
||||||
|
} else if (metadata.date instanceof Date) {
|
||||||
|
// Date object
|
||||||
|
dateStr = metadata.date.toISOString().split('T')[0];
|
||||||
|
} else {
|
||||||
|
// Fallback: convert to string and extract date part
|
||||||
|
dateStr = String(metadata.date).split(' ')[0];
|
||||||
|
}
|
||||||
|
|
||||||
const date = new Date(dateStr);
|
const date = new Date(dateStr);
|
||||||
formattedDate = date.toLocaleDateString('en-US', {
|
if (!isNaN(date.getTime())) {
|
||||||
year: 'numeric',
|
formattedDate = date.toLocaleDateString('en-US', {
|
||||||
month: 'long',
|
year: 'numeric',
|
||||||
day: 'numeric'
|
month: 'long',
|
||||||
});
|
day: 'numeric'
|
||||||
isoDate = dateStr;
|
});
|
||||||
|
isoDate = dateStr;
|
||||||
|
} else {
|
||||||
|
console.warn(`Invalid date format for ${file}: ${metadata.date} (type: ${typeof metadata.date})`);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(`Error parsing date for ${file}:`, e);
|
console.error(`Error parsing date for ${file}:`, e);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse tags
|
// Parse tags
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -24,7 +24,7 @@
|
||||||
"autoprefixer": "^10.4.14",
|
"autoprefixer": "^10.4.14",
|
||||||
"cheerio": "^1.0.0",
|
"cheerio": "^1.0.0",
|
||||||
"concurrently": "^8.0.1",
|
"concurrently": "^8.0.1",
|
||||||
"live-server": "^1.2.2",
|
"live-server": "^1.2.0",
|
||||||
"marked": "^11.1.0",
|
"marked": "^11.1.0",
|
||||||
"postcss": "^8.4.21",
|
"postcss": "^8.4.21",
|
||||||
"tailwindcss": "^3.3.0"
|
"tailwindcss": "^3.3.0"
|
||||||
|
|
|
||||||
|
|
@ -12,9 +12,9 @@ const options = {
|
||||||
// Footer template
|
// Footer template
|
||||||
const footer = `
|
const footer = `
|
||||||
<footer class="bg-base-darker text-palenight-200 py-12 border-t border-palenight-400/20">
|
<footer class="bg-base-darker text-palenight-200 py-12 border-t border-palenight-400/20">
|
||||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
<div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
<p class="text-palenight-300">© 2024 Glenn Thompson. All rights reserved.</p>
|
<p class="text-palenight-300">© 2026 Glenn Thompson. All rights reserved.</p>
|
||||||
<div class="webring-text mt-6">
|
<div class="webring-text mt-6">
|
||||||
<p class="text-palenight-300">I am part of the <a href="https://systemcrafters.net" target="_blank" class="text-accent-blue hover:text-accent-cyan">System Crafters</a> webring:</p>
|
<p class="text-palenight-300">I am part of the <a href="https://systemcrafters.net" target="_blank" class="text-accent-blue hover:text-accent-cyan">System Crafters</a> webring:</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Binary file not shown.
Loading…
Reference in New Issue