Repos / hi.imnhan.com / fa8c6f1169
commit fa8c6f1169ed4c39d337188915b709571ff07a0c
Author: Nhân <hi@imnhan.com>
Date: Fri Aug 25 19:37:33 2023 +0700
s4g: first revision
diff --git a/s4g/index.dj b/s4g/index.dj
index 4a2c22b..fac832a 100644
--- a/s4g/index.dj
+++ b/s4g/index.dj
@@ -4,62 +4,66 @@ Description: It just had to happen at some point.
Thumb: series-footer.png
---
-This blog is now built with [s4g][1]---a static site generator (SSG) made by
-yours truly.
+This blog is now built with [s4g][1]---an experimental static site generator.
## Why?
-What sets s4g apart from typical SSGs is that it doesn't separate source code
-and output. For a concrete example, [Pelican][2] would read source from the
+Unlike typical static site generators, s4g doesn't separate source code and
+output. For a concrete example, [Pelican][2] would read source from the
/content/ dir and write a complete website to /output/, like this:
```
my-blog
├── content <-- source
-│ ├── pages
-│ │ ├── about.md
-│ │ └── home.md
-│ └── posts
-│ ├── first-post.md
-│ └── second-post.md
+│ ├── pages
+│ │ ├── about.md
+│ │ └── home.md
+│ └── posts
+│ ├── first-post.md
+│ └── second-post.md
└── output <-- generated website ready to be served
├── about
- │ └── index.html
+ │ └── index.html
├── home
- │ └── index.html
+ │ └── index.html
└── posts
├── first-post
- │ └── index.html
+ │ └── index.html
└── second-post
└── index.html
```
-While s4g would simply put the processed html right next to its source (s4g
-uses djot instead of markdown, so source files are .dj instead of .md):
-
+s4g, on the other hand, simply looks for .dj files (s4g uses djot instead of
+markdown) and generates a matching .html in the same place:
```
my-blog <-- is both source and serveable website
├── about
-│ ├── index.dj
-│ └── index.html
+│ ├── index.dj
+│ └── index.html
├── home
-│ ├── index.dj
-│ └── index.html
+│ ├── index.dj
+│ └── index.html
└── posts
├── first-post
- │ ├── index.dj
- │ └── index.html
+ │ index.dj
+ │ index.html
└── second-post
├── index.dj
└── index.html
```
-This simplifies a few things:
+This is certainly not a novel idea. In fact, one can glob over their dir with a
+pandoc command and [be done with it][8]. The fun starts when you want to
+generate things that need aggregate data, a home index, series index, RSS feed,
+etc... While we're at it, why not add rebuild-on-save, livereload, the whole
+shebang? One thing led to another, and s4g was born.
+
+This dumb approach to paths simplifies a few things:
### 1. Folder layout _is_ website layout
-With Pelican you typically need to supply a few url patterns to let
+With Pelican we typically need to supply a few url patterns to let
the generator know where to put the generated html:
```
@@ -70,13 +74,13 @@ ARTICLE_LANG_URL = "posts/{slug}-{lang}/"
ARTICLE_LANG_SAVE_AS = "posts/{slug}-{lang}/index.html"
```
-While with s4g you just put the .dj file where you want the .html to end up.
+While with s4g we just put the .dj file where we want the .html to end up.
### 2. Obvious static asset placement
A post typically links to static assets such as images or videos.
Ideally we want to put these assets in the same place as their content file.
-This is surprisingly tricky with Pelican: you have to either throw every
+This is surprisingly tricky with Pelican: we have to either throw every
asset of every post in one big static folder, or carefully tweak the url
settings and use a custom link syntax, as per [their docs][3]:
@@ -118,12 +122,12 @@ Here's a [live example][5] from my blog:
```
movie-streaming/ <-- series home
├── gflick <-- post
-│ ├── index.dj
-│ └── index.html
+│ ├── index.dj
+│ └── index.html
├── gflick-fixed <-- post
-│ ├── gflick_01_mobile.png
-│ ├── index.dj
-│ └── index.html
+│ ├── gflick_01_mobile.png
+│ ├── index.dj
+│ └── index.html
├── index.dj
├── index.html
└── put.io <-- post
@@ -160,22 +164,22 @@ Each post in the series has a extra header and footer:
### Miscellaneous blog things
-An RSS feed is table stakes, so that's what you get out of the box.
+An RSS feed is table stakes, so that's what we get out of the box.
Technically it's an Atom feed, but hey, tomaytoes-tomahtoes.
-There's also automatic OpenGraph / Twitter Cards meta tags, so you get those
-sweet preview widgets when sharing your links on social media or rich chat
+There's also automatic OpenGraph / Twitter Cards meta tags, so we get those
+sweet preview widgets when sharing links on social media or rich chat
applications.
-Cool links don't die, but sometimes you do want to change a post's URL. In such
+Cool links don't die, but sometimes we do want to change a post's URL. In such
cases, simply add a line to *_s4g/redirects.txt* that says:
```
old-link/index.html -> new-link/
```
-S4g will then generate an html with the appropriate `<meta
-http-equiv="Refresh" ... >` tag to redirect visitors to your new location. I
+S4g will then generate *old-link/index.html* with the appropriate `<meta
+http-equiv="Refresh" ...>` tag to redirect visitors to the new location. I
heard this works on googlebot too! Anyway, this is how I updated all of my old
lengthy paths e.g. "posts/introducing-mcross-a-minimal-gemini-browser" to
short, typeable paths such as "mcross".
@@ -192,21 +196,9 @@ line number yet), etc.
The livereload turns out to be quite handy: it feels especially nice to edit my
css, save and see the change instantly on my phone browser.
-### Risks
-
-Since source and output live in the same folder, there's a non-zero chance that
-some bug in s4g may eat your source data. I obviously don't want that to
-happen, but I haven't tested it rigorously. Therefore, I only run s4g on
-version-controlled websites, and recommend users do the same.
## Quickstart
-I probably won't bother to write proper documentation any time soon, because
-let's face it: I'm probably going to be s4g's only user.
-
-However, if you're curious enough to tinker with it, the following should
-get you started:
-
```sh
# Install
sudo pacman -Syu nodejs go
@@ -235,6 +227,40 @@ For more elaborate examples, check out the [sample site][6] and [my own
blog][7], which cover hidden posts, deploying on sub-directory paths, custom &
fallback thumbnails, per-post custom templates, series, among other things.
+## Questionables
+
+### Djot?
+
+Imagine markdown but not full of corner cases and highly extensible. I'm glad
+jgm didn't try to fold this into commonmark. Let John Gruber keep his weird toy
+non-spec "format". Let me be clear though, I have no ill will towards
+Gruber---his thing worked for his purposes, but it's a tragedy that we as an
+industry failed to converge on a more technically sound format for lightweight
+text markup.
+
+### Since source and output live in the same folder, will some bug in s4g eat
+my source?
+
+I obviously try to avoid that, but the current code is proof-of-concept
+quality. Therefore, I only run s4g on version-controlled websites, and
+recommend users do the same for now.
+
+### Adding compiled assets to version control sounds... bad?
+
+For programs, probably.
+For websites though, I prefer to keep snapshots of the whole website as it's
+deployed, and be able to roll it back together with the source code. Admittedly
+this makes for noisy diffs sometimes, but I'll be sly here and call it a UI
+problem ;)
+
+### I just looked at the code and holy crap what's with all those (non) data
+structures and nested loops!
+
+Yeah but the whole thing takes about 100ms on my thirty-something-articles
+blog, which is by no means impressive, but not a real hindrance for daily use
+either. If an actual user shows up with a site big enough to have a problem,
+I'll look into optimizing it.
+
[1]: https://github.com/nhanb/s4g
[2]: https://getpelican.com/
[3]: https://docs.getpelican.com/en/4.8.0/content.html#mixed-content-in-the-same-directory
@@ -242,3 +268,4 @@ fallback thumbnails, per-post custom templates, series, among other things.
[5]: https://hi.imnhan.com/movie-streaming/
[6]: https://github.com/nhanb/s4g/tree/master/docs
[7]: https://github.com/nhanb/hi.imnhan.com
+[8]: https://github.com/nhanb/gbvs.saigonfgc.com/blob/26e50c676c3c060310b292f1c520753cf34210fc/build.py
diff --git a/s4g/index.html b/s4g/index.html
index be838c6..5754ef7 100644
--- a/s4g/index.html
+++ b/s4g/index.html
@@ -38,53 +38,57 @@
<h1>s4g is a Stupidly Simple Static Site Generator</h1>
-<p>This blog is now built with <a href="https://github.com/nhanb/s4g">s4g</a>—a static site generator (SSG) made by
-yours truly.</p>
+<p>This blog is now built with <a href="https://github.com/nhanb/s4g">s4g</a>—an experimental static site generator.</p>
<section id="Why">
<h2>Why?</h2>
-<p>What sets s4g apart from typical SSGs is that it doesn’t separate source code
-and output. For a concrete example, <a href="https://getpelican.com/">Pelican</a> would read source from the
+<p>Unlike typical static site generators, s4g doesn’t separate source code and
+output. For a concrete example, <a href="https://getpelican.com/">Pelican</a> would read source from the
/content/ dir and write a complete website to /output/, like this:</p>
<pre><code>my-blog
├── content <-- source
-│ ├── pages
-│ │ ├── about.md
-│ │ └── home.md
-│ └── posts
-│ ├── first-post.md
-│ └── second-post.md
+│ ├── pages
+│ │ ├── about.md
+│ │ └── home.md
+│ └── posts
+│ ├── first-post.md
+│ └── second-post.md
└── output <-- generated website ready to be served
├── about
- │ └── index.html
+ │ └── index.html
├── home
- │ └── index.html
+ │ └── index.html
└── posts
├── first-post
- │ └── index.html
+ │ └── index.html
└── second-post
└── index.html
</code></pre>
-<p>While s4g would simply put the processed html right next to its source (s4g
-uses djot instead of markdown, so source files are .dj instead of .md):</p>
+<p>s4g, on the other hand, simply looks for .dj files (s4g uses djot instead of
+markdown) and generates a matching .html in the same place:</p>
<pre><code>my-blog <-- is both source and serveable website
├── about
-│ ├── index.dj
-│ └── index.html
+│ ├── index.dj
+│ └── index.html
├── home
-│ ├── index.dj
-│ └── index.html
+│ ├── index.dj
+│ └── index.html
└── posts
├── first-post
- │ ├── index.dj
- │ └── index.html
+ │ index.dj
+ │ index.html
└── second-post
├── index.dj
└── index.html
</code></pre>
-<p>This simplifies a few things:</p>
+<p>This is certainly not a novel idea. In fact, one can glob over their dir with a
+pandoc command and <a href="https://github.com/nhanb/gbvs.saigonfgc.com/blob/26e50c676c3c060310b292f1c520753cf34210fc/build.py">be done with it</a>. The fun starts when you want to
+generate things that need aggregate data, a home index, series index, RSS feed,
+etc… While we’re at it, why not add rebuild-on-save, livereload, the whole
+shebang? One thing led to another, and s4g was born.</p>
+<p>This dumb approach to paths simplifies a few things:</p>
<section id="1-Folder-layout-is-website-layout">
<h3>1. Folder layout <em>is</em> website layout</h3>
-<p>With Pelican you typically need to supply a few url patterns to let
+<p>With Pelican we typically need to supply a few url patterns to let
the generator know where to put the generated html:</p>
<pre><code>ARTICLE_PATHS = ["posts"]
ARTICLE_URL = "posts/{slug}/"
@@ -92,13 +96,13 @@ <h3>1. Folder layout <em>is</em> website layout</h3>
ARTICLE_LANG_URL = "posts/{slug}-{lang}/"
ARTICLE_LANG_SAVE_AS = "posts/{slug}-{lang}/index.html"
</code></pre>
-<p>While with s4g you just put the .dj file where you want the .html to end up.</p>
+<p>While with s4g we just put the .dj file where we want the .html to end up.</p>
</section>
<section id="2-Obvious-static-asset-placement">
<h3>2. Obvious static asset placement</h3>
<p>A post typically links to static assets such as images or videos.
Ideally we want to put these assets in the same place as their content file.
-This is surprisingly tricky with Pelican: you have to either throw every
+This is surprisingly tricky with Pelican: we have to either throw every
asset of every post in one big static folder, or carefully tweak the url
settings and use a custom link syntax, as per <a href="https://docs.getpelican.com/en/4.8.0/content.html#mixed-content-in-the-same-directory">their docs</a>:</p>
<blockquote>
@@ -135,12 +139,12 @@ <h3>3. Easy post grouping</h3>
Here’s a <a href="https://hi.imnhan.com/movie-streaming/">live example</a> from my blog:</p>
<pre><code>movie-streaming/ <-- series home
├── gflick <-- post
-│ ├── index.dj
-│ └── index.html
+│ ├── index.dj
+│ └── index.html
├── gflick-fixed <-- post
-│ ├── gflick_01_mobile.png
-│ ├── index.dj
-│ └── index.html
+│ ├── gflick_01_mobile.png
+│ ├── index.dj
+│ └── index.html
├── index.dj
├── index.html
└── put.io <-- post
@@ -168,17 +172,17 @@ <h3>3. Easy post grouping</h3>
</section>
<section id="Miscellaneous-blog-things">
<h3>Miscellaneous blog things</h3>
-<p>An RSS feed is table stakes, so that’s what you get out of the box.
+<p>An RSS feed is table stakes, so that’s what we get out of the box.
Technically it’s an Atom feed, but hey, tomaytoes-tomahtoes.</p>
-<p>There’s also automatic OpenGraph / Twitter Cards meta tags, so you get those
-sweet preview widgets when sharing your links on social media or rich chat
+<p>There’s also automatic OpenGraph / Twitter Cards meta tags, so we get those
+sweet preview widgets when sharing links on social media or rich chat
applications.</p>
-<p>Cool links don’t die, but sometimes you do want to change a post’s URL. In such
+<p>Cool links don’t die, but sometimes we do want to change a post’s URL. In such
cases, simply add a line to <strong>_s4g/redirects.txt</strong> that says:</p>
<pre><code>old-link/index.html -> new-link/
</code></pre>
-<p>S4g will then generate an html with the appropriate <code><meta
-http-equiv="Refresh" ... ></code> tag to redirect visitors to your new location. I
+<p>S4g will then generate <strong>old-link/index.html</strong> with the appropriate <code><meta
+http-equiv="Refresh" ...></code> tag to redirect visitors to the new location. I
heard this works on googlebot too! Anyway, this is how I updated all of my old
lengthy paths e.g. “posts/introducing-mcross-a-minimal-gemini-browser” to
short, typeable paths such as “mcross”.</p>
@@ -194,20 +198,9 @@ <h3>Quality-of-life stuff</h3>
<p>The livereload turns out to be quite handy: it feels especially nice to edit my
css, save and see the change instantly on my phone browser.</p>
</section>
-<section id="Risks">
-<h3>Risks</h3>
-<p>Since source and output live in the same folder, there’s a non-zero chance that
-some bug in s4g may eat your source data. I obviously don’t want that to
-happen, but I haven’t tested it rigorously. Therefore, I only run s4g on
-version-controlled websites, and recommend users do the same.</p>
-</section>
</section>
<section id="Quickstart">
<h2>Quickstart</h2>
-<p>I probably won’t bother to write proper documentation any time soon, because
-let’s face it: I’m probably going to be s4g’s only user.</p>
-<p>However, if you’re curious enough to tinker with it, the following should
-get you started:</p>
<pre><code class="language-sh"># Install
sudo pacman -Syu nodejs go
go install go.imnhan.com/s4g@latest
@@ -230,6 +223,41 @@ <h2>Quickstart</h2>
blog</a>, which cover hidden posts, deploying on sub-directory paths, custom &
fallback thumbnails, per-post custom templates, series, among other things.</p>
</section>
+<section id="Questionables">
+<h2>Questionables</h2>
+<section id="Djot">
+<h3>Djot?</h3>
+<p>Imagine markdown but not full of corner cases and highly extensible. I’m glad
+jgm didn’t try to fold this into commonmark. Let John Gruber keep his weird toy
+non-spec “format”. Let me be clear though, I have no ill will towards
+Gruber—his thing worked for his purposes, but it’s a tragedy that we as an
+industry failed to converge on a more technically sound format for lightweight
+text markup.</p>
+</section>
+<section id="Since-source-and-output-live-in-the-same-folder-will-some-bug-in-s4g-eat-my-source">
+<h3>Since source and output live in the same folder, will some bug in s4g eat
+my source?</h3>
+<p>I obviously try to avoid that, but the current code is proof-of-concept
+quality. Therefore, I only run s4g on version-controlled websites, and
+recommend users do the same for now.</p>
+</section>
+<section id="Adding-compiled-assets-to-version-control-sounds-bad">
+<h3>Adding compiled assets to version control sounds… bad?</h3>
+<p>For programs, probably.
+For websites though, I prefer to keep snapshots of the whole website as it’s
+deployed, and be able to roll it back together with the source code. Admittedly
+this makes for noisy diffs sometimes, but I’ll be sly here and call it a UI
+problem ;)</p>
+</section>
+<section id="I-just-looked-at-the-code-and-holy-crap-what-s-with-all-those-non-data-structures-and-nested-loops">
+<h3>I just looked at the code and holy crap what’s with all those (non) data
+structures and nested loops!</h3>
+<p>Yeah but the whole thing takes about 100ms on my thirty-something-articles
+blog, which is by no means impressive, but not a real hindrance for daily use
+either. If an actual user shows up with a site big enough to have a problem,
+I’ll look into optimizing it.</p>
+</section>
+</section>
</main>