
Pindoc is a self-hosted project memory system I built to replace the Wiki.js + OpenProject combo I'd been using for personal notes. It tries to be a wiki and a lightweight tracker at the same time, with embedding search and typed cross-references built into the schema instead of bolted on. It's been in active personal dogfood for a while; the public repo is the consolidation step.
Stack: Go for the backend, Postgres + pgvector for storage and embedding search, MCP-native for agent integration, all wired up with docker compose for self-hosting. Apache 2.0.
Why Go: I wanted a single static binary I could drop on a $5 VPS and forget about. No runtime, no node_modules, no Python venvs. The embedding pipeline (chunking + provider abstraction + pgvector inserts) is all in pure Go, with bundled EmbeddingGemma Q4 ONNX so the default path needs no external API. Goroutines made the background reindex job basically free to write.
What's in the box from a Go perspective:
- pgx for Postgres + pgvector (worked great, no surprises)
- chi for routing, no framework
- sqlc for type-safe queries (this is a love letter, sqlc is excellent)
- standard library for everything else
The two specific frictions I was solving: near-duplicate docs piling up in the wiki, and "quick TODO" notes getting disconnected from the analyses that produced them. Both turned out to be embedding-search problems underneath. Once that was wired up properly, the data model could stay simple.
Honest caveats: solo maintainer, the multi-user/OAuth flow has only had sanity testing, and the use case leans AI-coding-agent-shaped because that's how I write notes (a lot of generated content, selective human reading).
GitHub: https://github.com/var-gg/pindoc
Happy to talk through any of the Go-specific decisions — I'm sure some of them are wrong, would love to hear it.