# richardx366/obsidian-google-drive architecture

> Architecture diagram of the GitHub repository richardx366/obsidian-google-drive, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-06-22). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/richardx366/obsidian-google-drive
- Repository: https://github.com/richardx366/obsidian-google-drive

## Overview

1. **What this repository is**
   - This is an **Obsidian plugin** that syncs a vault with **Google Drive**.
   - The runtime boundary is the **Obsidian app on the user’s device**; the plugin runs inside Obsidian and manipulates the vault through Obsidian’s plugin API, not by directly acting as a separate desktop service.

2. **Top-level architecture**
   - `main.ts` is the plugin entrypoint and orchestration layer.
   - The sync logic is split into small helpers under `helpers/`, which suggests a command-driven architecture rather than a large monolith.
   - `pull.ts`, `push.ts`, and `reset.ts` represent the three main synchronization modes exposed to the user.

3. **Local subsystem: Obsidian vault + plugin state**
   - The plugin’s primary local boundary is the **vault filesystem** managed by Obsidian.
   - It likely watches/reads local files through Obsidian APIs and converts them into sync operations.
   - The README makes clear that file changes made outside Obsidian are intentionally out of scope; this is a key architectural constraint because the plugin depends on Obsidian’s change tracking.

4. **Remote subsystem: Google Drive**
   - Google Drive is the canonical remote storage for synced vault content.
   - The plugin creates a Drive folder per vault and uses Drive metadata/properties to associate files with the correct vault.
   - The multi-vault design is based on **vault-name identity**, not a single global account-wide sync bucket.

5. **Authentication and token boundary**
   - The plugin does **not** appear to do a direct Google OAuth flow inside Obsidian.
   - Instead, the README indicates it uses `https://ogd.richardxiong.com` to convert a **refresh token into an access token**, explicitly to hide the client secret.
   - That service is also used for a connectivity ping, so it is part auth broker, part availability check.

6. **Sync flow: pull first, then push**
   - The main operational flow is: **pull changes from Google Drive, then push local changes**.
   - This ordering is important because the README says push commands first pull, then upload.
   - The sync engine therefore behaves like a reconciliation pipeline, not a pure upload tool.

7. **Conflict handling and data precedence**
   - The plugin’s conflict policy is intentionally simple: **local file priority** with automatic resolution.
   - The README notes one special case: cloud-side creation/modification can overwrite a local deletion.
   - That means the architecture favors deterministic reconciliation over manual conflict UI or merge tooling.

8. **Reset / state alignment**
   - `reset.ts` implies a destructive or re-baselining path used to make the local vault match Drive state.
   - This is a separate subsystem from incremental sync, useful when the local vault must be treated as a mirror of remote state.
   - In an architecture diagram, this is the “state reset” edge case, distinct from routine push/pull.

9. **HTTP and API client layer**
   - `helpers/ky.ts` is likely a shared HTTP client wrapper, probably built around the `ky` library.
   - `helpers/drive.ts` likely centralizes Google Drive API operations and abstract Drive file/folder representation.
   - This separation matters because it isolates transport concerns from sync logic.

10. **User-facing commands and interaction points**
   - The README references a ribbon button and command palette commands:
     - Pull from Google Drive
     - Push to Google Drive
     - Set Local Vault to Google Drive
   - These are user-triggered entry points into the same underlying sync engine, so the diagram should show multiple UI triggers converging into shared synchronization logic.

11. **Build/release and package structure**
   - `esbuild.config.mjs` indicates the plugin is bundled for distribution with **esbuild**.
   - `manifest.json` and `versions.json` are Obsidian plugin packaging/version compatibility metadata.
   - `.github/workflows/release.yml` and `version-bump.mjs` show an automated release pipeline, so there is a build-and-publish boundary separate from runtime sync behavior.

12. **What to emphasize in an architecture diagram**
   - Show three major zones:
     - **Obsidian local vault/plugin runtime**
     - **Google Drive API**
     - **ogd.richardxiong.com token broker / connectivity service**
   - Then connect them through:
     - **main.ts orchestration**
     - **sync helpers**
     - **auth/token exchange**
     - **Drive metadata mapping for vault identity**
   - The most important data flow is local file state ⇄ sync engine ⇄ Drive objects, with auth mediated by the external token service.

