Refactor site content and worflow

Since the site is now Gemini first, it doesn't make sense to use Markdown. In this commit I am refactoring the site generator to remove lowdown and frontmatter dependencies.
This commit is contained in:
Erick Ruiz de Chavez 2025-01-08 05:38:01 -05:00
parent 0bd550b561
commit 40121b1c49
19 changed files with 116 additions and 77 deletions

1
.gitignore vendored
View file

@ -1,2 +1,3 @@
__pycache__
.venv .venv
_capsule _capsule

View file

@ -3,7 +3,7 @@ env := development
default: clean generate default: clean generate
clean: clean:
\rm -rf _capsule \rm -rf _capsule __pycache__
generate: generate:
docker compose run --rm -e GEMINI_ENV=${env} gemini docker compose run --rm -e GEMINI_ENV=${env} gemini

View file

@ -1,13 +1,10 @@
from slugify import slugify from slugify import slugify
import _utils
title = input("Enter draft's title: ") title = input("Enter draft's title: ")
slug = slugify(title) slug = slugify(title)
body = f""" fm = _utils.loads("---\n---\n")
--- fm.metadata["title"] = title
title: {title}
---
"""
with open(f"_drafts/{slug}.gmi", mode="w", encoding="utf8") as file: with open(f"_drafts/{slug}.gmi", mode="w", encoding="utf8") as file:
file.write(body) file.write(_utils.dumps(fm))

View file

@ -1,8 +1,6 @@
--- ---
links: inline
title: Live Long and Prosper with These Tools title: Live Long and Prosper with These Tools
--- ---
I'm not entirely sure why, but I love trying out and testing productivity tools—especially those geared toward programming. Over the years, I've explored and used a wide variety of tools, and these are the ones I can't live without. Below, I've listed them in alphabetical order. For each, I'll include a brief description and explain why it stands out to me. When time and inspiration allow, I plan to write dedicated articles diving deeper into each tool. I'll also do my best to keep this list updated as I discover new favorites or stop using the current ones. I'm not entirely sure why, but I love trying out and testing productivity tools—especially those geared toward programming. Over the years, I've explored and used a wide variety of tools, and these are the ones I can't live without. Below, I've listed them in alphabetical order. For each, I'll include a brief description and explain why it stands out to me. When time and inspiration allow, I plan to write dedicated articles diving deeper into each tool. I'll also do my best to keep this list updated as I discover new favorites or stop using the current ones.
To help you understand the labels I've used, here's a quick guide to the emojis and letters in parentheses you'll see next to each tool: To help you understand the labels I've used, here's a quick guide to the emojis and letters in parentheses you'll see next to each tool:
@ -76,4 +74,4 @@ To help you understand the labels I've used, here's a quick guide to the emojis
## Honorary Mentions ## Honorary Mentions
- Keyboard Maestro (💻,1⃣,🌐) - Keyboard Maestro (💻,1⃣,🌐)

View file

@ -0,0 +1,6 @@
---
title: 'Prime Directive: Minimalism and Efficiency with Gemini Protocol'
---
Just a couple of weeks ago I restarted my site with the idea of keep a minimalist approach, focused on content rather than flashy styles or colorful themes. Also for the first time I decided to do a dual hosting to make it available via HTTPS and Gemini (Protocol).
An idea I've been floating on my head for a couple of days was that, since HTTPS site was already pretty basic in terms of styles and layout, why not just somehow serve the same content I have for Gemini. This morning, this idea materialized thanks to a small proxy tool called Kineto. This tool is a proxy that allows serving a single Gemini Capsule to regular web browsers. And, after making a few tweaks to my code and deployment I was able to remove Jekyll completely and just keep the minimal parts.

View file

