diff --git a/.github/workflows/auto-tag.yaml b/.github/workflows/auto-tag.yaml
deleted file mode 100644
index 19eafd6..0000000
--- a/.github/workflows/auto-tag.yaml
+++ /dev/null
@@ -1,49 +0,0 @@
-name: Auto Tag Release
-
-on:
- push:
- branches:
- - 'release/*'
-
-jobs:
- create-tag:
- runs-on: ubuntu-latest
- permissions:
- contents: write
- steps:
- - name: Checkout code
- uses: actions/checkout@v4
- with:
- fetch-depth: 0
-
- - name: Extract tag name from branch
- id: extract_tag
- run: |
- BRANCH_NAME="${GITHUB_REF#refs/heads/}"
- TAG_NAME="${BRANCH_NAME#release/}"
- echo "tag_name=$TAG_NAME" >> $GITHUB_OUTPUT
- echo "Extracted tag name: $TAG_NAME"
-
- - name: Check if tag already exists
- id: check_tag
- run: |
- if git rev-parse --verify "refs/tags/${{ steps.extract_tag.outputs.tag_name }}" >/dev/null 2>&1; then
- echo "tag_exists=true" >> $GITHUB_OUTPUT
- echo "Tag ${{ steps.extract_tag.outputs.tag_name }} already exists"
- else
- echo "tag_exists=false" >> $GITHUB_OUTPUT
- echo "Tag ${{ steps.extract_tag.outputs.tag_name }} does not exist"
- fi
-
- - name: Create and push tag
- if: steps.check_tag.outputs.tag_exists == 'false'
- run: |
- git config --local user.email "action@github.com"
- git config --local user.name "GitHub Action"
- git tag -a "${{ steps.extract_tag.outputs.tag_name }}" -m "Release ${{ steps.extract_tag.outputs.tag_name }}"
- git push origin "${{ steps.extract_tag.outputs.tag_name }}"
-
- - name: Skip tag creation
- if: steps.check_tag.outputs.tag_exists == 'true'
- run: |
- echo "Tag ${{ steps.extract_tag.outputs.tag_name }} already exists, skipping creation"
\ No newline at end of file
diff --git a/.github/workflows/publish-plugin.yaml b/.github/workflows/publish-plugin.yaml
deleted file mode 100644
index 5704c78..0000000
--- a/.github/workflows/publish-plugin.yaml
+++ /dev/null
@@ -1,37 +0,0 @@
-name: Release Obsidian plugin
-
-on:
- push:
- tags:
- - "*"
-
-jobs:
- build:
- runs-on: ubuntu-latest
- permissions:
- contents: write
- steps:
- - uses: actions/checkout@v4
-
- - name: Setup Bun
- uses: oven-sh/setup-bun@v1
- with:
- bun-version: latest
-
- - name: Build plugin
- run: |
- cd packages/plugin
- bun install
- bun run build
-
- - name: Create release
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- run: |
- tag="${GITHUB_REF#refs/tags/}"
-
- cd packages/plugin
- gh release create "$tag" \
- --title="$tag" \
- --draft \
- main.js manifest.json styles.css
diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml
new file mode 100644
index 0000000..140c20b
--- /dev/null
+++ b/.github/workflows/release.yaml
@@ -0,0 +1,85 @@
+name: Release Plugin
+
+on:
+ push:
+ branches:
+ - 'release/*'
+
+jobs:
+ release:
+ runs-on: ubuntu-latest
+ permissions:
+ contents: write
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+
+ - name: Extract version from branch
+ id: extract_version
+ run: |
+ BRANCH_NAME="${GITHUB_REF#refs/heads/}"
+ VERSION="${BRANCH_NAME#release/}"
+ echo "version=$VERSION" >> $GITHUB_OUTPUT
+ echo "Extracted version: $VERSION"
+
+ - name: Check if tag already exists
+ id: check_tag
+ run: |
+ if git rev-parse --verify "refs/tags/${{ steps.extract_version.outputs.version }}" >/dev/null 2>&1; then
+ echo "tag_exists=true" >> $GITHUB_OUTPUT
+ echo "Tag ${{ steps.extract_version.outputs.version }} already exists"
+ else
+ echo "tag_exists=false" >> $GITHUB_OUTPUT
+ echo "Tag ${{ steps.extract_version.outputs.version }} does not exist"
+ fi
+
+ - name: Setup Bun
+ if: steps.check_tag.outputs.tag_exists == 'false'
+ uses: oven-sh/setup-bun@v1
+ with:
+ bun-version: latest
+
+ - name: Install dependencies
+ if: steps.check_tag.outputs.tag_exists == 'false'
+ run: bun install
+
+ - name: Run tests
+ if: steps.check_tag.outputs.tag_exists == 'false'
+ run: cd packages/plugin && bun test
+
+ - name: Build plugin
+ if: steps.check_tag.outputs.tag_exists == 'false'
+ run: |
+ cd packages/plugin
+ bun run build
+
+ - name: Create and push tag
+ if: steps.check_tag.outputs.tag_exists == 'false'
+ run: |
+ git config --local user.email "action@github.com"
+ git config --local user.name "GitHub Action"
+ git tag -a "${{ steps.extract_version.outputs.version }}" -m "Release ${{ steps.extract_version.outputs.version }}"
+ git push origin "${{ steps.extract_version.outputs.version }}"
+
+ - name: Create GitHub release
+ if: steps.check_tag.outputs.tag_exists == 'false'
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ run: |
+ VERSION="${{ steps.extract_version.outputs.version }}"
+ cd packages/plugin
+
+ # Create release with plugin files
+ gh release create "$VERSION" \
+ --title="$VERSION" \
+ --notes="Release $VERSION - See CHANGELOG.md for details" \
+ --draft \
+ main.js manifest.json styles.css
+
+ - name: Skip release (tag exists)
+ if: steps.check_tag.outputs.tag_exists == 'true'
+ run: |
+ echo "Tag ${{ steps.extract_version.outputs.version }} already exists"
+ echo "If you want to re-release, delete the tag first: git push --delete origin ${{ steps.extract_version.outputs.version }}"
diff --git a/README.md b/README.md
index decda9d..eda0e16 100644
--- a/README.md
+++ b/README.md
@@ -2,245 +2,286 @@
[](https://opensource.org/licenses/MIT)
-A complete synchronization solution for Obsidian vaults with Google Drive backend, featuring real-time sync, folder structure preservation, and automatic conflict detection.
+
+
+
+
+A local-first Obsidian plugin for seamless vault synchronization with Google Drive. Direct integration, no server required, complete privacy and control.
## โจ Features
- ๐ **Bi-directional Sync** - Upload and download files between Obsidian and Google Drive
- ๐ **Folder Preservation** - Maintains complete directory hierarchy in Google Drive
- โก **Real-time Updates** - Files sync immediately on creation or modification
-- ๐ **OAuth 2.0 Auth** - Secure Google Drive authentication
-- ๐ **Remote Deployment** - Works on any hosting platform with auto-detected URLs
-- ๐ **Index Reconciliation** - Periodic scanning ensures all files are tracked
-- ๐พ **Local Storage** - Development mode with local file storage
-- ๐ **Auto-Detection** - Dynamic configuration for any environment
+- ๐ **OAuth 2.0 Auth** - Secure Google Drive authentication directly from plugin
+- ๐ป **Local-First** - No external server required, runs entirely in Obsidian
+- ๐ **Smart Sync** - Intelligent change detection and conflict resolution
+- ๐๏ธ **Tombstone Management** - Proper deletion tracking with grace periods
+- ๐ **File Rename Detection** - Handles file and folder renames efficiently
## ๐ Quick Start
-### 1. Clone and Install
+### 1. Install Plugin
+
+#### Option A: From Obsidian Community Plugins
+1. Open Obsidian Settings โ Community Plugins
+2. Search for "Vync"
+3. Click Install
+4. Enable the plugin
+
+#### Option B: Manual Installation
```bash
+# Clone and build
git clone
cd vync
bun install
-```
-
-### 2. Setup Server
-```bash
-cd packages/server
-cp .env.example .env
-# Edit .env with your configuration
-bun run dev
-```
-### 3. Setup Obsidian Plugin
-```bash
+# Build the plugin
cd packages/plugin
bun run build
-# Install plugin in Obsidian
+
+# Copy to your vault's plugins folder
+cp -r dist/* /path/to/your/vault/.obsidian/plugins/vync/
```
+### 2. Configure Google Drive
+1. Open Vync settings in Obsidian
+2. Click "Authenticate with Google Drive"
+3. Complete OAuth flow
+4. Start syncing!
+
**๐ Detailed guide:** See [QUICK_START.md](QUICK_START.md)
## ๐ Documentation
### Getting Started
-- **[Quick Start Guide](QUICK_START.md)** - Get running in 10 minutes
-- **[Environment Setup](packages/server/ENV_SETUP_GUIDE.md)** - Configure environment variables
-- **[Deployment Guide](DEPLOYMENT_GUIDE.md)** - Deploy to production
+- **[Quick Start Guide](QUICK_START.md)** - Get running in 5 minutes
+- **[Google OAuth Setup](docs/OAUTH_SETUP.md)** - Configure Google Drive API
### Features
+- **[Sync Logic](docs/SYNC_LOGIC.md)** - How the sync algorithm works
- **[Folder Sync](FOLDER_SYNC_DOCUMENTATION.md)** - Folder structure preservation
-- **[OAuth Setup](OAUTH_REDIRECT_FIX.md)** - Dynamic OAuth configuration
-- **[Binary Files](PDF_UPLOAD_FIX.md)** - PDF and image upload support
+- **[Conflict Resolution](docs/CONFLICTS.md)** - Handling sync conflicts
+- **[Tombstone Management](docs/TOMBSTONES.md)** - Deletion tracking
### Reference
-- **[Environment Variables](ENVIRONMENT_VARIABLES.md)** - All configuration options
-- **[Server API](packages/server/README.md)** - Server documentation
+- **[Plugin API](packages/plugin/README.md)** - Plugin documentation
- **[Changelog](CHANGELOG.md)** - Version history
-- **[Summary](SUMMARY.md)** - Project overview
+- **[Architecture](docs/ARCHITECTURE.md)** - Technical overview
## ๐๏ธ Architecture
+Vync is a **local-first** plugin that runs entirely within Obsidian:
+
```
-vync/
-โโโ packages/
-โ โโโ server/ # Backend sync server
-โ โ โโโ src/
-โ โ โ โโโ routes/ # API endpoints
-โ โ โ โโโ services/# Drive services
-โ โ โโโ .env # Configuration
-โ โ
-โ โโโ plugin/ # Obsidian plugin
-โ โโโ src/
-โ โ โโโ services/# Sync services
-โ โ โโโ main.ts # Plugin entry
-โ โโโ manifest.json
-โ
-โโโ docs/ # Documentation
+vync/packages/plugin/
+โโโ src/
+โ โโโ main.ts # Plugin entry point
+โ โโโ services/
+โ โ โโโ googleDriveAuth.ts # OAuth authentication
+โ โ โโโ googleDriveService.ts# Google Drive API client
+โ โ โโโ syncService.ts # Sync orchestration
+โ โ โโโ syncState.ts # State management
+โ โ โโโ tombstoneManager.ts # Deletion tracking
+โ โ โโโ vaultWatcher.ts # File change detection
+โ โ โโโ conflictUI.ts # Conflict resolution UI
+โ โโโ types.ts # TypeScript definitions
+โโโ tests/ # Unit tests
+โโโ manifest.json # Plugin manifest
```
+### How It Works
+
+1. **Direct Integration** - Plugin communicates directly with Google Drive API
+2. **Local State** - Sync state stored in `.obsidian/plugins/vync/`
+3. **OAuth Tokens** - Encrypted and stored locally
+4. **No Server** - Zero external dependencies, completely private
+
## ๐ง Configuration
-### Server (.env)
-```bash
-# Storage backend
-DRIVE_TYPE=google # 'local' or 'google'
+### Google Drive API Setup
-# Google OAuth (if using Google Drive)
-GOOGLE_CLIENT_ID=xxx.apps.googleusercontent.com
-GOOGLE_CLIENT_SECRET=xxx
+1. **Create Google Cloud Project**
+ - Go to [Google Cloud Console](https://console.cloud.google.com/)
+ - Create a new project
+ - Enable Google Drive API
-# Optional - auto-detected if not set
-GOOGLE_REDIRECT_URI=https://your-domain.com/auth/google/callback
-```
+2. **Configure OAuth Credentials**
+ - Create OAuth 2.0 Client ID (Desktop app type)
+ - Download credentials JSON
+ - Add to plugin settings
+
+### Plugin Settings (in Obsidian)
-### Obsidian Plugin
```
Settings โ Vync:
-- Server URL: http://localhost:3000
-- Vault ID: my-vault
-- Auto Sync: ON
+โโโ Google OAuth
+โ โโโ Client ID: [from Google Cloud]
+โ โโโ Client Secret: [from Google Cloud]
+โ โโโ Status: โ Connected
+โโโ Sync Settings
+โ โโโ Auto Sync: ON
+โ โโโ Sync Interval: 5 minutes
+โ โโโ Conflict Resolution: Prompt
+โโโ Advanced
+ โโโ Tombstone Grace Period: 30 days
+ โโโ Debug Logging: OFF
```
-## ๐ Deployment
+## ๐ฆ Distribution
-### Supported Platforms
-- โ
Vercel (Serverless)
-- โ
Railway (Container)
-- โ
Render (Web Service)
-- โ
Docker (Container)
-- โ
VPS (PM2)
+### Publishing to Community Plugins
-### Quick Deploy
-```bash
-# Vercel
-vercel deploy
+When ready to publish:
-# Railway
-railway up
+1. **Create Release Branch**
+ ```bash
+ git checkout -b release/v1.0.0
+ git push origin release/v1.0.0
+ ```
-# Docker
-docker build -t vync .
-docker run -p 3000:3000 vync
-```
+2. **Automatic Release** - GitHub Actions will:
+ - Run tests
+ - Build plugin
+ - Create version tag
+ - Create GitHub release
+ - Attach `main.js`, `manifest.json`, `styles.css`
-**๐ Full guide:** [DEPLOYMENT_GUIDE.md](DEPLOYMENT_GUIDE.md)
+3. **Submit to Obsidian**
+ - Fork [obsidian-releases](https://github.com/obsidianmd/obsidian-releases)
+ - Add your plugin to `community-plugins.json`
+ - Submit PR
## ๐ How It Works
### Sync Flow
-1. **File Created** in Obsidian
-2. **Plugin Detects** change via VaultWatcher
-3. **Immediate Upload** to server
-4. **Server Uploads** to Google Drive
-5. **Index Updated** with file metadata
-6. **Folder Structure** created automatically
-
-### Index Reconciliation
-- Runs every 5 minutes automatically
-- Detects files created outside Obsidian
-- Ensures vault and index parity
-- Manual trigger via command palette
-
-### Conflict Resolution
-- Automatic detection of conflicts
-- User-prompted resolution
-- Preserves both versions
-- Tracks conflict history
-
-## ๐ Security
-
-### Best Practices
-- โ
HTTPS in production
-- โ
Environment-specific credentials
-- โ
Restricted CORS origins
-- โ
Sensitive files in .gitignore
-- โ
OAuth token encryption
-
-### Protected Files
+1. **File Changed** in Obsidian
+2. **VaultWatcher Detects** change event
+3. **SyncService** determines action (upload/download/conflict)
+4. **Direct Upload/Download** to/from Google Drive
+5. **State Updated** locally with revision IDs
+6. **Folder Structure** mirrored automatically
+
+### Smart Sync Features
+
+**Three-Way Comparison**
+- Compares: Local file โ Last sync state โ Remote file
+- Uses revision IDs (not timestamps) for accuracy
+- Detects: unchanged, local-only, remote-only, conflicts
+
+**Tombstone Management**
+- Tracks deletions with grace periods (default 30 days)
+- Syncs deletions across devices
+- Prevents accidental data loss
+
+**Conflict Resolution**
+- Detects simultaneous changes on multiple devices
+- Presents user with resolution options
+- Preserves both versions if requested
+
+## ๐ Security & Privacy
+
+### Local-First Design
+- โ
**No External Server** - Direct vault-to-Google Drive sync
+- โ
**Local OAuth Tokens** - Encrypted and stored in your vault
+- โ
**No Data Collection** - Zero telemetry or analytics
+- โ
**Open Source** - Fully auditable code
+- โ
**Standard APIs** - Uses official Google Drive API only
+
+### Data Storage
```
-.env
-.env.production
-oauth-tokens.json
-credentials.json
+.obsidian/plugins/vync/
+โโโ data.json # Plugin settings (no secrets)
+โโโ sync-state.json # Sync index (file hashes, IDs)
+โโโ tombstones.json # Deletion tracking
+โโโ .oauth-tokens.json # Encrypted OAuth tokens (local only)
```
+**Note:** OAuth tokens never leave your device and are encrypted at rest.
+
## ๐งช Testing
-### Manual Tests
+### Development
```bash
-# Test file sync
-1. Create file in Obsidian
-2. Check console for upload
-3. Verify in Google Drive
-
-# Test folder sync
-1. Create nested folders
-2. Add files to folders
-3. Check Drive structure
-
-# Test OAuth
-1. Visit /auth/google
-2. Complete flow
-3. Check /auth/status
-```
+cd packages/plugin
-### Commands
-```bash
-# Server health
-curl http://localhost:3000/health
+# Run unit tests
+bun test
+
+# Run linter
+bun run lint
-# Auth status
-curl http://localhost:3000/auth/status
+# Build plugin
+bun run build
+
+# Watch mode
+bun run dev
+```
-# Plugin commands (in Obsidian)
-- "Sync Vault"
-- "Reconcile Sync Index"
-- "Test Connection"
+### Plugin Commands (in Obsidian)
```
+Cmd/Ctrl + P โ Search for:
+โโโ "Vync: Full Sync" - Sync entire vault
+โโโ "Vync: Sync Status" - View sync state
+โโโ "Vync: Resolve Conflicts" - Handle conflicts
+โโโ "Vync: Clear Cache" - Reset sync state
+```
+
+### Manual Testing
+1. **File Sync** - Create/edit files, verify in Drive
+2. **Folder Sync** - Create nested folders, check structure
+3. **Renames** - Rename files/folders, verify tracking
+4. **Deletions** - Delete files, check tombstones
+5. **Conflicts** - Edit same file on two devices simultaneously
## ๐ Troubleshooting
### Common Issues
-**Server won't start**
-```bash
-# Check port availability
-lsof -i :3000
-# Use different port
-PORT=8080 bun run dev
-```
+**OAuth Authentication Failed**
+- Verify Client ID and Secret are correct
+- Check OAuth consent screen is configured
+- Ensure "Desktop app" type is selected
+- Try removing and re-adding credentials
-**OAuth errors**
-```bash
-# Add redirect URI to Google Console
-http://localhost:3000/auth/google/callback
-```
+**Files Not Syncing**
+- Check sync status in plugin settings
+- Verify Google Drive has sufficient space
+- Look for conflicts in conflict resolution UI
+- Check Obsidian Developer Console (Cmd/Ctrl + Shift + I) for errors
-**Files not syncing**
-```bash
-# Run index reconciliation
-Cmd/Ctrl + P โ "Reconcile Sync Index"
-```
+**Sync Conflicts**
+- Use "Vync: Resolve Conflicts" command
+- Choose which version to keep
+- Or keep both versions with different names
+
+**Plugin Not Loading**
+- Check `.obsidian/plugins/vync/` exists
+- Verify `manifest.json`, `main.js`, `styles.css` are present
+- Enable plugin in Settings โ Community Plugins
+- Check Obsidian console for error messages
-**๐ More solutions:** See documentation links above
+**๐ More help:** [Open an issue](https://github.com/your-repo/issues)
## ๐ Roadmap
-### v1.1 (Short Term)
-- [ ] File deletion from Google Drive
-- [ ] Chunked large file uploads
-- [ ] Selective sync patterns
+### v1.1 (Next Release)
+- [ ] Delta sync for large files
+- [ ] Selective sync (exclude patterns)
+- [ ] Bandwidth optimization
+- [ ] Sync statistics dashboard
-### v1.2 (Medium Term)
-- [ ] Real-time collaboration
-- [ ] Mobile app support
-- [ ] Alternative storage backends
+### v1.2 (Future)
+- [ ] Mobile app support (iOS/Android)
+- [ ] Alternative backends (Dropbox, OneDrive)
+- [ ] End-to-end encryption option
+- [ ] Shared vault collaboration
### v2.0 (Long Term)
-- [ ] End-to-end encryption
-- [ ] Multi-user support
-- [ ] Advanced conflict resolution
+- [ ] Multi-device conflict resolution UI
+- [ ] Advanced sync rules engine
+- [ ] Plugin marketplace integration
+- [ ] Automated backups and versioning
## ๐ค Contributing
@@ -266,9 +307,10 @@ Built with:
## ๐ฌ Support
-- **Documentation**: See links above
-- **Issues**: GitHub Issues
-- **Discussions**: GitHub Discussions
+- **Documentation**: See [Documentation](#-documentation) section
+- **Bug Reports**: [GitHub Issues](https://github.com/your-repo/issues)
+- **Feature Requests**: [GitHub Discussions](https://github.com/your-repo/discussions)
+- **Questions**: [GitHub Discussions Q&A](https://github.com/your-repo/discussions/categories/q-a)
## โญ Star History
@@ -276,8 +318,6 @@ If this project helps you, consider giving it a star!
---
-**Status**: Production Ready โ
-**Version**: 1.0.0
-**Last Updated**: 2024
+**Status**: Beta Testing ๐ง
-[Quick Start](QUICK_START.md) | [Documentation](SUMMARY.md) | [Deployment](DEPLOYMENT_GUIDE.md) | [Contributing](#contributing)
\ No newline at end of file
+[Quick Start](QUICK_START.md) | [Documentation](#-documentation) | [Architecture](#-architecture) | [Contributing](#-contributing)
\ No newline at end of file
diff --git a/assets/illustration.png b/assets/illustration.png
new file mode 100644
index 0000000..73f2dda
Binary files /dev/null and b/assets/illustration.png differ