Tend your corner of the atmosphere. spores.garden turns your AT Protocol records into a personal site with unique themes. Your data never leaves your PDS. Grow something that's truly yours. spores.garden
TypeScript 84.0%
CSS 11.2%
JavaScript 3.4%
HTML 1.4%
Other 0.1%
308 1 0

Clone this repository

https://tangled.org/hypha.coop/spores.garden https://tangled.org/did:plc:rxduhzsfgfpl2glle7vagcwl/spores.garden
git@knot.tangled.wizardry.systems:hypha.coop/spores.garden git@knot.tangled.wizardry.systems:did:plc:rxduhzsfgfpl2glle7vagcwl/spores.garden

For self-hosted knots, clone URLs may differ based on your setup.

Download tar.gz
readme.md

spores.garden#

A digital garden that goes where you go.

spores.garden is a personal website builder powered by your AT Protocol data. Curate your records, pick layouts, customize your space. Your content stays in your PDS—the website is just a view.

Quick Start#

npm install
npm run dev

Then open your browser to:

  • http://127.0.0.1:5174 (or the port shown in your terminal)

You will see a "Connect" button. Log in with your Bluesky/AT Protocol handle (e.g., user.bsky.social) to view and edit your garden.

You can also directly view gardens by URL:

  • http://127.0.0.1:5174/@your-handle.bsky.social (path-based with handle)
  • http://127.0.0.1:5174/did:plc:your-did-here (path-based with DID)

How It Works#

  1. Load ALL records from your PDS - any lexicon
  2. Select record types to display
  3. Map to layouts (post, card, image, leaflet, etc.)
  4. Customize with themes and custom CSS
  5. Save config to your PDS

Lexicons#

Writes use the coop.hypha.spores.* namespace; reads fall back to garden.spores.* for legacy data.

Site Configuration:

  • coop.hypha.spores.site.config - Site configuration (title, subtitle)
  • coop.hypha.spores.site.layout - Layout preferences
  • coop.hypha.spores.site.section - Individual section definitions
  • coop.hypha.spores.site.profile - Profile / about-me record

User Content:

  • coop.hypha.spores.content.text - Text content records
  • coop.hypha.spores.content.image - Image content records

Social/Interactive:

  • coop.hypha.spores.social.flower - Flowers planted in gardens
  • coop.hypha.spores.social.takenFlower - Flowers collected from other gardens
  • coop.hypha.spores.item.specialSpore - Special spore items (capture-the-flag mechanic)

Generative (Client-Side Only):

  • Themes and sections are generated deterministically from your DID on every load—never stored on PDS

Architecture#

Static Site → Slingshot (records) + Constellation (backlinks) → Your PDS
  • Slingshot: Fast record fetching cache
  • Constellation: Backlink indexing for flower interactions and special spore tracking
  • atcute: OAuth for AT Protocol

Project Structure#

  • /src/components/ - Web Components
    • site-app.ts - Main application coordinator
    • site-*.ts - Modular app components (Auth, Editor, Router, Renderer, Data, Interactions)
    • section-block.ts - Content block rendering
  • /src/layouts/ - Record rendering layouts
  • /src/records/ - AT Protocol record loading and field extraction
  • /src/themes/ - Theme engine and presets
  • /lexicons/ - AT Protocol lexicon definitions
  • /docs/ - Documentation

Layouts#

Layout Best For
post Blog posts, articles
card Short content
image Photos, art
link Single link preview
links Link tree
list Generic list
profile About section
raw Custom HTML
leaflet Long-form articles from standard.site
smoke-signal Events (hosting/attending)
flower-bed Flower garden display
collected-flowers Collected flowers display

Layouts extract common fields (title, content, image, date, etc.) from any lexicon.

Special Spores#

Special spores are rare, gamified items that implement a capture-the-flag mechanic:

  • Rarity: Only 1 in 10 new gardens receives a special spore (10% probability on first config)
  • Capture Mechanics: Users can steal spores from gardens, but rapid re-steals are blocked for 1 minute
  • Backlink-Based: All spore records reference the origin garden via backlinks, enabling full lineage tracking
  • Timestamp Guardrail: Capture records with createdAt more than 5 minutes in the future are ignored
  • Evolution: Complete history of all captures is preserved and displayed chronologically

See Special Spore Documentation for detailed implementation and mechanics.

Themes#

Built-in presets: minimal, dark, bold, retro

Custom CSS supported for full control.

Testing#

npm test          # Run tests in watch mode
npm run test:run  # Run tests once
npm run test:ui   # Run tests with UI
npm run typecheck # TypeScript type check
npm run check     # Strict pre-launch gate (typecheck + tests + build)
npm run test:e2e  # Playwright smoke tests (requires @playwright/test + browsers)

Debug Logging#

Verbose runtime logs are disabled by default. Enable them when debugging with either:

  • query param: ?debug=1
  • local storage: localStorage.setItem('spores.garden.debug', '1')

Deployment Notes#

  • Namespace behavior is now new-first by default:
    • writes use coop.hypha.spores.*
    • reads use coop.hypha.spores.* with fallback to garden.spores.*
  • Copy .env.example to .env.local for local development overrides.

Developer Utilities#

  • node scripts/special-spore-probability.js did:plc:... to check deterministic spore assignment for a DID.
  • scripts/special-spore-helper.html browser helper page for manual spore checks.
  • npm run garden:backup / npm run garden:reset -- --dry-run|--yes / npm run garden:restore -- --from <file> for onboarding validation against real account data.

Documentation#

License#

MIT