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:
parent
0bd550b561
commit
40121b1c49
19 changed files with 116 additions and 77 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,2 +1,3 @@
|
|||
__pycache__
|
||||
.venv
|
||||
_capsule
|
||||
|
|
2
Makefile
2
Makefile
|
@ -3,7 +3,7 @@ env := development
|
|||
default: clean generate
|
||||
|
||||
clean:
|
||||
\rm -rf _capsule
|
||||
\rm -rf _capsule __pycache__
|
||||
|
||||
generate:
|
||||
docker compose run --rm -e GEMINI_ENV=${env} gemini
|
||||
|
|
13
_draft.py
13
_draft.py
|
@ -1,13 +1,10 @@
|
|||
from slugify import slugify
|
||||
|
||||
import _utils
|
||||
|
||||
title = input("Enter draft's title: ")
|
||||
|
||||
slug = slugify(title)
|
||||
body = f"""
|
||||
---
|
||||
title: {title}
|
||||
---
|
||||
"""
|
||||
|
||||
fm = _utils.loads("---\n---\n")
|
||||
fm.metadata["title"] = title
|
||||
with open(f"_drafts/{slug}.gmi", mode="w", encoding="utf8") as file:
|
||||
file.write(body)
|
||||
file.write(_utils.dumps(fm))
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
---
|
||||
links: inline
|
||||
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.
|
||||
|
||||
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
|
||||
|
||||
- Keyboard Maestro (💻,1️⃣,🌐)
|
||||
- Keyboard Maestro (💻,1️⃣,🌐)
|
|
@ -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.
|
35
_generate.py
35
_generate.py
|
@ -1,9 +1,8 @@
|
|||
import glob
|
||||
import os
|
||||
import subprocess
|
||||
from datetime import datetime
|
||||
|
||||
import frontmatter
|
||||
import _utils
|
||||
|
||||
if not os.path.exists("_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:
|
||||
links_body = file.read()
|
||||
|
||||
articles = glob.glob("_posts/*.md")
|
||||
articles = glob.glob("_posts/*.gmi")
|
||||
articles.sort()
|
||||
|
||||
if os.getenv("GEMINI_ENV") != "production":
|
||||
articles += glob.glob("_drafts/*.md")
|
||||
articles += glob.glob("_drafts/*.gmi")
|
||||
|
||||
today = datetime.today().strftime("%F")
|
||||
year = datetime.today().strftime("%Y")
|
||||
|
@ -31,21 +30,12 @@ year = datetime.today().strftime("%Y")
|
|||
articles_list = []
|
||||
|
||||
for article in articles:
|
||||
gmi = article.replace("_posts/", "").replace("_drafts/", "").replace(".md", ".gmi")
|
||||
gmi = article.replace("_posts/", "").replace("_drafts/", "")
|
||||
|
||||
fm = frontmatter.load(article)
|
||||
article_title = fm.get("title")
|
||||
article_date = fm.get("date")
|
||||
|
||||
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
|
||||
fm = _utils.load(article)
|
||||
article_title = fm.metadata["title"]
|
||||
article_date = fm.metadata.get("date")
|
||||
article_content = fm.content
|
||||
|
||||
if article_date is None:
|
||||
article_date = today
|
||||
|
@ -68,13 +58,8 @@ for article in articles:
|
|||
|
||||
articles_list.sort(reverse=True)
|
||||
|
||||
result = subprocess.run(
|
||||
["lowdown", "-tgemini", "index.md"],
|
||||
capture_output=True,
|
||||
check=True,
|
||||
text=True,
|
||||
)
|
||||
home_content = result.stdout
|
||||
fm = _utils.load("index.gmi")
|
||||
home_content = fm.content
|
||||
|
||||
body = (
|
||||
home_body.replace("%%header%%", header_body)
|
||||
|
|
|
@ -1,3 +1 @@
|
|||
|
||||
|
||||
© %%year%% Erick Ruiz de Chavez
|
||||
© %%year%% Erick Ruiz de Chavez
|
|
@ -1 +1 @@
|
|||
# Erick Ruiz de Chavez
|
||||
# Erick Ruiz de Chavez
|
|
@ -2,4 +2,4 @@
|
|||
|
||||
=> https://linkedin.com/in/erickruizdechavez LinkedIn
|
||||
=> https://github.com/eruizdechavez GitHub
|
||||
=> https://erick.social/@erick Fediverse
|
||||
=> https://erick.social/@erick Fediverse
|
|
@ -1,7 +1,12 @@
|
|||
%%header%%
|
||||
|
||||
=> / Front page
|
||||
|
||||
## %%title%%
|
||||
|
||||
%%body%%
|
||||
|
||||
%%links%%
|
||||
|
||||
|
||||
%%footer%%
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
%%header%%
|
||||
|
||||
%%body%%
|
||||
|
||||
## Articles
|
||||
%%articles%%
|
||||
|
||||
%%links%%
|
||||
|
||||
|
||||
%%footer%%
|
||||
|
|
11
_posts/2024-12-22-regenerating-my-blog-a-fresh-start.gmi
Normal file
11
_posts/2024-12-22-regenerating-my-blog-a-fresh-start.gmi
Normal 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!
|
|
@ -1,12 +0,0 @@
|
|||
---
|
||||
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!
|
|
@ -2,7 +2,6 @@
|
|||
title: 'Energy Shields at Minimum: Automating Laptop Power Mode'
|
||||
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.
|
||||
|
||||
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.
|
14
_publish.py
14
_publish.py
|
@ -3,9 +3,10 @@ import os
|
|||
import sys
|
||||
from datetime import UTC, datetime
|
||||
|
||||
import frontmatter
|
||||
import _utils
|
||||
|
||||
articles = glob.glob("_drafts/*.md")
|
||||
articles = glob.glob("_drafts/*.gmi")
|
||||
print(articles)
|
||||
articles.sort()
|
||||
titles = []
|
||||
|
||||
|
@ -14,8 +15,8 @@ if len(articles) == 0:
|
|||
sys.exit(1)
|
||||
|
||||
for article in articles:
|
||||
fm = frontmatter.load(article)
|
||||
titles.append(fm.get("title"))
|
||||
fm = _utils.load(article)
|
||||
titles.append(fm.metadata["title"])
|
||||
|
||||
print("\nAvailable drafts:\n")
|
||||
|
||||
|
@ -44,7 +45,8 @@ now = datetime.now(UTC)
|
|||
file_date = now.strftime("%F")
|
||||
frontmatter_date = now.strftime("%F %H:%m %z")
|
||||
|
||||
fm = frontmatter.load(article)
|
||||
|
||||
fm = _utils.load(article)
|
||||
fm.metadata["date"] = frontmatter_date
|
||||
|
||||
with open(
|
||||
|
@ -52,7 +54,7 @@ with open(
|
|||
mode="w",
|
||||
encoding="utf8",
|
||||
) as file:
|
||||
file.write(frontmatter.dumps(fm))
|
||||
file.write(_utils.dumps(fm))
|
||||
|
||||
try:
|
||||
os.remove(article)
|
||||
|
|
|
@ -3,9 +3,9 @@ import os
|
|||
import sys
|
||||
from datetime import datetime
|
||||
|
||||
import frontmatter
|
||||
import _utils
|
||||
|
||||
articles = glob.glob("_posts/*.md")
|
||||
articles = glob.glob("_posts/*.gmi")
|
||||
articles.sort(reverse=True)
|
||||
titles = []
|
||||
|
||||
|
@ -14,8 +14,8 @@ if len(articles) == 0:
|
|||
sys.exit(1)
|
||||
|
||||
for article in articles:
|
||||
fm = frontmatter.load(article)
|
||||
titles.append(fm.get("title"))
|
||||
fm = _utils.load(article)
|
||||
titles.append(fm.metadata["title"])
|
||||
|
||||
print("\nAvailable articles:\n")
|
||||
|
||||
|
@ -40,7 +40,7 @@ while index < 0 or index > len(articles):
|
|||
except (ValueError, IndexError):
|
||||
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")
|
||||
del fm.metadata["date"]
|
||||
|
||||
|
@ -49,7 +49,7 @@ with open(
|
|||
mode="w",
|
||||
encoding="utf8",
|
||||
) as file:
|
||||
file.write(frontmatter.dumps(fm))
|
||||
file.write(_utils.dumps(fm))
|
||||
|
||||
try:
|
||||
os.remove(article)
|
||||
|
|
50
_utils.py
Normal file
50
_utils.py
Normal 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"""
|
|
@ -1,14 +1,12 @@
|
|||
---
|
||||
layout: home
|
||||
---
|
||||
Hi 👋, I'm Erick!
|
||||
|
||||
Hi 👋, I’m 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. I’m 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 I’m 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 I've 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.
|
||||
|
|
@ -1,7 +1,3 @@
|
|||
packaging==24.2
|
||||
pyparsing==3.1.4
|
||||
python-frontmatter==1.1.0
|
||||
python-slugify==8.0.4
|
||||
PyYAML==6.0.2
|
||||
setuptools==70.3.0
|
||||
text-unidecode==1.3
|
||||
|
|
Loading…
Reference in a new issue