Jan Miksovsky’s BlogArchive AboutContact

Retire an old server to be a static site

Screenshot of the Elix web component library documentation

I was able retire an old #Heroku site by copying the content to a completely #static #website. Instead of resurrecting the source project and rewriting it, I used the #WebOrigami crawl command to retrieve the static files.

The @crawl picked up all but a few exotically-referenced resources that I copied over by hand. I dropped it all on Netlify. Some pages didn’t have an .html extension, so I added a small Netlify config to serve those as HTML. Then I pointed the old domain at the new site: Done!

Retiring this server as a static site reduces my monthly cost for it from $7/month to $0. The site’s for an old startup company but includes documentation for a web components library that I want to leave available.

If you’d like help retiring a site, let me know and I’ll see if I can assist.

The basic site auditing tool in #WebOrigami can work against a site defined in many ways: a data file, files in the file system, an Origami program — or a live #website running in production.

In the video I show an audit of the unbelievably massive Space Jam. For a site with 350+ handwritten HTML files, it contains surprisingly few broken internal links.

A simple protocol lets you make the contents of your #smallweb / #indieweb site more fully discoverable and explorable by interested users. This can also let site A see what resources site B offers.

I’ve been working on this in the spirit of the web’s simple, venerable, and immensely valuable View Source facility. View Source just lets you view a single HTML page; the web lacks a standard equivalent of a directory listing for a given route. This aims to fill that gap.

I made a short video walking through how I generate OpenGraph images for the pages on my blog using Origami.

This video is an experiment. It takes me ages to create polished documentation or videos — and that’s discouraged me from creating anything at all! I thought I’d try recording a video with only minimal rehearsal and no editing and see if this kind of thing can fill the gap until I can produce something better.

Cat test

I want to test RSS-to-Mastodon posting via MastoFeed, so here’s a test post with a photo of Mojo, who wants to come inside.

Update: I couldn’t get MastoFeed to work, and ended up following these instructions for Pipedream instead.

An ocicat with brown fur and green eyes stands on a yellow stucco banister and stares at the camera.

Sample influencer lifestyle blog for Henry David Thoreau

To demonstrate that Origami is a good language for building #smallweb / #indieweb blogs, I built a fun sample blog reenvisioning Henry David Thoreau has a modern influencer with a lifestyle blog about off-grid living.

Blog post titled "Beans" with text adapted from Thoreau's "Walden"

Creating a site in Origami is completely different than creating a site in any other tool I know of.

Origami isn’t a blog engine or framework, just like Microsoft Excel isn’t an invoicing or expense reporting framework. Excel is a general tool that transforms and aggregates numbers and text in tables. Origami is a general tool that transforms and aggregates data and content in trees.

So this project isn’t configuring a blog tool — it’s defining what a blog is from scratch. The source is endlessly malleable, and you can readily change what gets produced to achieve a wide variety of results.

To build in Origami, think about the starting tree of content you’ll write or gather by hand, and the final tree of resources in your running site. Step by step, you transform the former into the latter.

For a blog you might start with, say, a markdown folder containing markdown posts, an images folder for photos, and an assets folder for stylesheets.

Tree diagram of staring point with assets, images, and markdown folders

The final resource tree comprises the images and assets as is, plus generated pages for individual posts, list pages, and feeds.

Tree diagram of site resources showing generated pages, posts, and feed areas

To generate individual pages you can use a template language. Origami has a nice one built in; you can use others.

But the real magic is writing formulas to process a pile of content at once, like a pipeline that transforms markdown to HTML, calculates data, and sorts the posts to prepare them for rendering.

Origami pipeline transforming a markdown folder into data

Or a compact definition of the entire public portion of the site:

Origami program that defines the publicly-visible resources for a blog site

This Origami program generates the full tree of the resources for your blog, which you can browse immediately. The Origami runtime only does the work to generate a page when you ask for it.

The same Origami program can also produce a complete build folder with all your site files. Deploy those on a static web server or have a service do a build whenever you update your project.

Full source

Sample Origami site for an outdoor trekking company

Each month this year I’m trying to post a sample website written in Origami, a declarative programming language at the level of #HTML and #CSS for defining websites. This month’s sample is Aventour Expeditions, a site for an outdoor travel company.

It’s easy to have Origami call other template languages, so for this sample I used the Handlebars template language to turn markup and data into HTML.

Home page for an outdoor trekking company with tagline "Start your adventure" Page for a trek to the Wadi Rum desert in Jordan

It took just a few lines of Origami code to define the structure of the site and indicate which Handlebars template should be used to create which pages. For this outdoor travel example, Origami makes it very, very easy to:

Origami site definition for the trekking company site Tree diagram of the trekking company site

Origami also made it easy to cross-link the data for each trek with related treks. That allows the page for one trek to show cards links to related treks.

Page showing related treks to mountain destinations in Canada and Nepal

Aside: modern HTML and CSS are soooo much better than the past. I based the trekking site on a WordPress template whose design I liked but whose HTML/CSS was ridiculously complex and burdened with tons of JavaScript for trivial things.

Rewriting slashed the size of the pages. For the home page:

Before: 42k HTML, 600k CSS, 1580k JS

After: 13k HTML, 12k CSS, 0k JS!

Using Handlebars templates in the shell

It’s useful to be able to apply templates written in a language like #Handlebars to things in the shell.

The Origami #CLI lets you invoke JavaScript functions defined in .js files, but you can now also identify a handler for any file extension — like OS app file associations, but for a CLI. https://weborigami.org/language/filetypes.html#custom-file-types

So a handler can load a .hbs file as a function that applies a Handlebars template, then apply that in the command line.

