seams.so#
Web annotation system built on AT Protocol - annotate any webpage and share annotations via Bluesky's decentralized infrastructure.
Project Structure#
- Browser Extension (TypeScript/WXT) - Chrome/Firefox extension for creating and viewing annotations
- Backend Server (Go) - SQLite-backed indexing service for querying annotations by URL
- Landing Page (
landing/) - Public feed of recent annotations - Proxy (
proxy/) - Web-based proxy using wabac.js for annotation without extension
Quick Start#
Development Environment#
# Enter Nix development shell (includes Node.js, pnpm, Go, etc.)
nix develop
Extension Development#
# Install dependencies
pnpm install
# Start development server with hot reload
pnpm dev
# Build for production
pnpm build
# Package for Chrome Web Store / Firefox Add-ons
pnpm zip
Load the extension:
- Chrome: Open
chrome://extensions, enable "Developer mode", click "Load unpacked", select.output/chrome-mv3 - Firefox: Open
about:debugging#/runtime/this-firefox, click "Load Temporary Add-on", select.output/firefox-mv3/manifest.json
Backend Server#
cd server
# Install Go dependencies
go mod download
# Run server (defaults to port 8080)
go run cmd/server/main.go
# Run tests
go test ./internal/service -v
# Build binary
go build -o seams-server ./cmd/server
See server/README.md for detailed backend documentation.
Architecture#
Browser Extension (Storage-First)#
- Background worker: Fetches annotations from backend on tab changes, syncs user's own annotations from PDS
- Content script: Reads from
storage.local, renders highlights, tracks text selection - Sidepanel: UI for creating/viewing annotations, optimistically updates cache
Backend (Go + SQLite)#
- Indexes annotation records from users' Personal Data Servers (PDSs)
- Resolves DIDs via plc.directory to support any PDS (not just bsky.social)
- Provides query endpoint:
GET /api/annotations?url={url} - Rate-limited: 100 req/min (GET), 10 req/min (POST)
Data Flow#
User creates annotation → PDS (via OAuth) → Backend indexes → storage.local cache → Content script renders highlights
Configuration#
Environment Variables#
Extension (.env):
BACKEND_URL=http://localhost:8080 # Backend API URL
Backend:
PORT=8080 # Server port (default: 8080)
DB_PATH=./db/annotations.db # SQLite database path
Documentation#
- AGENTS.md - Developer guide, architecture overview, commands
- hitsory/STORAGE_FIRST_ARCHITECTURE.md - Extension architecture and design decisions
- server/README.md - Backend API documentation
- server/TESTING.md - Backend testing guide
Tech Stack#
Extension:
- TypeScript + WXT (Web Extension Framework)
@atcute/oauth-browser-client- AT Protocol OAuth- Vite for bundling
Backend:
- Go 1.22+
- SQLite (with WAL mode for concurrency)
- chi (HTTP router)
Proxy:
- wabac.js (client-side service worker)
- CORS proxy server (Node.js/Hono)
- Injects browser-based sidebar and content script
- Caddy for static files and reverse proxy
Infrastructure:
- Nix for reproducible development environments
- pnpm for package management
License#
MIT