# Sync Trakt
[](https://github.com/o1xhack/obsidian-sync-trakt/releases)
[](https://github.com/o1xhack/obsidian-sync-trakt/releases)
[](LICENSE)
[](https://obsidian.md)
[](https://github.com/sponsors/o1xhack)
**Turn your [Trakt.tv](https://trakt.tv) watch history into a richly localized Markdown library โ with per-episode timestamps, metadata in 15+ languages, and quiet incremental sync that doesn't churn your vault.**
> ๐ **English** ยท [็ฎไฝไธญๆ](docs/i18n/README.zh-CN.md) ยท [็น้ซไธญๆ](docs/i18n/README.zh-TW.md) ยท [ๆฅๆฌ่ช](docs/i18n/README.ja.md) ยท [ํ๊ตญ์ด](docs/i18n/README.ko.md) ยท [Franรงais](docs/i18n/README.fr.md) ยท [Deutsch](docs/i18n/README.de.md) ยท [Espaรฑol](docs/i18n/README.es.md) ยท [Italiano](docs/i18n/README.it.md)
## โจ Why?
- **Detailed watch history** โ exactly which episode you watched at what time, including re-watches, kept in sync as you keep watching
- **Metadata in 15+ languages** โ translate titles / overviews / taglines / genres via TMDB. Built-in presets for Chinese (CN / TW / HK), Japanese, Korean, French, German, Spanish (ES / MX), Portuguese (BR), Italian, Russian โ plus a custom mode for any TMDB-supported locale. **Strict primary + user-defined fallback** (e.g. zh-CN with English fallback) prevents silent zh-TW substitutions when the primary translation is missing. English originals always preserved in `*_original_*` frontmatter fields
- **Filenames follow your language** โ switch metadata language and existing notes auto-rename on the next sync to match the new title. Internal Obsidian links update automatically. One-shot "Rename now" button in settings for manual triggers
- **Note templates in 11 languages** โ hand-curated bundled templates (en + zh-CN + zh-TW + ja + ko + fr + de + it + es + pt-BR + ru). Pick from the template-language dropdown; switch any time without losing customizations
- **Tabbed settings UI** โ General / Notes / Sync / Daily Notes. Last-viewed tab remembered per device
- **Daily Notes integration** โ auto-injects per-event lines (watched / watchlist / favorited / rated) into your Daily Note on every sync, chronologically sorted, in your chosen template language. Marker-bounded region is fully isolated โ content outside it is **never modified**. Optional incremental mode preserves your hand-written annotations inside the marker block. Manual date-range backfill with quick presets (Last 7 days / This month / etc.). Daily Notes can also run on their own auto-sync interval without rewriting media notes. See [spec 0006](docs/specs/0006-daily-notes-integration.md) and [spec 0011](docs/specs/0011-daily-notes-auto-sync.md)
- **Fast incremental sync** โ first sync seeds the local TMDB cache + Trakt history state; subsequent syncs only fetch what changed. Steady-state sync time drops from minutes to single-digit seconds. See [spec 0001](docs/specs/0001-incremental-sync.md)
- **Quiet writes** โ sync only rewrites notes whose content actually changed. After watching one new episode, a 1200-item library writes one note instead of all 1200 โ your cross-device sync layer (Obsidian Sync / iCloud / Syncthing) stops re-uploading the entire library every run. See [spec 0002](docs/specs/0002-diff-based-write.md)
- **Per-setting cloud toggle** โ pick which settings sync across devices and which stay local. Auto-sync interval, startup-sync toggle, UI language โ each can be device-local so your Mac and iPhone don't fight over them. See [spec 0003](docs/specs/0003-device-local-settings.md)
## ๐ฌ Detailed watch history
When **Sync watch history (detailed)** is enabled, the plugin queries Trakt's `/sync/history` endpoint and inlines per-episode (or per-movie) timestamps into the note body โ and keeps that block updated as you watch new episodes:
```markdown
## Watch History
- S1E1 โ 2024-01-15 21:30, 2024-03-22 19:00
- S1E2 โ 2024-01-16 22:00
- S1E3 โ 2024-01-17 21:45
- S2E1 โ 2024-04-02 20:00
```
Re-watches are listed comma-separated; episodes sort by season then episode number. The block is wrapped in `%% trakt:watch-history %%` markers โ the plugin updates only what's between the markers, so any hand-written notes elsewhere in the body are never touched.
## ๐ Metadata localization
Set **Metadata language** to your preference and synced notes get title, overview, tagline, and genres translated via TMDB (with Trakt's translation endpoint as a fallback when no TMDB key is configured). English originals stay in `trakt_original_*` frontmatter fields:
```yaml
trakt_title: ้ปๆ้ชๅฃซ
trakt_original_title: The Dark Knight
trakt_genres:
- ๅจไฝ
- ็ฏ็ฝช
- ๅงๆ
trakt_original_genres:
- Action
- Crime
- Drama
trakt_metadata_language: zh-CN
```
Tags and tag-note paths always stay in English โ your existing Dataview queries keep working unchanged.
## ๐ Plugin UI + note templates
Metadata localization above is one axis; the plugin's own surfaces are separate axes:
- **Settings tab, command palette, notice popups** speak **English** and **็ฎไฝไธญๆ**. More UI languages on demand โ [open an issue](https://github.com/o1xhack/obsidian-sync-trakt/issues) if you want to volunteer one.
- **Bundled note templates** in 11 languages โ English, Simplified Chinese (zh-CN), Traditional Chinese (zh-TW / zh-HK), Japanese, Korean, French, German, Italian, Spanish, Portuguese (BR), Russian. Hand-curated, not machine-translated; section headings, bullet labels, and punctuation follow each language's conventions (full-width colons in Japanese, spaced colons in French, etc.). The template-language dropdown lists exactly these 11; locales outside the list fall back to English (rather than silently picking a sibling locale).
## ๐
Daily Notes integration
Auto-inserts per-event lines into your Daily Note for every sync โ chronologically sorted, in your chosen template language. Covers watched episodes, watchlist additions, favorites, and ratings:
```markdown
%% trakt:daily:start %%
10:00 โ ็ไบ ไฝๆบๅ็ฏ็ฝช (2026) S1E16, S1E17
14:30 โ ๅ ๅ
ฅๆณ็ ้ปๆ้ชๅฃซ (2008)
21:30 โ ๆๅ 9/10 ้็ (2020)
%% trakt:daily:end %%
```
Each event type is gated by its corresponding sync source toggle โ if `Sync favorites` is off, favorite events won't appear in Daily Notes either. Verbs (`watched` / `็ไบ` / `่ฆ่ด` / `์์ฒญ` / `a regardรฉ`โฆ) follow your **template language** setting across all 11 bundled languages.
**Safety contract**: the marker region is fully isolated โ content outside it is **never modified**. Past days are add-only by default (existing markers preserved); today is overwritten so newer events appear on later syncs. An **incremental mode** opt-in changes today's behavior to append-only too, so any annotations you write inside the marker block survive every sync.
**Manual backfill** uses a date-range picker with quick presets (Last 7 days / Last 30 days / This month / Last month). Live count shows how many Daily Notes actually exist in the picked range before you confirm. Configure folder + filename format (Moment.js syntax like `YYYY-MM-DD` or `YYYY/YYYY.MM.DD`) in **Settings โ Daily Notes**. See [spec 0006](docs/specs/0006-daily-notes-integration.md).
**Daily Notes-only auto-sync** can be enabled separately from full media
auto-sync. It refreshes the Trakt/TMDB data needed for Daily Notes and
updates existing Daily Note files, but it does not create, rename,
delete, or rewrite media notes. The Daily-only timer and the full sync
timer share one lock, so if they fire together, one run skips instead of
writing concurrently.
## ๐ Cross-device sync
Auth state โ Trakt tokens, TMDB key, all settings โ lives in `/.obsidian/plugins/sync-trakt/data.json` and follows your vault-sync layer. Configure auth once on Mac, share with iPhone via Obsidian Sync (with `Plugin data` enabled), Syncthing, iCloud + Advanced Data Protection, or Cryptomator. The plugin doesn't store anything on a server.
Large rebuildable runtime caches, including TMDB metadata and detailed
watch-history aggregates, live outside the vault in each device's local
Obsidian app storage. They are not uploaded to Obsidian Sync, and each
device can rebuild them from Trakt/TMDB if cleared. A small synced
full-refresh coordinator keeps devices from writing detailed history from
an older local cache after another device has detected Trakt-side
deletions.
**Any individual setting can opt out of cross-device sync** via a small cloud icon next to it (currently exposed for `Sync on startup` / `Auto-sync` / `Auto-sync interval` / `Daily Notes auto-sync` / `Daily Notes auto-sync interval` / `Plugin UI language`). Useful when, e.g., you want media-note sync every few hours on Mac, Daily Notes every 15 minutes on Mac, and no automatic timers on iPhone.
## ๐ View your library in Obsidian Bases
The `trakt_poster_url` frontmatter field works out-of-the-box with [Obsidian Bases](https://help.obsidian.md/bases) (Obsidian 1.9.3+). Build a database view of your sync folder and display posters as thumbnails:
- **Card view**: open Display settings โ set **Image property** to `trakt_poster_url`
- **Table view** (1.9.4+): add a formula column with `image(note.trakt_poster_url)`
Filter by `trakt_type = "movie"` / `"show"`, sort by `trakt_year` / `trakt_rating` / `trakt_my_rating`, group by `trakt_genres`. The same frontmatter properties that power Dataview queries also power Bases views โ no extra setup.
## ๐ Quick start
1. Settings โ Community plugins โ **Browse** โ search for **Sync Trakt** โ **Install** โ **Enable**
2. Settings โ **Sync Trakt** โ fill your Trakt + TMDB API keys ([SETUP guide](docs/SETUP.md))
3. Command palette โ **Sync Trakt: Sync**
## ๐ API keys: what each one unlocks
The plugin uses two APIs. **Trakt is mandatory** โ without it, the plugin can't sync anything. **TMDB is optional** but unlocks most of what makes the plugin worth installing. Here's the breakdown:
| Feature | Trakt API
_(required)_ | TMDB API
_(recommended)_ |
|---|:---:|:---:|
| Sync your Trakt library (watchlist, watched, favorites, ratings) | โ
| โ |
| Per-episode watch timestamps | โ
| โ |
| Title / overview / tagline in your language | โ
basic | โ
higher quality |
| **Genres in your language** | โ | โ
|
| **Poster images embedded in notes** | โ | โ
|
If you only want English content and no posters, you can leave TMDB blank โ Trakt alone is enough. If you want any non-English localization beyond title/overview/tagline, **add a TMDB key** ([free signup](https://www.themoviedb.org/settings/api)). After pasting your key, click the **Test** button next to the field to confirm it works before your first sync.
โ [Full walkthrough for both keys](docs/SETUP.md)
## ๐ฆ Install
Obsidian Community Plugins (recommended)
1. Settings โ Community plugins โ **Browse**
2. Search for **Sync Trakt**
3. Click **Install** โ **Enable**
Directory page: https://community.obsidian.md/plugins/sync-trakt
Development (build from source)
```bash
git clone https://github.com/o1xhack/obsidian-sync-trakt.git
cd obsidian-sync-trakt
npm install
npm run build # produces main.js
npm run lint
npm run test:i18n # smoke tests
```
Then copy `main.js`, `manifest.json`, `styles.css` to `/.obsidian/plugins/sync-trakt/`.
Local test (manual install)
1. Download `main.js`, `manifest.json`, `styles.css` from the [latest release](https://github.com/o1xhack/obsidian-sync-trakt/releases/latest)
2. Place all three files in `/.obsidian/plugins/sync-trakt/`
3. Settings โ Community plugins โ enable **Sync Trakt**
## ๐ Documentation
| Doc | Purpose |
|---|---|
| [SETUP](docs/SETUP.md) | Trakt + TMDB API key creation, first-time configuration, troubleshooting |
| [MANUAL](docs/MANUAL.md) | Full settings reference, frontmatter fields, template variables, sync behavior |
| [DEVELOPER](docs/DEVELOPER.md) | Architecture overview, data flow, how to extend (English only) |
| [docs/i18n/](docs/i18n/) | Translations of README / SETUP / MANUAL into 8 additional languages |
## ๐บ๏ธ Roadmap
Major versions since the fork (chronological):
- [x] **0.1** โ Initial fork. Detailed watch history with per-episode timestamps, metadata localization via TMDB + Trakt fallback chain, bilingual UI (en + zh-CN), translated note templates (en + zh-CN + zh-TW), distinct plugin id from upstream so both can coexist.
- [x] **0.2** โ Incremental sync. Persistent TMDB cache (stale-while-revalidate, 90-day TTL with jitter) + Trakt history-state cursor. Steady-state sync drops from minutes to single-digit seconds. โ [spec 0001](docs/specs/0001-incremental-sync.md)
- [x] **0.3** โ Diff-based writes. Only rewrite notes whose frontmatter or managed body section actually changed; cross-device sync layers stop shuffling 1200 files per sync. 0.3.x also added: TMDB API key Test button + warning banner when metadata language is set without a key, and two-tier filename disambiguation for localized-title collisions (e.g. 5 shows all called "้็" no longer fight for the same filename). โ [spec 0002](docs/specs/0002-diff-based-write.md)
- [x] **0.4** โ Directory submission preparation. Plugin id renamed `obsidian-sync-trakt` โ `sync-trakt` (Obsidian directory bot rejects ids containing "obsidian"), `minAppVersion` tightened to 1.6.6, and transparent automatic data migration from the legacy folder on first launch. โ [spec 0004](docs/specs/0004-obsidian-directory-submission.md)
- [x] **0.5** โ Device-local settings + automatic cleanup. Per-setting cloud-icon toggle so each setting can opt out of cross-device sync; auto-cleanup of the legacy folder's binary files (keeping data.json as a safety net) so users don't see two duplicate plugin entries in their settings. โ [spec 0003](docs/specs/0003-device-local-settings.md)
- [x] **0.6** โ Tabbed settings UI + 11 bundled note template languages. Settings page reorganized into 4 tabs (General / Notes / Sync / Daily Notes). Note templates expanded from 3 to 11 hand-curated languages (+ ja, ko, fr, de, it, es, pt-BR, ru). Template-language dropdown filtered to only show bundled languages. โ [spec 0005](docs/specs/0005-settings-ui-tabs.md) + [spec 0007](docs/specs/0007-template-language-expansion.md)
- [x] **0.7** โ Daily Notes integration. Auto-inserts per-event lines (watched / watchlist / favorited / rated) into your Daily Note for every sync, chronologically sorted, in your chosen template language. Add-only safety for past days; today is overwritten as the day progresses. โ [spec 0006](docs/specs/0006-daily-notes-integration.md)
- [x] **0.8** โ Daily Notes **incremental sync mode**. Opt-in mode where today's marker region is append-only (instead of full-replace), so any annotations you write inside survive every sync. โ [spec 0008](docs/specs/0008-metadata-language-fallback.md) intro discusses the trade-off; the actual mode lives in spec 0006.
- [x] **0.9** โ **Metadata language fallback**. Adds a "fallback language" dropdown under Metadata language. When set, the primary becomes a strict match (no silent zh-TW substitution for zh-CN) and falls through to the user-chosen fallback before keeping the English original. โ [spec 0008](docs/specs/0008-metadata-language-fallback.md)
- [x] **1.0** โ **Filename auto-rename + persistent What's-new modal + date-range backfill**. Changing metadata language now auto-renames existing notes on the next sync (Obsidian internal links auto-update). Every new release pops a one-shot "What's new" modal showing version history since last seen. Manual backfill replaced with a date-range picker (start/end + quick presets). โ [spec 0009](docs/specs/0009-filename-rename.md)
- [x] **1.1** โ **Vault-slim runtime cache architecture**. Large TMDB and detailed-history caches moved outside the vault, keeping `data.json` small for Obsidian Sync while preserving multi-device rebuild behavior. โ [spec 0010](docs/specs/0010-local-runtime-cache.md)
- [x] **1.2** โ **Daily Notes-only auto-sync**. Daily Notes can refresh on their own interval without media-note writes, sharing the same Trakt/TMDB data path and sync lock as full sync. โ [spec 0011](docs/specs/0011-daily-notes-auto-sync.md)
- [ ] **Future** โ More plugin UI translations (currently en + zh-CN) on demand; additional bundled template languages on request.
## ๐ค Acknowledgements
This plugin was originally inspired by [sarimabbas/traktr](https://github.com/sarimabbas/traktr) (MIT licensed), which provided the initial Trakt OAuth scaffolding. Substantial subsequent work โ detailed watch-history aggregation, metadata localization with translation-fallback chains, bilingual UI, bounded-concurrency fetching with live progress reporting, machine-managed body sections, the translation-aware template renderer, multi-language docs โ has reshaped most of the codebase into a fundamentally different architecture.
Thanks to [Sarim Abbas](https://github.com/sarimabbas) for the starting point. The original work's MIT copyright notice is preserved verbatim in [LICENSE](LICENSE) alongside this project's own.
## ๐ License
MIT โ see [LICENSE](LICENSE).
---
Author: [o1xhack](https://github.com/o1xhack)