@ -1,9 +1,8 @@
import glob import glob
import os import os
import subprocess
from datetime import datetime from datetime import datetime
import frontmatter import _utils
if not os.path.exists("_capsule"): if not os.path.exists("_capsule"):
os.makedirs("_capsule") os.makedirs("_capsule")
@ -19,11 +18,11 @@ with open("_includes/footer.gmi", mode="r", encoding="utf8") as file:
with open("_includes/links.gmi", mode="r", encoding="utf8") as file: with open("_includes/links.gmi", mode="r", encoding="utf8") as file:
links_body = file.read() links_body = file.read()
articles = glob.glob("_posts/*.md") articles = glob.glob("_posts/*.gmi")
articles.sort() articles.sort()
if os.getenv("GEMINI_ENV") != "production": if os.getenv("GEMINI_ENV") != "production":
articles += glob.glob("_drafts/*.md") articles += glob.glob("_drafts/*.gmi")
today = datetime.today().strftime("%F") today = datetime.today().strftime("%F")
year = datetime.today().strftime("%Y") year = datetime.today().strftime("%Y")
@ -31,21 +30,12 @@ year = datetime.today().strftime("%Y")
articles_list = [] articles_list = []
for article in articles: for article in articles:
gmi = article.replace("_posts/", "").replace("_drafts/", "").replace(".md", ".gmi") gmi = article.replace("_posts/", "").replace("_drafts/", "")
fm = frontmatter.load(article) fm = _utils.load(article)
article_title = fm.get("title") article_title = fm.metadata["title"]
article_date = fm.get("date") article_date = fm.metadata.get("date")
article_content = fm.content
links = fm.get("links", "end")
result = subprocess.run(
["lowdown", "-tgemini", f"--gemini-link-{links}", "--out-no-smarty", article],
capture_output=True,
check=True,
text=True,
)
article_content = result.stdout
if article_date is None: if article_date is None:
article_date = today article_date = today
@ -68,13 +58,8 @@ for article in articles:
articles_list.sort(reverse=True) articles_list.sort(reverse=True)
result = subprocess.run( fm = _utils.load("index.gmi")
["lowdown", "-tgemini", "index.md"], home_content = fm.content
capture_output=True,
check=True,
text=True,
)
home_content = result.stdout
body = ( body = (
home_body.replace("%%header%%", header_body) home_body.replace("%%header%%", header_body)

View file

@ -1,3 +1 @@
© %%year%% Erick Ruiz de Chavez
© %%year%% Erick Ruiz de Chavez

View file

@ -1 +1 @@
# Erick Ruiz de Chavez # Erick Ruiz de Chavez

View file

@ -2,4 +2,4 @@
=> https://linkedin.com/in/erickruizdechavez LinkedIn => https://linkedin.com/in/erickruizdechavez LinkedIn
=> https://github.com/eruizdechavez GitHub => https://github.com/eruizdechavez GitHub
=> https://erick.social/@erick Fediverse => https://erick.social/@erick Fediverse

View file

@ -1,7 +1,12 @@
%%header%% %%header%%
=> / Front page => / Front page
## %%title%% ## %%title%%
%%body%% %%body%%
%%links%% %%links%%
%%footer%% %%footer%%

View file

@ -1,6 +1,11 @@
%%header%% %%header%%
%%body%% %%body%%
## Articles ## Articles
%%articles%% %%articles%%
%%links%% %%links%%
%%footer%% %%footer%%

View file

@ -0,0 +1,11 @@
---
title: 'Regenerating My Blog: A Fresh Start'
date: 2024-12-22 00:45 +0000
---
Hey there! Looks like I'm back to writing after some time away. Over the years, I've started many blogs and personal sites, experimenting with different technologies and styles. And here I am again, excited to share my thoughts with you.
Even though I've never considered myself a great writer, the idea of having a blog to share my thoughts, experiences, and ideas has always been in the back of my mind. This time, I'm keeping it simple—sharing small bits whenever inspiration strikes.
The biggest difference this time is how I'm publishing the site and blog. In the past, I've used various tools like WordPress or Jekyll. This time, I'm back on Jekyll, which somehow feels intuitive and easy to use, even with zero Ruby experience. However, there's one key change: I'm also sharing and publishing the same content as a Gemlog—a blog hosted and shared using the Gemini Protocol. There are plenty of great articles about Gemini out there, and I might write about it briefly in a future post.
Feel free to use any of my social links to connect or share your thoughts. I'm looking forward to hearing from you and sharing this renewed journey. Thanks for stopping by!

View file

@ -1,12 +0,0 @@
---
title: 'Regenerating My Blog: A Fresh Start'
date: 2024-12-22 00:45 +0000
---
Hey there! Looks like Im back to writing after some time away. Over the years, Ive started many blogs and personal sites, experimenting with different technologies and styles. And here I am again, excited to share my thoughts with you.
Even though Ive never considered myself a great writer, the idea of having a blog to share my thoughts, experiences, and ideas has always been in the back of my mind. This time, Im keeping it simple—sharing small bits whenever inspiration strikes.
The biggest difference this time is how Im publishing the site and blog. In the past, Ive used various tools like WordPress or Jekyll. This time, Im back on Jekyll, which somehow feels intuitive and easy to use, even with zero Ruby experience. However, theres one key change: Im also sharing and publishing the same content as a Gemlog—a blog hosted and shared using the Gemini Protocol. There are plenty of great articles about Gemini out there, and I might write about it briefly in a future post.
Feel free to use any of my social links to connect or share your thoughts. Im looking forward to hearing from you and sharing this renewed journey. Thanks for stopping by!

View file

@ -2,7 +2,6 @@
title: 'Energy Shields at Minimum: Automating Laptop Power Mode' title: 'Energy Shields at Minimum: Automating Laptop Power Mode'
date: 2024-12-29 12:35 +0000 date: 2024-12-29 12:35 +0000
--- ---
I love automation—not just home automation but anything that simplifies my life. For example, I use a Shortcut on my iPhone that automatically turns on Low Power Mode when the battery drops below a certain percentage. I love automation—not just home automation but anything that simplifies my life. For example, I use a Shortcut on my iPhone that automatically turns on Low Power Mode when the battery drops below a certain percentage.
This morning, while working on my laptop, I realized that macOS allows Low Power Mode to be set to "always on" when on battery power, but it doesn't provide an option like "only when the battery level is below X%." Naturally, I decided to create a script to achieve the same functionality on my laptop that I already enjoy on my phone. This morning, while working on my laptop, I realized that macOS allows Low Power Mode to be set to "always on" when on battery power, but it doesn't provide an option like "only when the battery level is below X%." Naturally, I decided to create a script to achieve the same functionality on my laptop that I already enjoy on my phone.

View file

@ -3,9 +3,10 @@ import os
import sys import sys
from datetime import UTC, datetime from datetime import UTC, datetime
import frontmatter import _utils
articles = glob.glob("_drafts/*.md") articles = glob.glob("_drafts/*.gmi")
print(articles)
articles.sort() articles.sort()
titles = [] titles = []
@ -14,8 +15,8 @@ if len(articles) == 0:
sys.exit(1) sys.exit(1)
for article in articles: for article in articles:
fm = frontmatter.load(article) fm = _utils.load(article)
titles.append(fm.get("title")) titles.append(fm.metadata["title"])
print("\nAvailable drafts:\n") print("\nAvailable drafts:\n")
@ -44,7 +45,8 @@ now = datetime.now(UTC)
file_date = now.strftime("%F") file_date = now.strftime("%F")
frontmatter_date = now.strftime("%F %H:%m %z") frontmatter_date = now.strftime("%F %H:%m %z")
fm = frontmatter.load(article)
fm = _utils.load(article)
fm.metadata["date"] = frontmatter_date fm.metadata["date"] = frontmatter_date
with open( with open(
@ -52,7 +54,7 @@ with open(
mode="w", mode="w",
encoding="utf8", encoding="utf8",
) as file: ) as file:
file.write(frontmatter.dumps(fm)) file.write(_utils.dumps(fm))
try: try:
os.remove(article) os.remove(article)

View file

@ -3,9 +3,9 @@ import os
import sys import sys
from datetime import datetime from datetime import datetime
import frontmatter import _utils
articles = glob.glob("_posts/*.md") articles = glob.glob("_posts/*.gmi")
articles.sort(reverse=True) articles.sort(reverse=True)
titles = [] titles = []
@ -14,8 +14,8 @@ if len(articles) == 0:
sys.exit(1) sys.exit(1)
for article in articles: for article in articles:
fm = frontmatter.load(article) fm = _utils.load(article)
titles.append(fm.get("title")) titles.append(fm.metadata["title"])
print("\nAvailable articles:\n") print("\nAvailable articles:\n")
@ -40,7 +40,7 @@ while index < 0 or index > len(articles):
except (ValueError, IndexError): except (ValueError, IndexError):
selection = input("Enter a number (0 to exit): ") selection = input("Enter a number (0 to exit): ")
fm = frontmatter.load(article) fm = _utils.load(article)
file_date = datetime.fromisoformat(fm.metadata["date"]).strftime("%Y-%m-%d") file_date = datetime.fromisoformat(fm.metadata["date"]).strftime("%Y-%m-%d")
del fm.metadata["date"] del fm.metadata["date"]
@ -49,7 +49,7 @@ with open(
mode="w", mode="w",
encoding="utf8", encoding="utf8",
) as file: ) as file:
file.write(frontmatter.dumps(fm)) file.write(_utils.dumps(fm))
try: try:
os.remove(article) os.remove(article)

50
_utils.py Normal file
View file

@ -0,0 +1,50 @@
from dataclasses import dataclass, field
import yaml
@dataclass
class Article:
metadata: dict = field(default_factory=dict)
content: str = ""
def load(file_name) -> Article:
content = ""
with open(file=file_name, mode="r", encoding="utf8") as file:
content = file.read()
return loads(content)
def loads(content: str) -> Article:
lines = content.splitlines()
start = -1
end = -1
for index, line in enumerate(lines):
if line.startswith("---"):
if start == -1:
start = index
elif end == -1:
end = index
break
if start == -1 or end == -1:
raise ValueError("Missing frontmatter delimiters")
metadata = lines[start + 1 : end]
content = lines[end + 1 :]
metadata = yaml.safe_load("\n".join(metadata))
if not metadata:
metadata = {}
return Article(
metadata=metadata,
content="\n".join(content),
)
def dumps(article: Article) -> str:
return f"""---\n{yaml.dump(article.metadata)}---\n{article.content}\n"""

View file

@ -1,14 +1,12 @@
--- ---
layout: home
--- ---
Hi 👋, I'm Erick!
Hi 👋, Im Erick! I live in the U.S. with my wife, Lizzy, and our dogter, Masha. I'm fluent in both English and Spanish.
I live in the U.S. with my wife, Lizzy, and our dogter, Masha. Im fluent in both English and Spanish. I work as a Software Engineer at Bloomberg, where I'm passionate about software architecture, automation, and enhancing the developer experience.
I work as a Software Engineer at Bloomberg, where Im passionate about software architecture, automation, and enhancing the developer experience. Giving back to the community is something I truly enjoy. I do this through mentorships, conducting mock interviews, and hosting knowledge-sharing sessions to pass on what I've learned throughout my career.
Giving back to the community is something I truly enjoy. I do this through mentorships, conducting mock interviews, and hosting knowledge-sharing sessions to pass on what Ive learned throughout my career.
In my free time, I love watching movies and TV shows, listening to audiobooks and music, playing video games with Lizzy, and upgrading our home with smart automation. In my free time, I love watching movies and TV shows, listening to audiobooks and music, playing video games with Lizzy, and upgrading our home with smart automation.

View file

@ -1,7 +1,3 @@
packaging==24.2
pyparsing==3.1.4
python-frontmatter==1.1.0
python-slugify==8.0.4 python-slugify==8.0.4
PyYAML==6.0.2 PyYAML==6.0.2
setuptools==70.3.0
text-unidecode==1.3 text-unidecode==1.3