AJ88 downloadsTrack a wine cellar by note, vintage, lot and drinking window, with dashboard, monthly and sidebar views.
Track a physical wine cellar inside Obsidian — by note, vintage, lot and drinking window.
Every bottle you own lives in a normal Markdown note. The plugin reads and writes those notes, so your cellar stays yours: no database, no account, no network requests. Uninstall the plugin and the data is still there, readable, in plain text.
Requires Obsidian 1.2.8 or later. Works on desktop and mobile.
Settings → Community plugins → Browse → search for Wine Tracker → Install → Enable.
Download main.js, manifest.json and styles.css from the latest release and drop them into VaultFolder/.obsidian/plugins/wine-tracker/, then reload Obsidian and enable the plugin.
Wine/Wines) and, if you want tasting or spending logs, Daily notes folder.| Command | Description |
|---|---|
| Add bottle | Add a new purchase lot to inventory |
| Add lot to existing wine | Restock a wine you already have, with its details prefilled |
| Open sidebar | Reveal the Wine Tracker sidebar |
| Consume bottle | Drink a bottle and log a tasting note |
| Edit lot | Update any field on an existing lot |
| Log tasting | Log a tasting without consuming from inventory |
| Refresh prices/windows | Update current prices and infer missing drinking windows |
| Open dashboard | Open the dashboard note |
| Rebuild index | Re-scan all wine notes and rebuild the in-memory cache |
Opens a modal. Required: producer, cuvée, varietal, and either a vintage or the Non-vintage (NV) toggle.
Tick Non-vintage (NV) for NV Champagne and multi-year blends. The vintage is stored as NV and window inference is skipped, since there's no year to anchor a window to — set a window by hand if you want one.
Optional fields: qty (defaults to 1), purchase date, purchase price, shelf location, drinking window (start/end years), phased drinking windows, region, country, style, bottle size, source/merchant, current price, gift toggle, notes, rebuy toggle, do-not-buy-again toggle.
Already own the wine? Use Add lot to existing wine instead, or the Add lot button on the wine note's card — both open this same form with producer, cuvée, varietal, region, country and style already filled, so a restock only needs vintage, quantity and price.
What happens on save:
{wine notes folder}/{{producer}} - {{cuvee}} ({{grape}}).md if it doesn't existwine_id, producer, cuvee, grape, region, country, style, rebuy, do_not_buy_again)wine-inventory block (or creates the vintage entry)Phased drinking windows — enter one line per phase in the Window phases field:
3,2027,2031
3,2032,2036
Each line is qty,start,end. Use qty,before YYYY for a "drink before" style window.
If no window is entered and the varietal/style is recognised, a window is inferred automatically.
Three-step modal:
On confirm:
- [ ] #log/wine/tasting-note [[St Hallett - Blockhead (Shiraz)]] 2021 4/5 %%wine-lot:2021-a%%
- Plush fruit, ready now.
The link points at the wine note itself. A tasting logged for a wine you don't own (see Log tasting) is written as plain text rather than a link that would resolve to nothing.
Three-step modal: choose wine → choose lot → edit form.
Editable fields: qty, purchase date, purchase price, current price, shelf, source, bottle size, drinking windows (same qty,start,end format as Add bottle), notes, gift toggle.
Writes back to the wine note and rebuilds the cache.
Quick-log without consuming from inventory. A dropdown pre-fills wine, vintage, and lot ID from cached stock. Manual text fields are available for wines not in inventory (e.g. tasting at a restaurant).
Writes the same tasting stub format to today's daily note as Consume bottle.
Updates current prices and fills in missing drinking windows for a single wine note. Everything is computed locally — the plugin never contacts a price service.
If a wine note is open when you run the command, it opens directly on that note. Otherwise it shows a searchable picker.
The proposals screen shows every lot in the note. For each lot:
Current price field — shows the current_price already in the note, or blank. The purchase price is shown alongside for reference.
There is no price estimator. An earlier version compounded the purchase price by 3–7%/yr from grape and style alone and wrote the result into current_price, which invented valuations that kept appreciating on wines already past their drinking window. current_price is now only ever what you typed. Leave it blank and the cellar is valued at what you paid.
Proposed window — if the lot has no drinking window defined, an inferred window is shown (using the same heuristic as Add bottle). This is added on save; existing windows are never overwritten.
Nothing is written to the note until you hit Save.
Dashboard — sections for:
Monthly block — add a wine-plugin-monthly code block to any monthly note. The reference year is read from the note's filename using your Monthly note date format, so viewing a past month shows the status as it would have been then. Drinking windows are year-granular, so the block is scoped to the note's year rather than its month.
Sidebar — shows Drink now and Overdue in the right panel.
All views have a text search (wine name, producer, region, country, style, varietal, shelf) and a status dropdown filter. Views repaint automatically when a wine note changes, so consuming or editing a bottle updates them in place.
| Status | Condition |
|---|---|
| Cellaring | Reference year is before window start |
| Drink now | Reference year is inside the window |
| Overdue | Reference year is past window end |
| Unknown window | No window defined — shown as drinkable but filterable |
Phased windows split a lot's quantity across multiple statuses. Example: a lot of 6 with phases 3 × 2027–2031 and 3 × 2032–2036 shows as "Drink now: 3, Cellaring: 3" in 2028.
When a purchase price is entered in Add bottle, an entry is written under your finance heading in today's daily note:
## Finance
- [ ] #log/spending 84
- $84.00 USD #log/spending/alcohol/wine
- 3 x [[St Hallett - Blockhead (Shiraz)]] 2021
- Langtons
The #log/spending total on the root line is updated automatically. Finance logging only fires when a purchase price is present. If you don't want it, leave the purchase price blank.
| Setting | Default | Notes |
|---|---|---|
| Dashboard note path | Wine/Wine Dashboard.md |
Created automatically on first open |
| Wine notes folder | Wine/Wines |
All wine notes must live here |
| Flat inventory note path | Wine/Wine Inventory (flat).md |
Auto-generated Markdown table, one row per lot with stock. For reading and search — Dataview and Bases query note properties, not Markdown tables, so point those at the wine notes folder |
| Open sidebar on startup | on | Reopen the sidebar each time the vault loads |
| Daily notes folder | (empty) | Supports {{date:FORMAT}} placeholders |
| Daily note date format | YYYY-MM-DD |
Moment.js format for the daily note filename |
| Monthly notes folder | (empty) | Used by the monthly view |
| Monthly note date format | YYYY-MM |
Moment.js format for the monthly note filename |
| Tasting log marker | #log/review/daily-review |
Tasting notes are nested under the first line containing this text |
| Copy tastings to the wine note | on | Also append each tasting under the wine note's ## Tasting heading |
| Write rollup properties | on | Keep cellar_* properties current in each wine note, for Bases and Dataview |
| Infer journal settings | on | Read daily/monthly folders from the Journals plugin |
| Currency | USD |
ISO code used to format prices |
| Finance heading | ## Finance |
Must match the heading in your daily note |
| Finance category path | alcohol/wine |
Tag path appended after #log/spending/ |
| Infer finance settings | on | Read the spending heading and currency from the Finance Tracker plugin |
Journal and finance settings are inferred on load from the Journals and Finance Tracker plugins if you have them installed. Turn the toggles off to manage the values yourself.
A wine note carries a wine-plugin-card block just under its title. It renders a live summary of that one wine — bottles in stock, lots, value at cost, and a row per lot with its vintage, shelf, price and a coloured chip per drinking-window phase — plus buttons for Consume, Add lot, Log tasting and Prices & windows.
# St Hallett Blockhead
```wine-plugin-card
```
## Inventory
```wine-inventory
...
```
## Tasting
- 2026-08-14 · 2021 · 4/5 · lot 2021-a — Plush fruit, ready now.
The card is added to new notes automatically, and to older ones the next time the plugin writes to them. Nothing is stored in it — delete the block if you don't want it, and the note still works.
Tastings are appended under ## Tasting as well as to your daily note, so each bottle carries its own drinking record rather than having it scattered across daily notes. Turn that off with Copy tastings to the wine note.
Both query note properties, so each wine note carries computed rollups, refreshed whenever the index rebuilds:
| Property | Meaning |
|---|---|
cellar_bottles |
Bottles currently in stock across all lots |
cellar_lots |
Lots with stock remaining |
cellar_status |
Most urgent status across stock: overdue, drink-now, unknown, cellaring, or empty |
cellar_value |
Stock valued at current_price, falling back to what you paid |
cellar_vintages |
Vintages currently in stock |
cellar_ready_from |
Year the wine becomes drinkable — the current year if it already is |
Point a Base at your wine notes folder and these are all available as columns and filters. They are only written when a value actually changes, so they don't churn your files. Turn them off with Write rollup properties.
The flat inventory note is a plain Markdown table for reading and search — neither Bases nor Dataview can query a Markdown table, so use the properties above for that.
Inventory lives in a wine-inventory fenced block inside each wine note:
```wine-inventory
- vintage: 2021
lots:
- lot_id: 2021-a
qty: 6
purchase_date: 2025-03-10
unit_price: 28
current_price: 32
shelf: A1
source: Langtons
gift: false
notes: ""
bottle_size: ""
windows:
- qty: 3
start: 2027
end: 2031
- qty: 3
start: 2032
end: 2036
```
Markdown is the only source of truth. The plugin cache is derived from the notes at runtime and can be rebuilt at any time with the Rebuild index command.
Wine Tracker makes no network requests. All prices, drinking windows and statistics are computed locally from your own notes.
node --check main.js
node --test tests/*.test.js
The plugin is a single self-contained main.js with no bundler or local imports — all logic lives there.
Tests require main.js directly, redirecting the obsidian import to tests/obsidian-stub.js so it loads in bare Node. The pure helpers are re-exported on module.exports.__internals purely for this; Obsidian only reads the default export. Tests therefore exercise the shipping code rather than a copy.
Issues and pull requests welcome at github.com/arangutambo/wine-tracker.
MIT — see LICENSE.
If you find it useful, you can buy me a coffee.