Public
Like
1
google-calendar-linear-sync
Val Town is a collaborative website to build and scale JavaScript apps.
Deploy APIs, crons, & store data ā all from the browser, and deployed in miliseconds.
This document visualizes the bidirectional sync system architecture using the Declarative Reconciliation Loop (DRL) pattern.
sequenceDiagram participant User participant Worker as SyncWorker participant Linear as Linear API participant GCal as Google Calendar API participant Projector participant Diff as Diff Engine participant Actuator User->>Worker: deno task sync Note over Worker: 1. OBSERVE Phase Worker->>Linear: getIssues(teamId) Linear-->>Worker: LinearIssue[] Worker->>GCal: getEvents(calendarId, timeRange) GCal-->>Worker: GCalEvent[] Note over Worker: 2. PROJECT Phase Worker->>Projector: project(linearIssues, gcalEvents) Projector->>Projector: Parse metadata links Projector->>Projector: Classify into phases Projector-->>Worker: CanonicalItem[] Note over Worker: 3. DIFF Phase Worker->>Diff: diff(canonicalItems) Diff->>Diff: Analyze phase transitions Diff->>Diff: Generate operations Diff-->>Worker: Operation[] Note over Worker: 4. ACTUATE Phase Worker->>Actuator: execute(operations) loop For each operation alt Create Linear Issue Actuator->>Linear: createIssue() Linear-->>Actuator: LinearIssue Actuator->>GCal: updateEvent(addMetadata) else Create GCal Event Actuator->>GCal: createEvent() GCal-->>Actuator: GCalEvent Actuator->>Linear: updateIssue(addMetadata) else Update Status Actuator->>GCal: updateEvent(prefix) end end Actuator-->>Worker: SyncResult Worker-->>User: ā Sync completed
stateDiagram-v2 [*] --> eventOnly: New GCal event [*] --> linearOnly: New Linear issue eventOnly --> active: Create Linear issue (š„ Triage) linearOnly --> active: Create GCal event (š Scheduled) active --> completed: Linear state = Done/Canceled/Failed active --> overdue: >24h past event end active --> active: Metadata sync completed --> [*]: Update GCal prefix (ā /š«/ā) overdue --> [*]: Archive with ā³ prefix note right of eventOnly š„ GCal event without Linear match end note note right of linearOnly š Linear issue marked as "Scheduled" end note note right of active š Both systems have linked records end note note right of completed ā Linear marked as Done/Canceled/Failed end note note right of overdue ā³ Past deadline but still tracking end note
flowchart TD A[Linear Issues] --> P[Projector] B[Google Calendar Events] --> P P --> C1[eventOnly Items] P --> C2[linearOnly Items] P --> C3[active Items] P --> C4[completed Items] P --> C5[overdue Items] C1 --> D[Diff Engine] C2 --> D C3 --> D C4 --> D C5 --> D D --> O1[createLinearIssue] D --> O2[createGCalEvent] D --> O3[patchGCalEvent] D --> O4[createRescheduledEvent] O1 --> Act[Actuator] O2 --> Act O3 --> Act O4 --> Act Act --> LA[Linear API] Act --> GA[Google Calendar API] LA --> LU[š„ Issues Created/Updated] GA --> GU[š Events Created/Updated] style P fill:#e1f5fe style D fill:#f3e5f5 style Act fill:#e8f5e8 style LA fill:#fff3e0 style GA fill:#fce4ec
sequenceDiagram participant L as Linear Issue participant M as Metadata Parser participant G as GCal Event Note over L,G: Bidirectional Linking via Metadata L->>M: description with metadata Note right of M: <!-- calendar-sync --><br/>GoogleCalEventId:abc123<br/>Start:2025-07-19T10:00:00Z<br/>DurMin:30 G->>M: extendedProperties Note left of M: extendedProperties.private:<br/>{ linearIssueId: "issue-123" } M->>M: Parse and validate links M-->>L: Linked to GCal event abc123 M-->>G: Linked to Linear issue-123 Note over L,G: Creates canonical truth for sync decisions
flowchart LR Dev[Developer] --> Check{deno task check} Check --> |ā Valid| Validate{deno task validate} Check --> |ā Missing vars| Setup[deno task setup] Setup --> Check Validate --> |ā APIs work| DryRun[deno task dry-run] Validate --> |ā API issues| Fix[Fix credentials] Fix --> Validate DryRun --> |ā Safe| Sync[deno task sync] DryRun --> |ā Issues| Debug[Check operations] Debug --> DryRun Sync --> |ā Success| Monitor[Monitor results] Sync --> |ā Errors| Debug style Check fill:#e3f2fd style Validate fill:#f3e5f5 style DryRun fill:#e8f5e8 style Sync fill:#fff3e0
- Stateless: No database required; all state lives in remote systems via UID linkages
- Deterministic: Pure functions ensure identical inputs always produce identical outputs
- Idempotent: Operations can be safely retried without side effects
- Minimal: Only necessary changes are made to external systems
- Observable: Clear phase classifications and operation logging for debugging