1
1
Fork
You've already forked site
0
My personal site: a blog, news reader, data hub. https://robida.net/
  • Python 90.1%
  • JavaScript 7.2%
  • HTML 1.4%
  • CSS 1.2%
Beto Dealmeida e5eed9fc39
All checks were successful
ci/woodpecker/push/deploy Pipeline was successful
ci/woodpecker/push/lint Pipeline was successful
ci/woodpecker/push/test Pipeline was successful
Merge pull request 'feat: remove food analysis' ( #451 ) from remove-food-analysis into main
Reviewed-on: #451 
2026年05月31日 20:35:51 +02:00
.woodpecker fix: batch embeds 2026年03月05日 13:06:27 -05:00
deploy feat(mcp): SSE support 2026年03月20日 16:28:56 -04:00
docs Parse HTML instead of regex 2026年01月20日 10:47:53 -05:00
scripts More signed headers 2026年05月11日 17:48:06 -04:00
src/backend feat: remove food analysis 2026年05月31日 13:26:02 -04:00
stubs Parse HTML instead of regex 2026年01月20日 10:47:53 -05:00
tests Add coverage 2026年05月31日 14:01:34 -04:00
.gitignore feat: gemini server 2026年02月26日 23:20:44 -05:00
LICENSE.md Add license 2025年12月11日 16:55:25 -05:00
Makefile feat: commands for rebuilding FTS/embeddings 2026年03月05日 10:51:34 -05:00
package-lock.json chore: JS tests 2026年01月15日 14:09:56 -05:00
package.json chore: JS tests 2026年01月15日 14:09:56 -05:00
prek.toml fix: add missing conf 2026年03月01日 22:45:47 -05:00
pyproject.toml feat: show pronouns 2026年05月18日 09:17:23 -04:00
README.md fix: lints 2026年03月06日 18:16:56 -05:00
uv.lock feat: show pronouns 2026年05月18日 09:17:23 -04:00
vitest.config.js More tests 2026年01月15日 15:46:17 -05:00

Robida

A personal IndieWeb site that serves as identity, blog, social reader, and quantified-self hub. Built with Python (Litestar) and vanilla JS, backed by SQLite.

This is the software that powers robida.net. It's a single-user site — not a framework or CMS — but the code is public in case it's useful to anyone building their own IndieWeb tools.

What it does

Identity & Auth — The site is its own OAuth2/OIDC provider. I sign in to IndieWeb services with my domain. Implements IndieAuth (both client and server), RelMeAuth with GitHub/Codeberg, and dynamic client registration (RFC 7591).

Publishing — Posts are stored as microformats2 JSON in SQLite and rendered as semantic HTML with mf2dom. Supports notes, articles, photos, bookmarks, likes, replies, RSVPs, checkins, and more. Publishing happens via Micropub.

Social Reader — A built-in feed reader that subscribes to RSS, Atom, JSONFeed, JF2, and h-feed sources. Implements Microsub for channel management and timeline reading. Guest users can like and reply to posts, stored locally.

Webmentions — Sends and receives Webmentions for cross-site replies, likes, and reposts. Outgoing mentions are queued and processed asynchronously.

Feeds — Publishes content as Atom, RSS, JSONFeed, JF2, and h-feed.

Offline-first sync — The frontend runs a local SQLite database (sql-wasm.js persisted to IndexedDB) that syncs bidirectionally with the server via WebSocket using Hybrid Logical Clocks. The site works offline — you can compose posts, like things, and browse your feed without a connection.

Quantified Self — Integrates with external services and creates h-entry posts for each data point:

Semantic Search & MCP — Entry content is embedded using fastembed (all-MiniLM-L6-v2, 384 dimensions) and searched via cosine similarity. Exposed as a Model Context Protocol server so Claude can search my posts and query health data.

Architecture

┌──────────────┐ WebSocket ┌──────────────┐
│ Browser │◄──────────────────►│ Litestar │
│ sql-wasm.js │ HLC sync │ (async) │
│ IndexedDB │ │ SQLite │
└──────────────┘ └──────┬───────┘
 │
 ┌───────────┼───────────┐
 │ │ │
 Micropub Microsub Webmention
 (publish) (read) (social)
  • Backend: Litestar (async ASGI), aiosqlite, SQLite in WAL mode
  • Frontend: Vanilla JS modules, no bundler. Local SQLite via sql-wasm.js
  • Sync: Hybrid Logical Clocks — 48-bit physical ms + 16-bit logical counter. Preserves causality without a centralized clock
  • Content model: Everything is microformats2 JSON in a single microformats2 table. Rich column types (URL, HLC, TIMESTAMP, JSON) with registered adapters
  • Rendering: mf2dom — isomorphic mf2-to-HTML renderer (Python for server, TypeScript for client)

Points of interest

If you're exploring the code, these might be the most interesting parts:

Area Files What's there
HLC sync hlc.py, sync.py, sync.js Bidirectional CRDT sync between server and browser SQLite
IndieAuth/OIDC auth/ Full OAuth2 + OIDC provider with PKCE, refresh tokens, dynamic client registration
Micropub micropub/ Create/update/delete posts, media uploads, slug generation
Microsub microsub/ Channel management, timeline, feed subscriptions
Webmentions webmention/, sender.py Receiving, sending, and processing cross-site interactions
Feed parsing feeds/ RSS, Atom, JSONFeed, JF2, h-feed, h-card discovery
Semantic search embeddings.py fastembed vectors, brute-force cosine similarity
MCP server mcp/ JSON-RPC over HTTP, tool registry with per-tool scope enforcement
Offline-first UI static/js/ Local DB, sync client, SPA router, entry rendering

Running

This is a personal site, not a product — but if you want to poke around:

# Install dependencies
uv sync --dev
# Run the dev server
make dev
# Run tests (100% coverage enforced)
make pr

Requires Python 3.11+ and Node.js (for JS tests via Vitest).

License

GNU Affero General Public License 3.