Show HN: Shite – little hot-reloadin' static site maker from shell

2 years ago (github.com)

Or more precisely, my little site maker... It is a personal tool that I thoroughly enjoyed making, and enjoy using to write my website <https://evalapply.org>.

A caveat before any more; nobody was supposed to promote this insanity.

Like, terrible things have been done involving inotify and xdotool. But. It showed up on HN some months ago. That too while it was still, shall we say, fermenting. It got "done" some time thence, and of course one could not let the half-past just be. So here we are, for better or worse.

Thank you HN mods for helping me repost! _\\//

The README explains all, animated GIFs and whatnot. Some assorted highlights:

  - shite's, ah, "business logic" (except templates) is about 300 lines of Bash, written in Functional Programming style [^]. Pipeline all the things!
  - The innards won't surprise Perl/PHP/Shell gentleperson hackers from the last century.
  - The local hot reloading workflow is surprisingly nice, and occasionally hilarious! No JavaScript needed.
  - Full rebuilds are low performance and that's fine :)
  - Pandoc is great.
  - Sometimes sed and regex is exactly the HTML parser you need. *Very* sometimes.
  - stdio buffering can mess you up
  - jq -Rr @html # escapes HTML; what?!

... and all sorts of other stuff noted in the README and inline docs.

[^] because shell ain't a bad place to FP... https://www.evalapply.org/posts/shell-aint-a-bad-place-to-fp...

---

P.S.The commit history stops at 3-odd months ago, because I've been using a private fork for day-to-day content drafting, publishing, and layout tweaks. The "business logic" is by and large the same as the public version linked here.

Hey Aditya, you can make your command a little more unix-y if you feel so compelled by just renaming `shite.sh' to `shite' and run the shell script as a utility since it's already `chmod +x`'d.

Then you can `shite(1)` anywhere you want after you put the command in your PATH and feel like a proper `git(1)`.

Good `shite(1)` mate. Love it.

Nice! I also use inotifywait for hot reload when writing https://www.oilshell.org/

I never heard of the xdotool method ... although it sounds like it has some drawbacks? https://github.com/adityaathalye/shite/blob/master/bin/hotre...

I do it with a crappy Python web server that dynamically inserts some JavaScript. This also has bugs and drawbacks, though I don't think any fundamental ones ... At some point I would like to "make it nice", but it has been working well in practice for years

I think the method is reasonable, and doesn't depend on your local desktop environment as much.

I also have a Makefile for incremental rebuilds, but I would really like to replace that with Ninja. Ninja goes pretty well with shell (although it also has the issue of needing to escape $ as $$)

  • Lovely to hear from you, Andy! Thank you for sharing. It's good to know this work is in fine company :)

    > although it sounds like it has some drawbacks?

    Oh yes. The Xdotool Reload Method emulates keystrokes, so it has... drawbacks... as you put it mildly :)

    For my use-case, it literally does F5, or it fills out a url and hits Enter. cf. this `case` statement: https://github.com/adityaathalye/shite/blob/master/bin/hotre...

    I wanted to keep /mandatory/ moving parts to a minimum in a hand-rolled setup. So I sort of went hardline about avoiding prerequisites like a server process, and especially a JS client. The xdotool trick worked surprisingly well (for the most part), and so I stuck with it!

    > it has been working well in practice for years

    This is the holy grail. I really hope I get years-long stability out of it. Based on my experience so far, I feel good about the long-term odds.

    > I also have a Makefile for incremental rebuilds, but I would really like to replace that with Ninja.

    I was going to write a Makefile at some point. I'll have a look at Ninja. Thanks for the tip!

Lol, funny, I dig it.

Right here in real life I just do http://zim-wiki.org + a custom CSS Template + a few shell scripts.

