# Wiki.js Webhook Setup Guide
Complete guide to enable automatic processing of user-edited wiki pages.
## Overview
When you manually edit pages in Wiki.js, the webhook system ensures they're processed identically to AI-generated content:
- ✅ **Vectors updated** - Qdrant embeddings refreshed
- ✅ **Graph updated** - Entities extracted, relationships created
- ✅ **Bidirectional links** - Automatic entity linking both ways
- ✅ **Deletions handled** - Clean removal from vectors + graph
- ✅ **Moves processed** - Path updates propagated to graph
## Step 1: Configure Wiki.js Webhook
### Access Wiki.js Administration
1. Log into Wiki.js as administrator
2. Navigate to **Administration** → **Webhooks**
3. Click **Add New Webhook**
### Webhook Configuration
| Field | Value |
|-------|-------|
| **Name** | Library Desk Integration |
| **Endpoint URL** | `http://library-desk:8089/webhooks/wikijs` |
| **Content Type** | `application/json` |
| **Events** | ☑ page.create
☑ page.update
☑ page.delete
☑ page.rename |
| **Status** | ✅ Active |
### Authentication Header
Add custom header for API authentication:
```
Authorization: Bearer af88ed8f44bed81bdb20d0534f1c4547340b29e2aba4963f61a71b993d7eb6e5
```
*(Use your actual Library Desk API key from `.env`)*
## Step 2: Verify Webhook Endpoint
Test the webhook health endpoint:
```bash
curl http://192.168.86.149:8089/webhooks/health
```
Expected response:
```json
{
"status": "ok",
"service": "webhooks"
}
```
## Step 3: Test Webhook Integration
### Test 1: Page Creation
1. Create a new page in Wiki.js
2. Add content mentioning existing entities (e.g., "Docker", "Kubernetes")
3. Save the page
**Expected Result:**
- Vectors created in Qdrant
- Document node created in Neo4j
- Entities extracted and linked
- Bidirectional links added (new page links to entities, entities' pages link back)
### Test 2: Page Update
1. Edit an existing page
2. Add new content with entity mentions
3. Save changes
**Expected Result:**
- Vectors updated in Qdrant (old removed, new added)
- Graph updated with new entities
- Entity links refreshed
### Test 3: Page Deletion
1. Delete a page from Wiki.js
**Expected Result:**
- Vectors removed from Qdrant
- Document node removed from Neo4j
- Orphaned entities cleaned up (entities only mentioned in this page)
- Broken relationships removed
### Test 4: Page Move/Rename
1. Move a page to different location (e.g., `/tech/docker` → `/infrastructure/docker`)
2. Or rename the page
**Expected Result:**
- Document node path updated in Neo4j
- Entity links updated if title changed
- Vectors remain valid (no re-embedding needed unless content changed)
## Event Processing Details
### page.create
```
User creates page → Webhook → Library Desk
├─ Ingest page (vector + graph)
├─ Extract entities
├─ Forward linking (page → entities)
└─ Backward linking (entities → page)
```
### page.update
```
User edits page → Webhook → Library Desk
├─ Re-ingest page (force refresh)
├─ Update entities
├─ Refresh forward links
└─ Refresh backward links
```
### page.delete
```
User deletes page → Webhook → Library Desk
├─ Remove vectors from Qdrant
├─ Find orphaned entities
├─ Delete Document node
├─ Delete orphaned entities
└─ Clean broken relationships
```
### page.rename
```
User moves/renames page → Webhook → Library Desk
├─ Update Document node path
├─ Update title if changed
├─ Re-link entities if title changed
└─ Update references
```
## Monitoring Webhook Activity
### Check Logs
```bash
# Library Desk logs
docker logs library-desk --follow | grep webhook
# Look for:
# - "Received Wiki.js webhook: page.create"
# - "Processing page.update for page 123"
# - "Cleanup complete for deleted page 456"
```
### Verify Processing
After making changes in Wiki.js, verify:
**1. Vectors Updated:**
```bash
curl -X POST http://192.168.86.149:8089/query/hybrid \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"query": "your page content", "user": "jpmschweitzer"}'
```
**2. Graph Updated:**
```cypher
// In Neo4j Browser
MATCH (d:Document {page_id: 123})
OPTIONAL MATCH (d)-[:MENTIONS]->(e)
RETURN d, collect(e.name) as entities
```
**3. Entity Links Added:**
Visit the page in Wiki.js and verify entity names are hyperlinked.
## Troubleshooting
### Webhook Not Triggering
**Problem:** Changes in Wiki.js don't trigger processing
**Solutions:**
1. Check webhook configuration in Wiki.js Admin
2. Verify endpoint URL is correct: `http://library-desk:8089/webhooks/wikijs`
3. Check authorization header is set
4. Verify library-desk is running: `docker ps | grep library-desk`
5. Check library-desk logs: `docker logs library-desk --tail 50`
### Processing Failures
**Problem:** Webhook triggers but processing fails
**Solutions:**
1. Check library-desk logs for errors
2. Verify Neo4j is accessible
3. Verify Qdrant is accessible
4. Check Ollama is running (for embeddings)
5. Verify user mapping in `extract_user_from_email()`
### Orphaned Entities
**Problem:** Deleted pages leave entities behind
**Solution:**
Manually clean orphaned entities:
```cypher
// Find orphaned entities (no MENTIONS relationships)
MATCH (e:User_Jpmschweitzer)
WHERE NOT e:Document
AND NOT EXISTS {(d:Document)-[:MENTIONS]->(e)}
DETACH DELETE e
RETURN count(e) as deleted
```
### Broken Links
**Problem:** Entity links broken after page moves
**Solution:**
Re-run entity linking on all pages:
```bash
curl -X POST http://192.168.86.149:8089/entity-linking/link-all \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"user": "jpmschweitzer"}'
```
## Performance Considerations
### Background Processing
Webhook handler processes events in the background to avoid blocking Wiki.js:
- Webhook response: <100ms (immediate acknowledgment)
- Processing: 2-10s (runs asynchronously)
- No impact on Wiki.js editing experience
### Rate Limiting
For bulk operations (importing many pages):
- Consider temporarily disabling webhook
- Use batch ingestion endpoint instead: `/ingest/batch`
- Re-enable webhook after bulk import
## Advanced Configuration
### Custom User Mapping
By default, user is extracted from email (`user@domain` → `user`).
Customize in `/services/library-desk/src/routers/webhooks.py`:
```python
def extract_user_from_email(email: str) -> str:
# Option 1: Map specific emails to users
user_map = {
"admin@example.com": "admin",
"john.doe@example.com": "jpmschweitzer"
}
return user_map.get(email, email.split("@")[0])
```
### Event Filtering
To process only certain pages, add filtering in webhook handler:
```python
# Only process pages in /tech/ path
if not payload.page.get("path", "").startswith("/tech/"):
logger.info(f"Skipping page outside /tech/: {payload.page.get('path')}")
return
```
### Disable Bidirectional Linking
To only do forward linking (page → entities) without backward linking:
Edit `process_wiki_page_change()`:
```python
# Comment out the bidirectional linking call
# link_stats = await consolidation_service._apply_bidirectional_entity_linking(...)
```
## Summary
With webhooks configured:
| User Action | Automatic Processing |
|-------------|---------------------|
| Create page | Ingest + entity link (bidirectional) |
| Edit page | Re-ingest + refresh links |
| Delete page | Clean vectors + graph + orphaned entities |
| Move page | Update paths + refresh links |
**Result:** User-edited and AI-generated pages are **indistinguishable** in the knowledge base!