Skip to content

asong56/Rhizome

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

119 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

🌿 Rhizome v2

A minimalist, decentralised webring β€” rebuilt for stability, scale, and extensibility.


What's new in v2

Area Change
Stability Shared src/core.js β€” single loadNodes with ETag validation, stale-while-error (72 h grace)
Stability Two-phase HEAD→GET probe with exponential backoff in scripts/prune.js
Stability Pruner runs daily instead of weekly; --dry-run mode for safe testing
Usability Cancel-redirect button on ring.html; "Visit site β†’" link after cancelling
Usability directory.html β€” searchable, filterable, sortable node directory
Usability Tag filtering on wander button (index.html) and transit page
Automation join.yml workflow β€” validates URL, verifies embed, commits, closes issue automatically
Features <rhizome-spore> supports lang, size, theme, filter-tag attributes
Features scripts/feed.js β€” aggregates member RSS/Atom feeds into feed.xml
Features Federation via peers option in loadNodes (opt-in cross-ring discovery)

Project structure

Rhizome/
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ core.js          # Shared browser module: uid, loadNodes, liveNodes
β”‚   β”œβ”€β”€ index.js         # Landing page: wander, tag bar, stats
β”‚   └── ring.js          # Transit page: node selection, progress, cancel
β”œβ”€β”€ scripts/
β”‚   β”œβ”€β”€ lib/
β”‚   β”‚   β”œβ”€β”€ semaphore.js # Async bounded-concurrency primitive
β”‚   β”‚   β”œβ”€β”€ probe.js     # Two-phase HTTP health check
β”‚   β”‚   └── verify.js    # Spore embed verifier
β”‚   β”œβ”€β”€ prune.js         # Node health check (daily CI)
β”‚   β”œβ”€β”€ join.js          # Auto-join processor (triggered by join.yml)
β”‚   └── feed.js          # RSS feed aggregator
β”œβ”€β”€ assets/css/
β”‚   β”œβ”€β”€ ring.css         # Transit page styles
β”‚   └── directory.css    # Directory page styles
β”œβ”€β”€ spore.js             # <rhizome-spore> web component (standalone IIFE)
β”œβ”€β”€ index.html           # Landing page
β”œβ”€β”€ ring.html            # Transit page
β”œβ”€β”€ directory.html       # Node directory
β”œβ”€β”€ nodes.json           # Node registry
β”œβ”€β”€ feed.xml             # Generated RSS feed (auto-committed)
└── .github/workflows/
    β”œβ”€β”€ prune.yml        # Daily health check
    β”œβ”€β”€ join.yml         # Auto-process join requests
    └── feed.yml         # 6-hourly feed aggregation

Quick start (fork & deploy)

  1. Fork this repository
  2. Enable GitHub Pages (Settings β†’ Pages β†’ Source: GitHub Actions or main branch /)
  3. Update the host URL in index.html and ring.html to your Pages URL
  4. Update SELF in scripts/feed.js to your feed URL
  5. Edit nodes.json β€” replace the seed node with your own site

Embedding the widget

Add to any page on your member site:

<rhizome-spore
  host="https://YOUR-USERNAME.github.io/Rhizome"
  lang="en"
  size="default"
  theme="auto">
</rhizome-spore>
<script src="https://YOUR-USERNAME.github.io/Rhizome/spore.js" defer></script>

Widget attributes

Attribute Values Default Description
host URL β€” Required. Your Rhizome registry base URL
lang en zh ja fr de es en Button label language
size default compact wide default Widget size
theme auto light dark auto Color scheme
filter-tag any tag string β€” Only traverse nodes with this tag

nodes.json schema

[
  {
    "name":   "My Site",
    "url":    "https://mysite.com",
    "bio":    "A short description (max 200 chars)",
    "tags":   ["blog", "dev"],
    "joined": "2026-01-15",
    "feed":   "https://mysite.com/feed.xml",
    "status": "dormant"
  }
]

Fields tags, joined, feed, and status are all optional. status: "dormant" is set automatically by the pruner; never set it manually.


Scripts

All scripts require Node.js β‰₯ 20 (for native fetch). No npm install needed.

# Health check β€” mark unreachable nodes as dormant
npm run prune

# Health check + verify embed is still present
npm run prune:verify

# Report changes without writing nodes.json
npm run prune:dry

# Aggregate member feeds into feed.xml
npm run feed

# Preview feed without writing
npm run feed:dry

Federation (opt-in)

To cross-discover nodes from another Rhizome fork, pass peers to loadNodes:

import { loadNodes } from './src/core.js';

const nodes = await loadNodes({
  peers: ['https://other-ring.github.io/Rhizome/nodes.json'],
});

Peer nodes are deduplicated by URL and marked with _peer: true in the data.


Joining (for site owners)

Open a Join issue using the issue template. The bot will:

  1. Parse your submission fields
  2. Probe your URL for reachability (HEAD β†’ GET, with retry)
  3. Verify <rhizome-spore> is present on your page
  4. Append your node to nodes.json and commit
  5. Close the issue with a welcome message

If validation fails, the bot comments with the reason. Fix and re-apply the join label.


License

Zero-clause BSD. Fork freely, credit appreciated.

About

A minimalist, decentralized webring protocol for the indie web.

Resources

License

Code of conduct

Contributing

Security policy

Stars

2 stars

Watchers

0 watching

Forks

Contributors