Origami can resolve pretty much anything — JSON/YAML files, files with front matter, entire folder trees, a ZIP file, whatever — to an object your Handlebars template can operate on.

You can even write a one-liner that fetches data from a server and applies a template to it.

Applying a Handlebars template to a file system folder lets you, e.g., generate an HTML index page with links to all the HTML pages in the folder.

If one Handlebars template references another template (a “partial”), Origami resolves that reference for you. If you reference bold, it will look for a template named bold.hbs and use that.

This lets you decompose templates for complex results without the usual overhead of manually loading those templates and passing them as Handlebars configuration.

Origami itself is a powerful template language, but you might prefer Handlebars or some other template language. You can use Origami to define the overall structure of your site, then use Handlebars/etc. to turn data from anything into HTML.

It was easy to rewrite the Origami “About Us” sample site using Handlebars.

All City Someday: a photo blog backed by Google Drive

Suppose you want a photo blog that’s not on Tumblr or Instagram. Maybe you don’t like being sold, or want to draw outside the lines, or want photos as part of your own site. What would a #smallweb alternative look like that let you post a photo and caption from your phone?

I made a proof-of-concept street art photo blog that supports this on-phone flow: 1) snap a photo and set a caption, 2) save the photo to Google Drive via Files, 3) trigger a rebuild via the browser, 4) see the new photo on your own site.

View source

Google Drive is hardly #indieweb, but look beyond “corporate = bad” and consider the nature of the relationship. They provide a commodity service: you pay them, they store your files. Those files are a medium of exchange. If (when?) Google screws around, you can easily move the files to a different storage provider. Switching costs for hosted platforms like Tumblr or Instagram are far higher.

All storage services provide a proprietary API to enable unique features and faster service… but also to force you to write to that API and make your own code a switching cost. But most of what you want from storage is just an easy way to: 1) list directories, 2) read a whole file, and (maybe) 3) save a whole file.

The tiny AsyncTree interface does exactly those things.

interface AsyncTree {
  get(key: any): Promise<any>;
  keys(): Promise<IterableIterator<any>>;
  set?(key: any, value: any): Promise<this>;
}

This interface lets small storage drivers wrap the proprietary APIs; switching providers is just a matter of switching drivers.

The Origami language can use such a driver to read images out of Google Drive and create a static, deployable site. Origami templates also understand that interface, so you can make a template that directly maps a folder’s photos to HTML <img> tags with dates and captions. 🎉

One significant hurdle: obtaining a Google API credential file. OMG figuring out any kind of auth on Google, Azure, or AWS is like wandering through a maze of twisty little passages, all alike. It’s also theoretically possible to use Google Cloud Pub/Sub to automatically trigger a site rebuild whenever a photo is added to Google Drive, but dang that looks complicated. Maybe some other day.

Standards like Exif (for photo captions and dates) make amazing things possible. They’re there for everyone to use — if a corp isn’t trying to cage you in their silo.

The code for this photo blog is small: HTML + CSS + about 40 lines of Origami code. That includes defining RSS and JSON feeds. 😃

If I ever needed to switch storage providers, I’d just have to update the 3 lines of code that authenticate with Google and get a reference to the Drive folder. Everything else would stay the same.

Abstracting away storage doesn’t just give you an interesting way to build a site, it also opens up general-purpose terminal access so you can:

Design notes:

  1. It was fun to play with #CSS blur, text-shadow, and -webkit-text-stroke for a graffiti heading that’s just plain text! May also be the first time I’ve ever used magenta.
  2. I was able to auto-size the header width to be roughly as wide as the photos by playing with values for font-size: clamp(…).
  3. The fonts are so different from the stock fonts that any font swap was really jarring, so I forced early loading of the small font files and used font-display: block.

I made an ebook about my hike across Japan

I’ve made a little ebook about my hike across Japan last year.

In the summer of 2023, I walked for a month from the Pacific Coast to the Sea of Japan. I crossed steep mountains including Mt. Fuji, portions of the Southern Alps, the Yatsugatake range, the Northern Alps, and the Shio no Michi Trail. In between, I walked through cities, towns, and rural areas. The hike was a substantial challenge but also a fun adventure.

Book cover showing a grassy meadow and an elevated walking path

Creating an ebook is not difficult. Will Crichton wrote a great article advocating for using the EPUB format as a more portable and responsive alternative to PDFs.

Before reading it I hadn’t appreciated that EPUB files are just ZIP files with a particular folder structure and some book data. In retrospect that makes sense, but for me that single insight demystified the entire prospect of creating an ebook. It’s just a small bundle of files, mostly HTML, and some metadata.

You can use apps to make an ebook, but I wanted to build one more directly. Since the Origami website definition language is great at processing trees of content (like a folder of text and images) into new forms, I realized it could easily generate an ebook in EPUB format.

It wasn’t hard to write an Origami program to generate files in the required folder structure, and then it was just a matter of zipping it up.

Which left the question: what material could I turn into a book?

JamesG posted a good list of ideas for things people can do on their website. Facundo Olano expanded on that to suggest adding EPUB downloads for your blog or subsets of it. Their posts made me realize my own hike posts might make an interesting sample book.

During the hike I’d kept a travel diary in markdown with photos, so it was fairly easy to add a cover image, an introduction, and some metadata. Voilà: a book!

It may seem silly, but packaging something as a “book” feels weightier. Simply seeing the cover art in my ebook library alongside purchased novels was thrilling, as was opening up the book and paging through it. It felt like that day in third grade when a teacher had us bind illustrated stories into books and the school librarian put them on a library shelf. 📚

Try making an ebook — about anything — and you’ll feel the same thrill.

Older posts