Main entry points: [`main.ts`](https://github.com/richardx366/obsidian-google-drive/blob/master/main.ts) (Main), [`helpers/drive.ts`](https://github.com/richardx366/obsidian-google-drive/blob/master/helpers/drive.ts) (Drive API), [`helpers/push.ts`](https://github.com/richardx366/obsidian-google-drive/blob/master/helpers/push.ts) (Push), [`helpers/pull.ts`](https://github.com/richardx366/obsidian-google-drive/blob/master/helpers/pull.ts) (Pull)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_runtime["Obsidian runtime"]
  node_main_ts["Main<br/>plugin entrypoint<br/>[main.ts]"]
  node_pull_ts["Pull<br/>sync command<br/>[pull.ts]"]
  node_push_ts["Push<br/>sync command<br/>[push.ts]"]
  node_reset_ts["Reset<br/>resync command<br/>[reset.ts]"]
  node_drive_ts["Drive API<br/>drive adapter<br/>[drive.ts]"]
  node_ky_ts["HTTP client<br/>request wrapper<br/>[ky.ts]"]
  node_vault[("Vault<br/>local filesystem")]
  node_ui(("Commands<br/>user triggers"))
  node_sync_state{{"Reconcile<br/>sync policy"}}
end

subgraph group_remote["Remote services"]
  node_token_service(("Token broker<br/>auth broker"))
  node_gdrive[("Google Drive<br/>remote storage")]
  node_vault_map{{"Vault mapping<br/>identity mapping"}}
end

subgraph group_release["Build and release"]
  node_esbuild["Bundler<br/>build tool<br/>[esbuild.config.mjs]"]
  node_manifest["Manifest<br/>plugin metadata<br/>[manifest.json]"]
  node_versions["Versions<br/>compatibility map<br/>[versions.json]"]
  node_version_bump["Version bump<br/>release script<br/>[version-bump.mjs]"]
  node_release_wf["Release CI<br/>publish workflow<br/>[release.yml]"]
end

node_ui -->|"invoke"| node_main_ts
node_main_ts -->|"dispatch"| node_pull_ts
node_main_ts -->|"dispatch"| node_push_ts
node_main_ts -->|"dispatch"| node_reset_ts
node_main_ts -->|"coordinate"| node_drive_ts
node_main_ts -->|"coordinate"| node_ky_ts
node_main_ts -->|"read/write"| node_vault
node_pull_ts -->|"fetch"| node_drive_ts
node_pull_ts -->|"apply"| node_vault
node_push_ts -->|"pre-sync"| node_pull_ts
node_push_ts -->|"upload"| node_drive_ts
node_push_ts -->|"scan"| node_vault
node_reset_ts -->|"baseline"| node_drive_ts
node_reset_ts -->|"overwrite"| node_vault
node_drive_ts -->|"api calls"| node_gdrive
node_drive_ts -->|"map identity"| node_vault_map
node_vault_map -->|"folder metadata"| node_gdrive
node_ky_ts -->|"token exchange"| node_token_service
node_ky_ts -->|"http transport"| node_gdrive
node_sync_state -->|"policy"| node_pull_ts
node_sync_state -->|"policy"| node_push_ts
node_sync_state -->|"policy"| node_reset_ts
node_release_wf -->|"run"| node_version_bump
node_release_wf -->|"build"| node_esbuild
node_version_bump -->|"update"| node_manifest
node_version_bump -->|"update"| node_versions
node_esbuild -->|"package"| node_manifest

click node_main_ts "https://github.com/richardx366/obsidian-google-drive/blob/master/main.ts"
click node_pull_ts "https://github.com/richardx366/obsidian-google-drive/blob/master/helpers/pull.ts"
click node_push_ts "https://github.com/richardx366/obsidian-google-drive/blob/master/helpers/push.ts"
click node_reset_ts "https://github.com/richardx366/obsidian-google-drive/blob/master/helpers/reset.ts"
click node_drive_ts "https://github.com/richardx366/obsidian-google-drive/blob/master/helpers/drive.ts"
click node_ky_ts "https://github.com/richardx366/obsidian-google-drive/blob/master/helpers/ky.ts"
click node_esbuild "https://github.com/richardx366/obsidian-google-drive/blob/master/esbuild.config.mjs"
click node_manifest "https://github.com/richardx366/obsidian-google-drive/blob/master/manifest.json"
click node_versions "https://github.com/richardx366/obsidian-google-drive/blob/master/versions.json"
click node_version_bump "https://github.com/richardx366/obsidian-google-drive/blob/master/version-bump.mjs"
click node_release_wf "https://github.com/richardx366/obsidian-google-drive/blob/master/.github/workflows/release.yml"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_main_ts,node_pull_ts,node_push_ts,node_reset_ts,node_drive_ts,node_ky_ts,node_vault,node_ui,node_sync_state toneBlue
class node_token_service,node_gdrive,node_vault_map toneAmber
class node_esbuild,node_manifest,node_versions,node_version_bump,node_release_wf toneMint
```

## Components

### Obsidian runtime

Plugin code running inside the Obsidian app against the local vault

- [Main](https://github.com/richardx366/obsidian-google-drive/blob/master/main.ts): plugin entrypoint · Registers commands and orchestrates sync flows inside Obsidian · `main.ts`
- [Pull](https://github.com/richardx366/obsidian-google-drive/blob/master/helpers/pull.ts): sync command · Reconciles local state from Google Drive into the vault · `helpers/pull.ts`
- [Push](https://github.com/richardx366/obsidian-google-drive/blob/master/helpers/push.ts): sync command · Pulls first, then uploads local changes to Drive · `helpers/push.ts`
- [Reset](https://github.com/richardx366/obsidian-google-drive/blob/master/helpers/reset.ts): resync command · Re-baselines the local vault to match Drive state · `helpers/reset.ts`
- [Drive API](https://github.com/richardx366/obsidian-google-drive/blob/master/helpers/drive.ts): drive adapter · Centralized Google Drive operations and vault/file mapping · `helpers/drive.ts`
- [HTTP client](https://github.com/richardx366/obsidian-google-drive/blob/master/helpers/ky.ts): request wrapper · Shared HTTP transport for Drive and token-service calls · `helpers/ky.ts`
- **Vault**: local filesystem · Obsidian-managed local note store and change boundary
- **Commands**: user triggers · Ribbon button and command-palette entry points into sync
- **Reconcile**: sync policy · Local-first reconciliation with automatic conflict resolution

### Remote services

Google Drive storage and the external token broker used for auth

- **Token broker**: auth broker · Converts refresh tokens to access tokens and provides a connectivity ping
- **Google Drive**: remote storage · Canonical remote store for synced vault content
- **Vault mapping**: identity mapping · Associates a vault with its Drive folder and metadata

### Build and release

Bundling, versioning, and publishing metadata for the plugin

- [Bundler](https://github.com/richardx366/obsidian-google-drive/blob/master/esbuild.config.mjs): build tool · Produces the distributable plugin bundle · `esbuild.config.mjs`
- [Manifest](https://github.com/richardx366/obsidian-google-drive/blob/master/manifest.json): plugin metadata · Obsidian plugin package metadata and compatibility info · `manifest.json`
- [Versions](https://github.com/richardx366/obsidian-google-drive/blob/master/versions.json): compatibility map · Version-to-release compatibility metadata · `versions.json`
- [Version bump](https://github.com/richardx366/obsidian-google-drive/blob/master/version-bump.mjs): release script · Automates plugin version updates during release · `version-bump.mjs`
- [Release CI](https://github.com/richardx366/obsidian-google-drive/blob/master/.github/workflows/release.yml): publish workflow · GitHub Actions pipeline for building and releasing the plugin · `.github/workflows/release.yml`

## Connections

- Commands → Main: invoke · User commands and ribbon actions enter the plugin through the main orchestrator
- Main → Pull: dispatch · Main routes the pull command into the pull workflow
- Main → Push: dispatch · Main routes the push command into the push workflow
- Main → Reset: dispatch · Main routes the reset command into the resync workflow
- Main → Drive API: coordinate · Main shares the Drive adapter across sync modes
- Main → HTTP client: coordinate · Main relies on shared HTTP plumbing for remote requests
- Main → Vault: read/write · The plugin operates on the Obsidian-managed local vault
- Pull → Drive API: fetch · Pull reads remote Drive state through the adapter
- Pull → Vault: apply · Pulled remote changes are written into the vault
- Push → Pull: pre-sync · Push performs a pull first before uploading local changes
- Push → Drive API: upload · Push sends local file changes through the Drive adapter
- Push → Vault: scan · Push inspects local vault state before uploading
- Reset → Drive API: baseline · Reset rebuilds local state from remote Drive contents
- Reset → Vault: overwrite · Reset aligns the vault to the chosen remote baseline
- Drive API → Google Drive: api calls · The Drive adapter is the repository's remote storage boundary
- Drive API → Vault mapping: map identity · Drive metadata binds files to the correct vault and folder
- Vault mapping → Google Drive: folder metadata · Vault identity is represented in Drive folder structure and properties
- HTTP client → Token broker: token exchange · HTTP client requests access tokens from the external broker
- HTTP client → Google Drive: http transport · Shared client also carries Drive API requests
- Reconcile → Pull: policy · Reconciliation rules shape how pull resolves differences
- Reconcile → Push: policy · Reconciliation rules shape upload order and precedence
- Reconcile → Reset: policy · Reset uses the same state-alignment rules in destructive form
- Release CI → Version bump: run · CI drives automated version updates during release
- Release CI → Bundler: build · Release workflow bundles the plugin for distribution
- Version bump → Manifest: update · Release automation keeps plugin metadata in sync
- Version bump → Versions: update · Release automation updates compatibility mappings
- Bundler → Manifest: package · Bundling targets the Obsidian plugin package structure
