Rabbit Makes Webring in the Year 2024??

Article header image - Old webring.org header image with a bunny peaking out from the bottom-right corner

In my thirst for internet-of-yesteryear-vibes, I made a webring.

What

A webring is a collection of websites that are linked together in a circular structure, where each site includes a link to the next site in the ring. This format was popular in earlier days of the internet as a way for groups of people with similar themed websites to connect and share. It’s a way to discover new websites, without all that newfangled “Ess-Ee-Ohh” (SEO) Google garbage.

Webrings still exist, but I don’t really hear about them much anymore.

Why

When webrings were more popular, I wasn’t old enough to appreciate them, and I certainly would not have known enough how to make a website (at least not one I would deem worthy of being in a webring). I think they allow for real connection online, which I especially value nowadays in this hyperconnected, hypercommodified version of the internet. It’s a slower, more intentional way to connect, where the emphasis isn’'’t on clicks, likes, or shares, but on genuine interest. This also satisfies an intense nostalgia I have for old internet.

The charm, it seems to me, is in the journey; clicking from one site to the next, you never quite know what you’ll find. It could be a fan page for your favorite TV show, a personal blog full of unfiltered thoughts, or a treasure trove of art. It’s exploration, with no algorithms - just pure, uncurated discovery. For me, personal websites are a space that values creativity over conformity, where we can celebrate our shared interests and maybe even inspire each other along the way, and a webring to connect these silos feels like the perfect, era-approprirate way to do so.

So, I’m making up for lost time. Time to… start my own webring.

When

2024. Yep.

Who

Me, silly.

How

I’m getting to that!

I wanted to keep things simple. Or at least “simple” insofar as the following criteria is concerned:

  • Minimal JavaScript
  • Static Site Generation (mainly so I can host it on Github Pages or move it elsewhere in the future)
  • Easy to Update
    • to add new sites to a webring
    • to add new webrings to the system

Out of scope: OPML/RSS feeds. Maybe that’s something I’ll want to revisit later, but for now, I just want a directory of sites that I can click through in a web browser.

I briefly explored a few existing solutions, including:

But neither of these did quite what I wanted. I’m already using Jekyll to build my own site, and I’ve been getting pretty familiar with it, so I wondered if I could use that somehow. With a bit of work, it turns out I could.

The following are bits and pieces of the Jekyll site with some notes on why they’re there and what they’re doing. To explore on your own, you could always go check out the repo.


_data/sites.yml - Simple data file defining any sites that belong to any webrings within this generated site. For example, my site:

- name: Astra Bun
  link: "https://astrabun.com"
  description: |
    A bun on the internet!
  rings:
    - critters

This file is meant to be super easy to update; if someone is joining the webring, just create a new object in the list with a name, link, and description, and set rings to a list of ring IDs (slugs). If a user is meant to be on multiple rings (there aren’t multiple on this service, at least not at the time of writing), then additional IDs can be added to their rings list.


rings/<ring-slug>.md - File to store webring metadata in. For the “critters” web ring, it’s rings/critters.md.

---
slug: 'critters'
name: 'The Internet Critters Webring'
description: 'Webring for Internet Critters'
layout: ring
---

Not much to say here - just some basic metadata.


_layouts/rings.html - Layout file for rendering the webring info page (and also the JSON of the ring members??)

This was probably the trickiest part of the process. This layout handles both rendering an HTML info page on what the ring is, who the members are, and some sample code to use as a member. There’s some Liquid magic that handles the conditional output:


{% if page.url contains '.json' %}
{% include generate_ring_json.json slug=page.slug %}
{% else %}

...

generate_ring_json.json is itself a Liquid file designed to filter the list of sites to only those with the current webring slug present and render an object that contains that array. I couldn’t find a very graceful way to do this, so there’s some really nasty string interpolation stuff happening to cobble together the JSON.

