# Radicale CardDAV Sync Integration This application now automatically syncs contacts to a Radicale CardDAV server whenever contacts are created, updated, or deleted. ## Features - ✅ **Automatic Sync** - Contacts are automatically synced when created or updated - ✅ **Automatic Deletion** - Contacts are removed from Radicale when soft/hard deleted - ✅ **Non-Blocking** - Sync happens asynchronously without slowing down the API - ✅ **Optional** - Sync is disabled by default, enable by configuring environment variables - ✅ **VCARD 3.0** - Generates standard VCARD format with full contact details ## Setup ### 1. Configure Environment Variables Add these to your `.env.local` or production environment: ```bash RADICALE_URL=http://localhost:5232 RADICALE_USERNAME=your_username RADICALE_PASSWORD=your_password ``` **Note:** If these variables are not set, sync will be disabled and the app will work normally. ### 2. Radicale Server Setup Make sure your Radicale server: - Is accessible from your application server - Has a user created with the credentials you configured - Has a contacts collection at: `{username}/contacts/` ### 3. One-Time Initial Sync To sync all existing contacts to Radicale: ```bash node export-contacts-to-radicale.mjs ``` This script will: - Prompt for Radicale URL, username, and password - Export all active contacts as VCARDs - Upload them to your Radicale server ## How It Works ### When Creating a Contact ```javascript // POST /api/contacts const contact = createContact(data); // Sync to Radicale asynchronously (non-blocking) syncContactAsync(contact); return NextResponse.json(contact); ``` ### When Updating a Contact ```javascript // PUT /api/contacts/[id] const contact = updateContact(contactId, data); // Sync updated contact to Radicale syncContactAsync(contact); return NextResponse.json(contact); ``` ### When Deleting a Contact ```javascript // DELETE /api/contacts/[id] deleteContact(contactId); // Delete from Radicale asynchronously deleteContactAsync(contactId); return NextResponse.json({ message: "Contact deleted" }); ``` ## VCARD Format Each contact is exported with the following fields: - **UID**: `contact-{id}@panel-app` - **FN/N**: Full name and structured name - **ORG**: Company - **TITLE**: Position/Title - **TEL**: Phone numbers (multiple supported - first as WORK, others as CELL) - **EMAIL**: Email address - **NOTE**: Contact type + notes - **CATEGORIES**: Based on contact type (Projekty, Wykonawcy, Urzędy, etc.) - **REV**: Last modified timestamp ## VCARD Storage Path VCARDs are stored at: ``` {RADICALE_URL}/{RADICALE_USERNAME}/contacts/contact-{id}.vcf ``` Example: ``` http://localhost:5232/admin/contacts/contact-123.vcf ``` ## Troubleshooting ### Sync Not Working 1. Check environment variables are set correctly 2. Verify Radicale server is accessible 3. Check application logs for sync errors 4. Test manually with the export script ### Check Sync Status Sync operations are logged to console: ``` ✅ Synced contact 123 to Radicale ❌ Failed to sync contact 456 to Radicale: 401 - Unauthorized ``` ### Disable Sync Simply remove or comment out the Radicale environment variables: ```bash # RADICALE_URL= # RADICALE_USERNAME= # RADICALE_PASSWORD= ``` ## Files - **`src/lib/radicale-sync.js`** - Main sync utility with VCARD generation - **`src/app/api/contacts/route.js`** - Integrated sync on create - **`src/app/api/contacts/[id]/route.js`** - Integrated sync on update/delete - **`export-contacts-to-radicale.mjs`** - One-time bulk export script ## Security Notes - ⚠️ Store credentials securely in environment variables - ⚠️ Use HTTPS for production Radicale servers - ⚠️ Consider using environment-specific credentials - ⚠️ Sync happens in background - errors won't block API responses ## Future Enhancements - Bi-directional sync (import changes from Radicale) - Batch sync operations - Sync queue with retry logic - Webhook notifications for sync status - Admin UI to trigger manual sync