Migrating From Astro to Web Origami
I have fallen out of love with the web framework Astro for mainly two reasons: too much bloat and lack of trust in the fetching and caching of remote images. (The takeover by Cloudflare didn’t help either.) With bloat I mean the many features I didn’t use or care for anymore, like Astro components, pesudo-JSX, opinionated content collections and asset management. Yes, that’s a lot of the stuff that made me turn to Astro in the first place. Go figure. And the way remote images are handled made development when offline or on a spotty connection almost impossible. Time for something new!
Now, I have plowed through my fair share of frameworks and static site generators: Jekyll, Metalsmith, Astro, own tooling, back to Metalsmith, Eleventy, back to Astro. Take the actual necessity of each of those migrations with a grain of salt, as I—like many technical inclined people with a personal website—enjoy tinkering with my online playground.
This time it feels a bit different, though. I am not on the lookout for a new tool that promises a feature I desperately need or the highest level of convenience. Quite the opposite! I am looking for a tool that does not obfuscate all the phenomenal features the web platform has to offer, something simple, something that embraces the platform, embraces standards, and does not get in the way when I want to author my website as close to bare HTML as possible.
A quick look into my Second Brain sent me to Web Origami. I stumbled upon this project back in summer 2024 when Jim Nielsen reported that he switched from Metalsmith to Web Origami. I checked the docs and was immediately fascinated: by the name and its inherent promise to allow for complex outcomes based on simple starting material; by the quality and scholarly, yet playful vibe of the documentation (It has Comics!!!); and by the general philosophy behind its Content/Transformation model. But I put in on the back burner. I was happy with Eleventy back then.
Months later, I read the wonderful story that is MomBoard: E-ink display for a parent with amnesia by Web Origami mastermind Jan Miksovsky. It reminded me to check the project website again and I was happy to see that it still existed. But … I put it on the back burner. I had just migrated from Eleventy to Astro.
And because the third time really seems to be the charm, I needed Declan Chidlow’s reminder that It's All Just Trees With Web Origami and how incredibly powerful this central mantra of Web Origami is. No back burner this time, rather a perfect match between a thoughtful and carefully crafted piece of software and me, an “AI”-slop-riddled web developer longing for calmness and less abstractions in his tools.
Web Origami has a simple and enticing premise—everything is a (async-)tree—but there certainly is a learning curve. The three building blocks are the Origami language, which is an expression-only JavaScript-like delight; a very useful CLI; and a builtin library of sensible functions. I recommend to work through the Blog tutorial to get a feel for Web Origami’s approach towards the most common tasks of developing a website.
The documentation is superb and instead of trying to recreate its foundational information, I thought I would share some of the elegant code that you can expect when working with Web Origami.
<notes>
-> Tree.deflatePaths
-> (files) => Tree.map(files, {
value: (file, fileName, tree) => {
(extension) = Origami.extension.extname(fileName)
...file
isSupplement = fileName.includes("/")
_body = Origami.inline(file)._body
excerpt = _body.split("\n")[0]
// More property wrangling omitted for brevity
}
})
-> (notes) => Tree.sort(notes, (note) => note.updated)
-> Tree.reverse
There is so much goodness going on! This code takes my folder of notes; flattens it into a list of files; turns each file into an object consisting of the file’s YAML front matter, its HTML body, and additional properties; sorts the notes by date; and reverses that order. And my list of notes is done. I am confident that if you know JavaScript, you can decipher what is going on above.
Every path of your project directory—like notes in the first line, the angle brackets are just my personal way of distinguishing paths from identifiers—can be used in Origami and will be read into memory without any further file reading code. Builtins like Tree.map() or Origami.inline() do the heavy lifting regarding transformation and templating. Syntactic sugar like the pipe operator -> produces succinct and digestible code.
And I’ll do you one more. I mentioned above that fetching and caching remote images with Astro was tricky. I firmly believe that binary data like images have no place in a code repository, so my assets are hosted on Cloudinary. With Web Origami and its JavaScript interop I can encapsulate the fetching from Cloudinary in an async tree and use that like any other tree structure in my Origami code. Any image path is really a tree lookup and the result is cached on disk. Without Cloudinary credentials a fallback image file is used.
API_KEY && API_SECRET
? (
cloudinary.js(API_KEY, API_SECRET, IMG_FORMAT)
-> (images) => Tree.cache(images, files:../cache/images)
)
: (key) => <dev/placeholder.avif>
Granted, while I was at it, I also radically simplified my responsive images logic. But that shouldn’t deflect from the fact that with Web Origami I can describe that logic with readable code while staying in control of the specifics. Working on my website while offline is not an issue anymore and it never should have been.
I had massive support from the small but smart and super helpful community, especially creator Jan Miksovsky, who was always available for questions and offered help on an unprecendented scale. At one point, he checked out my code and ran it locally to get to the bottom of an issue I had. Don’t take my word for it: Jan decided against the omnipresent Discord as the community chat room and opted for Zulip, that you can view without an account. A very smart move, in my opinion, and another building block of the calm, open, and welcoming culture Jan established with this project.
To avoid doing as many support roundtrips as I have, I can recommend the following:
- Work through the conceptual model and the Blog tutorial.
- Always have two tabs with the Origami language specification and the builtins open. Those components are versatile and powerful.
- A general remark, but I tend to forget that when I’m kneedeep in understanding something new: Whenever you have an issue, try to isolate it and come up with a minimal example before asking someone else. The
oriCLI is amazing and will help you with that. Usually, Jan managed to communicate concepts or present approaches with just a few lines of code and anoriinvocation. - If you think something vital is missing from Web Origami’s API, re-read the docs. It’s probably there. If not, Jan is always open to suggestions.
- It‘s easy to forget that Origami is not JavaScript. There are differences, e.g. local property access. The page on Origami expressions is your language tutorial.
- Web Origami ships with some nifty helpers, like the Origami Explorer served under
https://localhost:5000/!exploreby default. Use them.
I love Web Origami and I am very happy to be part of its community. The fun in working inside the engine room of my website is reinstated, thanks to Web Origami’s strong mental model and its excellent API. I cannot wait to use it in future projects!