http://jrm4.com

  • Thanks :)

    Likewise, I'm basically locked into "life in plaintext", as a die-hard orgmode user.

    With what I have on disk, a big positive is any "system" of organisation is opt-in, post-hoc, and fungible.

    Like, today, shite can be seen as merely one lens into a subset of my org files, to compile that subset into a website. Tomorrow I could bring back hugo.

    That choice has no bearing on how any other method of organisation might use those same files (e.g. I can pull up index views using orgmode's own query feature set).

    And further, a single blog posts's org file can power live demos in Emacs (org-babel), and gets exported as a blog post, and as a PDF slide deck, like this: https://www.evalapply.org/posts/why-and-how-i-use-org-mode/i...

amazing mind-link. i have also built a similar program (also called shite) only centered around plan9's rc shell and ndb, to manage my shite ;) (my use case is building a gemini+html output page with date/tag navigation from mostly plain text + minimal markdown in the form of tags and links).

https://git.2f30.org/shite/files.html

  • plan9! Some day I'll try it out. Such a nicely integrated system. As an emacs user, I cracked up at the manpage for Emacs in plan9. Hilarious!

    > https://git.2f30.org/shite/files.html

    So I looked at the templating code. Have you considered here documents for templating? Being able to declare complete HTML fragments is a big advantage for debugging parts, and keeping overall HTML valid. I author HTML fragments in an HTML-mode buffer and get linting etc. to make sure my markup is OK. Then I can just copy-paste it back into the heredoc.

    Another thing I did was to use functions as wrappers for each HTML fragment, so that I could define guarantees in the scope of the HTML (any variable / field that must be present or must be of a certain type).

    • I haven't really, because the only place where i needed valid html generated mostly by the program is on the navbar , the taglist etc. the main docu is kinda plaintext on a div when rendering html. But i will go back and investigate your idea since it would be elegant and rc supports normal here documents. for example

        ed $3 <<EOF
        g/$1/s//$2/g
        w
        EOF
      

      changes all occurrences of $1 to $2 in file $3. :)

      1 reply →

This is really impressive, I tried making my own SSG in shell scripts after looking at all these bloated ways to do it and realizing "this is something I could literally do in ten minutes of bash". It works for my use case but you went WAY further with the concept, good stuff

  • Thank you! It most assuredly was not "ten minutes of Bash".

    You see, there comes a time in every self-respecting Yak-shaving programmer’s life when one is driven to render large-scale follicle trimmage unto a sizeable Yak. In my case, ‘twas and ‘tis the deceptively diminutive but in fact mighty Site-Maker-Yak that renders World Wide Web Sites publishable unto the Internet.

    I wager, engaging oneself in the glorious enterprise of Yak-shaving is at least as therapeutic for the trimmer as it must be to the trimmee. I wholeheartedly recommend it :)

    • Yeah the live reload is especially impressive, I was literally just slapping content in between a header and footer and getting away with easy clean results hahaha

This is amazing and i love it.

As much as I've been enjoying hugo, I've been craving something that's much closer to this.

  • Haha thank you.

    I confess, I take childlike delight in every hotreload on save. Had it not worked well enough, I'd have stuck with hugo at the cost of a jankier authoring + build pipeline (org --ox-hugo--> markdown --hugo--> html).

One thing I enjoy about shell pipelines is that intermediate processes may terminate them.

eg https://www.99-bottles-of-beer.net/language-bourne-shell-108...

Nitpick: Generally “hot reloading” refers to reloading a single module or component in the system, while retaining the rest of the page state.

But maybe this counts because it’s a static site.

Y'all know that's a word in Scottish English, right?

I really like the dreams and desires section and how it explains the philosophy and how you view the project

I was curious how the hot-reloading works on the browser side. It looks like it starts its own Firefox window, keeps a reference to it, and somehow directly sends an F5 keypress to it? I don't quite follow how that part works.

Serious(-ish) question: does "And last but not least, I hereby decree that all texsht herein be read in Sean Connery voish." mean that this technically isn't FOSS?

A+ name, no notes

  • Heh, thank you. It almost wrote itself.

    I was trying to cook up a clever tagline, and fell upon "static sites from shell" and my brain looped about and found the tongue twister, sort of like "She sells sea shells on the sea shore", and well all esh shounds shtarted shounding like thish.

    These days I like that name more because it (hopefully) alerts the Dear Reader about the quality of software they are about to visit, should they take it upon themselves to do so.

I'm assuming just about everyone is aware of the meaning of the word.

https://www.urbandictionary.com/define.php?term=Shite

Kind of depressing that people find this amusing.