Web App · Docker · curl · Homebrew · AUR
Personal knowledge management system with gamification. Manage notes, goals, streaks, and skills through a web dashboard with AI-powered features.
git clone https://github.com/Axel-DaMage/joidy.git
cd joidy
cp .env.example .env
docker compose up -dLinux / macOS:
curl -fsSL https://raw.githubusercontent.com/Axel-DaMage/joidy/main/scripts/install.sh | bashWindows (PowerShell):
irm https://raw.githubusercontent.com/Axel-DaMage/joidy/main/scripts/install.ps1 | iexbrew tap Axel-DaMage/homebrew-tap
brew install joidy
joidy upyay -S joidy
# or
paru -S joidy- Docker + Docker Compose
Edit .env after cloning:
| Variable | Description | Source |
|---|---|---|
GEMINI_API_KEY |
AI service key | Google AI Studio |
OBSIDIAN_VAULT_PATH |
Path to your Obsidian vault | e.g. /home/user/Documents/Obsidian |
OBSIDIAN_WEBHOOK_SECRET |
Shared secret for Obsidian webhook auth | Optional, any random string |
SECRET_KEY |
Session signing key | Auto-generated on first setup |
Optional:
GITHUB_TOKEN= # GitHub sync
GITHUB_USERNAME=
TELEGRAM_BOT_TOKEN= # Notifications
TELEGRAM_ALLOWED_USER_ID=| Service | URL |
|---|---|
| Web App | http://localhost:3000 |
| API Docs | http://localhost:8000/docs |
make dev # Hot reload, source mounts
make stop # Stop all services
make logs # View logs
make test # Run tests
make migrate # Database migrationsJoidy supports bidirectional sync with Obsidian. In addition to the local file watcher (worker), you can configure Obsidian to push changes via webhook for instant sync without polling.
- Set
OBSIDIAN_WEBHOOK_SECRETin.envto a random string - Configure an Obsidian plugin (e.g. Obsidian Webhook) to send events to:
POST http://localhost:8000/webhook/obsidian?secret=YOUR_SECRET
{
"event": "create",
"path": "/vault/My Note.md",
"content": "---\ntitle: My Note\ntags: [python, web]\n---\n# Content here",
"mtime": 1700000000
}| Field | Type | Required | Description |
|---|---|---|---|
event |
string | yes | create, update, or delete |
path |
string | yes | File path (matches source_path in DB) |
content |
string | create/update | Full file content (frontmatter + body) |
mtime |
int | no | Remote modification time (Unix timestamp) |
- create: Creates a new note in the DB. Extracts title from frontmatter or filename, tags from frontmatter + inline
#tags. - update: Updates existing note by
source_path. If not found, creates it instead. - delete: Deletes the note matching
source_path. No-op if not found.
- If
OBSIDIAN_WEBHOOK_SECRETis set: requests must include?secret=<secret>query param - If not set but
AUTH_PASSWORDis configured: JWT auth required - If neither is set (dev mode): no auth required
POST /webhook/obsidian/legacy — accepts the old payload format (note_id, path, remote_mtime) for backward compatibility. Only records sync state without processing content.
.
├── api/ FastAPI REST backend
├── ai-service/ AI service (Gemini, OpenAI, etc.)
├── worker/ Background tasks (Obsidian sync, daily summaries)
├── frontend/ SvelteKit web application
├── data/ Database, uploads, vault
├── docker-compose.yml
└── Makefile
graph LR
User[Usuario / Navegador]
FE[Frontend 3000<br/>SvelteKit]
API[API 8000<br/>FastAPI]
AI[AI 8002<br/>FastAPI]
Worker[Worker 8001<br/>asyncio]
DB[(SQLite + sqlite-vec)]
Vault[Obsidian Vault]
User --> FE
FE --> API
API --> DB
API --> AI
API --> Worker
Worker --> Vault
Worker --> API
See QUICKSTART.md for a step-by-step dev onboarding guide.
GNU General Public License v3.0. See LICENSE.