The rings layout page also contains reference to _includes/display_webring.md which generates the sample code for including the webring navigation on a site. There’s a few Liquid if/else conditions in there so that I could also use the same component to render a sample of what the navigation looks like, and also what it looks like when a website not in the webring uses it. There’s a bit of code duplication in this file, but I decided I just don’t care enough to worry about it. The duplication is really just to provide sample outputs simulating if the current site WAS or WAS NOT in the webring. It doesn’t really matter if it is “correct” because this site will not be in the webring. Also, my goal was to spin this up as fast as possible, so, get off my back or whatever.


api/rings.json - A Liquid file to provide a JSON-formatted representation of all avaiable webrings (metadata only).

---
layout: none
---
{% assign data = site.rings | jsonify %}
{% assign keys_to_remove = "content,output,path,relative_path,date,collection,excerpt,categories,next,tags,previous,draft,layout,ext,id" | split: "," %}
{% assign filtered_data = data | ring_remove_keys: keys_to_remove %}
{% assign object_data = filtered_data | ring_array_to_object %}
{{ object_data }}

api/rings/<slug>.json (or in this case, api/rings/critters.json) - Finishes handling the JSON formatting for a given ring.

---
layout: ring
permalink: /api/rings/critters.json
slug: critters
---

{% assign page.url = "/api/rings/critters.json" %}

This works with a Ruby plugin and the condition in the ring layout to render the ring data in JSON.


_config.yml - a few notable config options to tie the last of this together

# ...
collections:
  rings:
    output: true
    permalink: /:collection/:slug
defaults:
  - scope:
      path: ""
      type: rings
    values:
      layout: ring
# ...

Mainly, the collection for rings is defined here, and we’re able to set a default layout for the rings. Not much else to mention.


There’s a few small, custom Ruby plugins (some you’ve probably seen mentioned in code blocks above) written to do some data massaging, and one to help with conditionally using the JSON format of the ring page. These aren’t too interesting, so I’m not going to spend time on them.

Where

I’m putting the ring here, on critterweb.net. I think I’ve built this in such a way that additional webrings can be hosted on this domain in the future, but for now, it’s just the one! Interested in joining? The critter ring is aimed to be for furries, especially furries with websites that have similar aeshetics/small-web designs, so let me know if you’d like to join, either in the comments, or on Bluesky.

Conclusion

This project, albeit challenging at times trying to wrestle with Liquid, was a blast from start to finish, not just because it let me flex my Jekyll muscles but because it felt like a tribute to the simpler, more personal days of the internet. Back before everything was dominated by AI and endless scrolling, the internet seemed to have more magical spaces - small, interconnected, and full of personality.

It also gives me another chance to connect with the furry community online, which is so important to me. Furry is a hobby for me, but it’s also a community that I’ve always found warmth and creativity in. This webring is a small way for me to contribute back to that, to hopefully connect with other furs and help us stay connected in our own unique corner of the web.

Thank you for reading as I went on this little journey down internet memory lane.

Also, check the footer of my website! There it is, the little navigation thingy!

UPDATES

2024-08-23

After getting some sleep, I realized there’s no need to force all members to do their own JS implementation (especially if they prefer not to have much JS on their site), so instead I’ve updated the site to handle linking to next/previous sites.

<div id="critter-webring-nav">
    <p>The Internet Critters Webring</p>
    <div>
        <span><a href="https://critterweb.net/rings/critters?name=SimulatedSiteName&to=prev" target="_blank">previous</a></span>
        <span><a href="https://critterweb.net/rings/critters" target="_blank">info</a></span>
        <span><a href="https://critterweb.net/rings/critters?name=SimulatedSiteName&to=next" target="_blank">next</a></span>
    </div>
</div>

This makes it a lot easier for folks to join than having to fiddle with JavaScript, but still leaves room for custom styling per site if desired! A simple previous/next link where you pass in your site name and the direction you want seems much simpler.

[Permalink to this update]

Read More

I found these resources helpful along this journey: