Skip to content

What is Webring?

Posted on:December 5, 2025 at 05:00 PM

The first iteration of webring

I originally created webring as a fun project to try to connect people sort of how it was done in the internet of old. The idea is that you can register your site and get links to the previous and next site in the ring, and I wanted to see how one could do it with modern frameworks. Here was my initial try:

Limitations:

import React, { useEffect, useState } from "react";
import { SITE } from "@config";

interface WebringLink {
  url: string;
  email: string;
}

const apiUrl = "https://webring-725549621836.us-central1.run.app/";
const email = SITE.email; // Your email address that you registered with

const Webring: React.FC = () => {
  const [prevSite, setPrevSite] = useState<WebringLink | null>(null);
  const [nextSite, setNextSite] = useState<WebringLink | null>(null);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    if (!apiUrl || !email) {
      setError("Webring not configured properly.");
      return;
    }

    const fetchLinks = async () => {
      try {
        const [prevRes, nextRes] = await Promise.all([
          fetch(`${apiUrl}/prev?cur=${encodeURIComponent(email)}`),
          fetch(`${apiUrl}/next?cur=${encodeURIComponent(email)}`),
        ]);

        if (prevRes.ok && nextRes.ok) {
          const prevJson = (await prevRes.json()) as WebringLink;
          const nextJson = (await nextRes.json()) as WebringLink;
          setPrevSite(prevJson);
          setNextSite(nextJson);
        } else {
          setError(`API responded with ${prevRes.status}`);
        }
      } catch (e) {
        const message =
          e instanceof Error ? e.message : "Failed to fetch webring";
        console.error("Webring fetch error:", message);
        setError(message);
      }
    };

    fetchLinks();
  }, []);

  if (error) {
    return (
      <div className="flex justify-center py-6">
        <p className="text-center text-xs text-gray-400">Webring: {error}</p>
      </div>
    );
  }

  if (!prevSite || !nextSite) return null;

  return (
    <div className="flex justify-center py-6">
      <div className="flex items-center gap-4">
        <a
          href={prevSite.url}
          className="text-sm font-medium"
          title={`Previous Site belongs to ${prevSite.email}`}
        >
          <span className="truncate">← Previous Site</span>
        </a>

        <a
          href="https://doshir.dev/posts/whatiswebring"
          className="text-xs"
        >
          Why Webring?
        </a>

        <a
          href={nextSite.url}
          className="text-sm font-medium"
          title={`Next Site belongs to ${nextSite.email}`}
        >
          <span className="truncate">Next Site →</span>
        </a>
      </div>
    </div>
  );
};

export default Webring;

So this begs the question - what did I settle on when I started to understand some of the limitations here? I eventually just did a “Featured Sites” modal that brings up data fetched from https://github.com/rithvik-doshi/webring-json. The data is already hosted for me on GitHub and can be edited simply via source control. I also don’t have to depend on other sites to show the full extent of the connected websites, though they are welcome to do so. Ultimately, trying to resurrect the webring was a fun thought experiment, but perhaps there is a reason it is slowly dying off in favor of other methods of connection and discovery on the web.