# MarkdownHub Self-hosted collaborative markdown workspace with real-time editing, Git integration, and AI-powered code generation. ## Features - **Three editor modes**: WYSIWYG (Milkdown), raw markdown, and split-pane with live preview - **File management**: Tree-based file browser, folders, search, drag-and-drop, rename, trash - **Git versioning**: Auto-commit on save, full history, diff viewer, restore previous versions - **External Git sync**: Per-user remotes (Gitea, GitHub, etc.), push/pull on demand - **Real-time collaboration**: Yjs CRDT via WebSocket — multiple users editing simultaneously - **Sharing**: Share files/folders with other users (read-only or read-write) - **AI integration**: Verify specs, generate prompts, summarize — via LiteLLM/vLLM - **AI Build Pipeline**: Write a spec → verify → build entire project → push to Gitea - **Authentication**: Local accounts, LDAP/SLDAP, TOTP 2FA, group-based access control - **Light/Dark theme**: Toggle in UI, persisted in preferences - **Export**: PDF, HTML, raw markdown download - **Image upload**: Drag-drop images into the editor - **PWA / Offline**: Service worker, IndexedDB caching, sync on reconnect - **Multi-device**: Responsive with mobile hamburger menu - **Docker deployment**: Single container, easy backup - **Admin panel**: User management, LDAP configuration (no restart needed) - **Security**: Rate limiting, encrypted tokens, audit log, password complexity ## Quick Start ```bash git clone https://git.aholck.net/anders-pub/markdown-hub.git cd markdown-hub docker build -t markdownhub . docker run -d --name markdownhub \ --restart unless-stopped \ -p 8080:8080 \ -v ./data:/app/data \ -e MH_SECRET="$(openssl rand -hex 32)" \ markdownhub ``` Default admin: `admin@localhost` / `admin` — **change password immediately**. See [INSTALL.md](INSTALL.md) for full deployment guide. ## Configuration Environment variables: | Variable | Default | Description | |----------|---------|-------------| | `MH_PORT` | `8080` | Server port | | `MH_DATA_DIR` | `./data` | Data directory (SQLite + files) | | `MH_SECRET` | `dev-secret-change-me` | JWT signing secret | | `MH_ADMIN_EMAIL` | `admin@localhost` | Initial admin email | | `MH_ADMIN_PASSWORD` | `admin` | Initial admin password | | `MH_AI_ENDPOINT` | — | LiteLLM-compatible API URL | | `MH_AI_API_KEY` | — | API key for AI endpoint | | `MH_AI_MODEL` | `gpt-4` | Default model for AI features | | `MH_LDAP_URL` | — | LDAP server (`ldap://` or `ldaps://`) | | `MH_LDAP_BIND_DN` | — | Service account DN | | `MH_LDAP_BIND_PASS` | — | Service account password | | `MH_LDAP_BASE_DN` | — | Base DN for user search | | `MH_LDAP_USER_FILTER` | `(&(objectClass=inetOrgPerson)(uid=%s))` | User search filter | | `MH_LDAP_GROUP_FILTER` | — | Required group DN for login | | `MH_LDAP_SKIP_TLS` | `false` | Skip TLS verification | LDAP settings can also be configured from the **Admin panel** (no restart needed). ## Architecture ``` ┌─────────────┐ ┌──────────────┐ ┌────────┐ │ Frontend │────▶│ Go Backend │────▶│ SQLite │ │ (Vue 3) │◀────│ (net/http) │ └────────┘ └─────────────┘ │ │────▶ Filesystem (.md files) │ │────▶ Git (per-user repos) │ │◀───▶ LDAP (optional) └──────────────┘ │ ┌──────▼───────┐ ┌────────┐ │ Build Daemon │────▶│ Gitea │ │ (Python) │ └────────┘ └──────────────┘ ``` - **Backend**: Go 1.23, stdlib `net/http`, SQLite (modernc.org/sqlite), gorilla/websocket - **Frontend**: Vue 3, Vite, Milkdown, marked, Yjs - **Auth**: JWT + bcrypt + TOTP + LDAP/SLDAP - **Git**: Shell-based git operations (auto-commit, remotes, push/pull) - **AI**: LiteLLM-compatible OpenAI API calls - **Build Daemon**: Python (stdlib only), polls for build jobs ## Project Structure ``` cmd/server/ — Web server entry point cmd/mdsync/ — CLI sync tool internal/api/ — HTTP handlers & routing internal/auth/ — JWT, bcrypt, TOTP, LDAP internal/collab/ — Real-time collaboration (Yjs WebSocket hub) internal/db/ — SQLite schema & migrations internal/files/ — File CRUD & search internal/git/ — Git operations internal/crypto/ — AES-256-GCM encryption daemon/ — Build daemon (Python) frontend/ — Vue 3 SPA ``` ## CLI Tool ```bash go build -o mdsync ./cmd/mdsync mdsync login https://md.example.com you@example.com password mdsync pull . mdsync push . mdsync status ``` ## Backup & Restore All data lives in the `data/` volume: - `data/db/markdownhub.db` — SQLite database - `data/files/{user_id}/` — User markdown files (also git repos) ```bash # Backup cp -r ./data ./backup-$(date +%Y%m%d) # Restore docker stop markdownhub rm -rf ./data && cp -r ./backup-YYYYMMDD ./data docker start markdownhub ``` ## License MIT — Anders Holck 2026