Live Reload should be easy.
I prefer pure CSS and pure HTML. But opened an exception for Markdown, for the sake of writing posts.
I don't know what you mean by 1, I thought I achieved that with:
<partial src="partials/layout.html">
My fancy content
</partial>
> Just like every dev writing a blog, my first question was: What is the minimum set of features to maintain it comfortably?
Then you created a program in JS that requires NodeJS to run. But cool programs written in JS don't require NodeJS when it's not necessary. They just run in the browser.
PS: Really cool static site generators that shoot for simplicity don't require you to create extra template files written in a new, made-up template language. When you want to create a new post, you give it (a) the static files from your existing site and (b) the markdown for your new post. The "templating" engine inspects your existing posts (incl. e.g. class attributes) and then copies the same document structure into a new file, except with the right stuff (timestamp, title and heading, post content...) substituted in to the places where it's supposed to go.
Yes. I'm looking to remove NodeJS dependency, but I will probably have to switch languages since JS itself doesn't let me read files from disk, to run the preprocessing.
Something like this does the job for you...basically applies the template and whatever metadata you give to the .md file.
for file in *.md; do
pandoc --quiet --template template.html $file -o "${file%.*}.html"
done
But I wanted a flexible way to reuse components. So I need the <partial> trick to support outer and inner partials in the reusable components. For example a form that I want to reuse on some pages, or a custom call to action.
Sorry, I don't think you understand. First, I'm not looking for help finding a tool that does what I describe. Second, that Pandoc invocation doesn't do what I describe. I'm saying no template file.
Let's say you have static site today with your lost post being "2022/03/31/working-on-a-new-tool.html". To author your new post, the tool could derive the template based on what the actual, HTML-formatted version of your last post looks like, and then it would substitute the new post content into the appropriate places. For example, where your previous post has a date stamp indicating it was published on March 31, the tool would put the date of the new post. Where your previous post has the title in an H1 or whathaveyou, your new title would appear. Where the main text of your last post appears, the main text of your new post appears. This would all be written into a new file. There's no need for an explicit template file.
PS: Pandoc doesn't run in the browser, either. You're already going to have your browser open to check the output. Its runtime is both powerful enough, and it's right there, so use it. No need to bring other runtimes into this.
content = """# This is a markdown content"""
from markdown import markdown
with open('output.html', 'w') as f:
f.write(open('template.html').read() % {
'header': 'welcome',
'content': markdown.markdown(content),
'footer': 'amazing company inc'
})
I wanted to be able to create new layouts without touching the precompiler.
To rely only on HTML/CSS/Markdown to code the frontend.
You can't code partials within the HTML file with your solution.
content = """# This is a markdown content"""
with open('output.html', 'w') as f:
f.write(open('template.html').read() % partial({
title: 'Velkommen',
content: markdown.markdown('markdown content')
}))
I really like the fact that partials are handled as HTML-like markup instead of the HTML just happening to be within some other template system. Kudos on that design choice!
Thanks! That made it easier to handle this usecase:
<partial src="partials/layout.html">
My fancy content
</partial>
Because I can use HTML parsers. But now I'm thinking of a way to remove all dependencies, to I will have to get rid of html parser, and find a way to those substitutions without parsing HTML, with just regex replacement.
Nice and simple. One note to the author - you could reduce your line count quite a bit and get a bunch of features for free by using Nunjucks (https://mozilla.github.io/nunjucks/) instead of parsing the template yourself. It handles your partials and variables in the same way plus a whole lot more.
Posts like this demonstrate to me that JavaScript is the modern Perl. The gigantic, vibrant module ecosystem and ease of installing them* is what makes JavaScript/Node.js my default system for getting stuff done quickly.
(* = Well, it was easy, but I feel like this ESM business now means npm/yarn install doesn't Just Work™ in some cases.)
I agree. Sure there are issues but basically node/js is my scripting language. It used to be python but I do so much more JS that I just end up doing everything I can there.
My static site generator is 5500 lines of Java, because the only thing I hate more than software I didn't invent myself is technologies that are fashionable ;-)
To be fair, 10 years is still uncomfortably modern in my book. My tech needs to at least be old enough to drive a car. Ideally it should be old enough to have an existential crisis about how its life is turning out.
... and you can probably build a 100 LOC static page generator in Java as well.
My thing does a lot of weird crap, though. Like it also acts as a Gemini protocol server, you can publish from the web and it pushes every change to a git repo. It also tracks backlinks and re-publishes every page that is mentioned. It also renders from a specialized version of gemtext so there really isn't any standard libraries to use (that I'm aware of).
tangential, but what do people generally do when they want mostly a static site, but a small amount of dynamic content/interactivity here and there? Seems like a common use-case that as sites grow they might want a little bit of not-static here and there.
Obviously not that difficult to add some javascript and APIs if you want, which avoids the need to mix in a different stack while generating the same look-and-feel. Or you can use NGINX/Apache frontend to redirect certain paths to a more traditional dynamic stack/CMS of course. Just curious if there's any "standard" approach or off-the-shelf tooling for that for (eg) Jekyll or similar.
Vercel (with or without Next) is my stack of choice for projects like this.
You can get a site running in Vercel+Next in <2m from ‘git init’.
I use it for https://potato.horse and most PoCs now, but we’ve scaled Vercel+Next to hundreds of thousands of users per day in other projects.
You could also use Netlify with Netlify functions, although I prefer the (slightly) less opinionated way of handing releases and per-commit vanity URLs Vercel offers.
Aaand if you want to get more funky with your approach, check out Astrojs (island architecture: start with static content and sprinkle the interactions on top of it).
You could also try, Elixir + Phoenix + Live View if you want to learn a new tech stack, feed your brain, and… spend a few days yak shaving. Nope, none of the 5 new versions of your blog will be live by the time you’re done, but you’ll become good friends with Erlang and co. Speaking from the experience, I use next when I want my stack to be boring.
It depends *where* said dynamic content/interactivity is desired. If its desired at the page level, such as one page is desired to be dynamic...Then i keep everything else produced by my static site generator (in my case Pelican), and then set up a subdirectory and use php. (PHP because pretty much any web host, VPS provider etc. either already comes with PHP or its pretty easy to setup. But also because i faovr php development for the web.) Your comment about leveraging redirecting to certain paths via nginx/apache is something i've done in the past also...but unless you have a nice (automated, or at least easy) workflow...that could get old fast.
...However, if what you want is dynamic content/interactivity within the context of a page that is served static from your SSG process, then I (reluctantly) resort to javascript (Sorry, my reluctance is because i'm not much of a fan of javascript...and in fact have tried to omit as much of it as reasonable from my projects.)
I'm in a totally different competition: how to get sh*t done quickly, get others to handle the hard parts and get good maintainability so that I can go home sooner?
Read Hugo/Wordpress documentation takes longer than write something like this.
I got this blog running faster that I would if I had to learn a new tool.
This is what JSX is great at, and it's why I wrote a new web framework that basically just uses JSX for server-side views, that work the way I always thought JSX should: it just returns an object that you can then render into a string if you want or transform first. This is also how I made it so you can put <script> and <style> tags into any component, and it'll de-dup them before rendering, so that you can keep your component scripts and HTML close by each other in source.
63 comments
[ 2.2 ms ] story [ 145 ms ] threadI wrote this very simple SSG, and would like to receive feedback on how to simplify code.
Also, I would be happy to fix any bug.
1. Layouts / Template Inheritance
2. Sass Compiler
3. Live Reload
Love the baseline set of tools here though!
> Just like every dev writing a blog, my first question was: What is the minimum set of features to maintain it comfortably?
Then you created a program in JS that requires NodeJS to run. But cool programs written in JS don't require NodeJS when it's not necessary. They just run in the browser.
PS: Really cool static site generators that shoot for simplicity don't require you to create extra template files written in a new, made-up template language. When you want to create a new post, you give it (a) the static files from your existing site and (b) the markdown for your new post. The "templating" engine inspects your existing posts (incl. e.g. class attributes) and then copies the same document structure into a new file, except with the right stuff (timestamp, title and heading, post content...) substituted in to the places where it's supposed to go.
<https://developer.mozilla.org/en-US/docs/Web/HTML/Element/in...>
<https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_a...>
Let's say you have static site today with your lost post being "2022/03/31/working-on-a-new-tool.html". To author your new post, the tool could derive the template based on what the actual, HTML-formatted version of your last post looks like, and then it would substitute the new post content into the appropriate places. For example, where your previous post has a date stamp indicating it was published on March 31, the tool would put the date of the new post. Where your previous post has the title in an H1 or whathaveyou, your new title would appear. Where the main text of your last post appears, the main text of your new post appears. This would all be written into a new file. There's no need for an explicit template file.
PS: Pandoc doesn't run in the browser, either. You're already going to have your browser open to check the output. Its runtime is both powerful enough, and it's right there, so use it. No need to bring other runtimes into this.
Check out fncli if you want to add some command line args... might be nice to specify some of the config that way
template.html:
generate.py: for serving it: it will be running on 127.0.0.1:8000cat template.html | sed s/content/$(markdowncompiler content.md)/
template.html:
generate.py1. drop markdown support, and posts in HTML
2. find a way to parse HTML via regex, which is doable if I use a different notation than a tag for `<partial src=...`
3. use a language that has filesystem support natively, to read files without a dependency
I'm working on 2 and 3. But I don't want to drop markdown support on the blog posts...so I guess I will live with this :)
It was 100 lines. But a little deceptive, since like yours it relied on a markdown parsing library.
The bulk of the code was handling creating a sitemap.xml and all the of meta/opengraph/twitter tags.
[1]https://blog.rysolv.com/markdown-static-site-generator
(* = Well, it was easy, but I feel like this ESM business now means npm/yarn install doesn't Just Work™ in some cases.)
This does seem to align with it being a modern perl
1. drop markdown support, and posts in HTML
2. find a way to parse HTML via regex, which is doable if I use a different notation than a tag for `<partial src=...`
3. use a language that has filesystem support natively, to read files without a dependency
I'm working on 2 and 3. But I don't want to drop markdown support on the blog posts...so I guess I will live with this :)
What I’m trying to say is that even if this qualifies as fashionable in your time scale, a decade is a lot.
This isn’t criticism of your approach. It’s better to stick to whatever works for you and focus on the problem domain rather than the tech stack.
... and you can probably build a 100 LOC static page generator in Java as well.
My thing does a lot of weird crap, though. Like it also acts as a Gemini protocol server, you can publish from the web and it pushes every change to a git repo. It also tracks backlinks and re-publishes every page that is mentioned. It also renders from a specialized version of gemtext so there really isn't any standard libraries to use (that I'm aware of).
Hehe, given how verbose Java can get, I’d increase the word wrap limit x3 in that case.
But yeah, I see your point and the project sounds pretty cool. Can I find it anywhere?
https://github.com/vlofgren/50-line-java-ssg
Does deal with partials, bit stuff like an automatic index requires maybe 5-10 additional lines.
Took about an hour (plus 15 minutes to try to figure out how to get into my github account, which I haven't actively used in the last 15 odd years).
My "real" Java SSG is used to generate https://memex.marginalia.nu/. Unfortunately I don't have the source published.
Obviously not that difficult to add some javascript and APIs if you want, which avoids the need to mix in a different stack while generating the same look-and-feel. Or you can use NGINX/Apache frontend to redirect certain paths to a more traditional dynamic stack/CMS of course. Just curious if there's any "standard" approach or off-the-shelf tooling for that for (eg) Jekyll or similar.
You can get a site running in Vercel+Next in <2m from ‘git init’.
I use it for https://potato.horse and most PoCs now, but we’ve scaled Vercel+Next to hundreds of thousands of users per day in other projects.
You could also use Netlify with Netlify functions, although I prefer the (slightly) less opinionated way of handing releases and per-commit vanity URLs Vercel offers.
Aaand if you want to get more funky with your approach, check out Astrojs (island architecture: start with static content and sprinkle the interactions on top of it).
You could also try, Elixir + Phoenix + Live View if you want to learn a new tech stack, feed your brain, and… spend a few days yak shaving. Nope, none of the 5 new versions of your blog will be live by the time you’re done, but you’ll become good friends with Erlang and co. Speaking from the experience, I use next when I want my stack to be boring.
...However, if what you want is dynamic content/interactivity within the context of a page that is served static from your SSG process, then I (reluctantly) resort to javascript (Sorry, my reluctance is because i'm not much of a fan of javascript...and in fact have tried to omit as much of it as reasonable from my projects.)
[0] https://github.com/mourner/tinyjam [1] https://agafonkin.com/
I made mine with Python and which is uses Github pages -
- Jinja templating engine
- Markdownpy
- Subprocess (for git CLI commands)
- And a classless CSS of your choice