How martinlegend/neogdsync works
1. What this repository is
- NeoGDSync is an Obsidian plugin that synchronizes an Obsidian vault with a Google Drive folder.
- The architecture is split between:
- the local plugin running inside Obsidian
- an optional OAuth proxy worker used to help with token acquisition/refresh flows
- Google Drive as the external storage backend
2. Main runtime boundary
- The core application is the Obsidian plugin itself, built from src/main.ts and supporting TypeScript modules.
- The plugin runs in the Obsidian desktop app environment, not as a standalone server.
- Its responsibilities include UI wiring, command registration, sync orchestration, and persistent plugin settings.
3. User-facing entry points
- Sync can be started from:
- Obsidian ribbon icon / command palette
- the custom URI scheme obsidian://neogdsync?...
- Supported modes are:
- smart sync: compare local and remote, sync only deltas, detect conflicts
- force push: local vault → Drive
- force pull: Drive → local vault
- These entry points are thin; they delegate to the sync engine rather than performing sync logic themselves.
4. Sync engine
- The central coordination layer is in src/syncer.ts / src/syncer.js.
- It likely owns the end-to-end flow:
- load config and state
- build or read the Drive index
- enumerate local vault files
- compare snapshots / metadata
- decide upload, download, delete, or conflict actions
- update stored state after completion
- This is the main subsystem to show as the “brain” of the plugin.
5. Drive API boundary
- src/driveApi.ts / src/driveApi.js isolates all communication with Google Drive REST APIs.
- This module is the external-service adapter for:
- listing files/folders
- reading metadata
- uploading/downloading file content
- creating revision history when enabled
- resolving folder/file IDs and parent-child relationships
- Keeping Drive calls behind this module makes the rest of the plugin independent of API details.
6. Authentication subsystem
- src/auth.ts handles OAuth-related state and token usage.
- The README shows the plugin uses a Google OAuth2 refresh token with Drive scope, stored locally in Obsidian plugin data.
- The auth layer is the boundary between local configuration and authenticated Drive requests.
- The token is not a user-facing session; it is a long-lived credential used by the Drive client to obtain access tokens when needed.
7. Local state, indexing, and conflict detection
- src/pathIndex.ts, src/snapshot.ts, and src/types.ts suggest the plugin maintains a path-based index and file-state snapshots.
- The README explicitly says the plugin avoids a full crawl after the first sync, so this state is important to architecture:
- pathIndex maps vault paths to Drive item IDs / metadata
- snapshot captures local or remote state for comparison
- types centralizes shared data contracts
- This state is what enables “smart sync” and conflict detection without re-walking the entire Drive tree every time.
8. File normalization and content handling
- src/mime.ts likely maps file extensions/content types to Google Drive MIME handling rules.
- This is important because Drive treats binary files, markdown, folders, and special metadata differently.
- The sync layer needs this mapping to decide how to upload, download, and preserve file semantics correctly.
9. Conflict and version history behavior
- A key product boundary is that conflicts are never silently overwritten.
- When local and remote diverge, the plugin saves the Drive copy as a conflict file rather than destroying data.
- Optional version history on Drive suggests the sync engine can preserve revisions instead of replacing content blindly.
- In architecture diagrams, this should appear as a decision point inside the sync engine before write operations.
10. Excludes and vault scoping
- The plugin supports configurable excludes via glob patterns.
- This means the sync pipeline does not operate on the entire vault uniformly; it filters candidate paths before comparison and upload/download.
- The Drive root folder ID is also a hard boundary: only the subtree under that Drive folder is treated as the synced vault.
11. OAuth proxy worker
- The oauth-proxy/ directory contains a Cloudflare Worker (worker.js + wrangler.toml).
- This is a separate deployment boundary from the Obsidian plugin.
- Its role is likely to support OAuth-related flows externally, such as redirect handling or token exchange assistance, so the plugin does not need to host a web server itself.
- Architecturally, it sits between the user’s browser/Google OAuth endpoints and the local token acquisition workflow.
12. Persistence and packaging
- Plugin state is stored locally in Obsidian’s plugin data, not in a backend database.
- The repository is packaged as an Obsidian plugin using standard frontend tooling:
- TypeScript source in src/
- esbuild.config.mjs for bundling
- manifest.json for Obsidian plugin metadata
- styles.css for UI styling
- versions.json indicates release/version compatibility metadata for the plugin distribution.
13. Non-functional boundaries
- The repo includes docs/privacy.html, which matters because the system handles sensitive OAuth credentials and file metadata.
- The privacy boundary is simple but important: credentials are stored locally and only sent to Google for authentication and Drive API access.
- No application backend is present in the main plugin; Google Drive is the only primary external data store.
14. How to draw the diagram
- Show Obsidian as the host runtime containing the plugin.
- Inside the plugin, draw modules for:
- UI/commands/URI handler
- sync orchestration
- auth/token management
- Drive API client
- index/snapshot/state
- MIME/file handling
- Draw Google Drive as the external service boundary.
- Draw the Cloudflare Worker as a separate optional support service for OAuth.
Main entry points: syncer.ts Sync engine · driveApi.ts Drive client · main.ts Plugin entry · auth.ts Auth manager
Components 17
Obsidian host
Desktop runtime that embeds the plugin and exposes the vault
- Obsidian · Desktop app hosting the plugin
- Vault · User files managed by the plugin
NeoGDSync plugin
Local TypeScript modules that register commands and run sync
- Plugin entry · Registers plugin behavior and wires the runtime
src/main.ts - UI & commands · Ribbon actions, command palette, and user triggers
src/main.ts - URI handler · Handles obsidian://neogdsync requests
src/main.ts - Sync engine · Coordinates smart sync, force push, and force pull
src/syncer.ts - Conflict policy · Detects divergence and preserves conflicting copies
src/syncer.ts - Auth manager · Manages refresh token use and authenticated access
src/auth.ts - Drive client · Wraps Google Drive REST calls for files and folders
src/driveApi.ts - Path index · Maps vault paths to Drive item identity and metadata
src/pathIndex.ts - Snapshot model · Captures local or remote file state for comparison
src/snapshot.ts - File rules · Normalizes file types and Drive MIME handling
src/mime.ts - Shared types · Common data contracts used across the sync pipeline
src/types.ts - Plugin data · Stored settings, tokens, and cached sync metadata
OAuth support
Optional Cloudflare Worker used to assist OAuth flows
- OAuth worker · Optional proxy service for OAuth redirect or token flow support
oauth-proxy/worker.js
External services
Google services the plugin talks to
- Google OAuth · OAuth endpoint used to obtain Drive access
- Google Drive · Remote storage backend and metadata source
Connections 22
- Obsidian → Plugin entry: hosts · Obsidian loads the plugin runtime
- Plugin entry → UI & commands: wires · Registers user-facing actions
- Plugin entry → URI handler: wires · Installs custom URI handling
- UI & commands → Sync engine: triggers · Starts sync from ribbon or command palette
- URI handler → Sync engine: triggers · Dispatches obsidian://neogdsync requests
- Sync engine → Auth manager: authenticates · Obtains authorized Drive access before remote operations
- Auth manager → OAuth worker: assists · Uses the optional proxy for OAuth flow support
- OAuth worker → Google OAuth: redirects · Brokers OAuth-related browser interaction
- Auth manager → Plugin data: reads/writes · Persists refresh token and auth state locally
- Sync engine → Path index: loads/updates · Uses the index to avoid full Drive crawls
- Sync engine → Snapshot model: compares · Builds or reads snapshots for delta detection
- Sync engine → File rules: normalizes · Chooses upload and download handling by file type
- Sync engine → Shared types: uses · Shares domain contracts across sync stages
- Sync engine → Conflict policy: decides · Routes divergent changes through conflict handling
- Conflict policy → Drive client: guards writes · Prevents silent overwrite of remote data
- Sync engine → Drive client: syncs · Executes listing, upload, download, and metadata operations
- Drive client → Google Drive: calls · Communicates with Google Drive REST APIs
- Sync engine → Vault: reads/writes · Enumerates local files and applies synced changes
- Sync engine → Plugin data: persists state · Stores sync progress and cached metadata
- Path index → Plugin data: backed by · Index state is retained in plugin data
- Snapshot model → Shared types: structured by · Snapshot records follow shared domain contracts
- File rules → Drive client: guides content · Influences how Drive payloads are encoded and decoded