Initial commit: Waypoint Obsidian plugin with calendar, recent files, and bookmarks

This commit is contained in:
2026-06-03 20:26:23 -04:00
commit fbdc42b4a3
16 changed files with 3400 additions and 0 deletions
+329
View File
@@ -0,0 +1,329 @@
# Waypoint Plugin — Implementation Plan
## Overview
A sidebar plugin for Obsidian that combines three panels into one coherent view: a **periodic note calendar** (day/week/month/quarter/year), a **recent files list**, and a **custom favorites/bookmarks system** with rename, icons, and grouping.
---
## Features (from requirements)
1. **Calendar panel** — shows a month grid with every day clickable
2. **Period indicators** — day, week, month, quarter, year all displayed and clickable
3. **Note creation on click** — clicking a period creates a note at a configurable path with a configurable template
4. **Recent files** — list of recently opened/edited files
5. **Favorites/Bookmarks** — custom bookmarks (distinct from Obsidian native bookmarks) with:
- Command: "Add current file as Waypoint bookmark"
- Rename without renaming the underlying file
- Assign an icon (from Lucide icons)
- Right-click context menu: rename, change icon, remove, move
- Foldable groups and indented hierarchy
6. **Settings** — configure folder paths and templates for each period type
---
## Architecture
### Approach
- **Plain ItemView** (not React) — simpler, matches recent-files-obsidian's approach, avoids extra dependencies
- **Single view type** `waypoint-view` that contains all three panels stacked vertically
- **Plugin data** stored via `Plugin.loadData()` / `Plugin.saveData()` for bookmarks and recent files
- **Settings** via `PluginSettingTab`
### Why not React?
The daily-note-calendar plugin uses React, but that adds complexity (esbuild config for JSX, react-dom dependency). The recent-files plugin does everything with plain Obsidian DOM helpers (`createDiv`, `setIcon`, etc.) and is much simpler. We can build a clean, native-feeling UI without React. If the calendar grid becomes complex, we can reconsider.
### File Structure
```
waypoint/
├── manifest.json
├── package.json
├── tsconfig.json
├── esbuild.config.mjs
├── styles.css
├── src/
│ ├── main.ts # Plugin entry point
│ ├── settings.ts # Settings interface + defaults + SettingTab
│ ├── views/
│ │ ├── waypoint-view.ts # Main ItemView (orchestrates panels)
│ │ ├── calendar-panel.ts # Calendar month grid + period indicators
│ │ ├── recent-files-panel.ts # Recent files list
│ │ └── favorites-panel.ts # Favorites/bookmarks tree
│ ├── models/
│ │ └── bookmark.ts # Bookmark item/group interfaces
│ ├── services/
│ │ ├── calendar-service.ts # Date math, period detection, note creation
│ │ ├── recent-files-service.ts # Track and filter recent files
│ │ └── favorites-service.ts # CRUD for custom bookmarks
│ └── utils/
│ ├── date-utils.ts # Date formatting, period navigation
│ └── icon-utils.ts # Icon picker modal
└── README.md
```
---
## Component Details
### 1. Calendar Panel (`calendar-panel.ts`)
**Visual layout (top to bottom):**
```
┌─────────────────────────────────────┐
│ Q3 · June · 1st, 2026 │ ← Breadcrumb: quarter, month, day (all clickable)
├─────────────────────────────────────┤
│ ◀ June 2026 ▶ │ ← Month+Year header with nav
├─────────────────────────────────────┤
│ Mon Tue Wed Thu Fri Sat Sun │ ← Day-of-week headers
├─────────────────────────────────────┤
│ W22 1 2 3 4 5 6 │ ← Week rows (week number + 7 days)
│ W23 7 8 9 10 11 12 13 │
│ W24 14 15 16 17 18 19 20 │
│ W25 21 22 23 24 25 26 27 │
│ W26 28 29 30 │
├─────────────────────────────────────┤
│ ◀ [Today] ▶ │ ← Today navigation
└─────────────────────────────────────┘
```
**Behavior:**
- **Click a day cell** → open or create the daily note for that date
- **Click week number** → open/create the weekly note
- **Click breadcrumb quarter** → open/create the quarterly note
- **Click breadcrumb month** → open/create the monthly note
- **Click breadcrumb day** → open/create the daily note
- **Left/right arrows on month header** → navigate months
- **"Today" button** → jump to current month
- **Dot indicator** → show which days already have notes
- **Today highlight** → accent-colored border on current day
- **Week numbers** displayed as the first column, using ISO week numbering (weeks start on Monday)
**Note creation logic:**
1. Check if a note exists at `{folder}/{nameTemplate}` using the date
2. If it exists, open it
3. If not, create it using the configured template file (via Obsidian API)
4. Apply the `type` property matching the period type (daily-note, weekly-note, etc.)
### 2. Recent Files Panel (`recent-files-panel.ts`)
Based closely on the recent-files-obsidian plugin:
- Track file opens/edits via `app.workspace.on('file-open')`
- Store as ordered list of `{ path, basename }`
- Display in a `nav-folder` styled list (matches Obsidian's file explorer look)
- Each item shows:
- File name (supporting frontmatter-title plugin if available)
- Hover preview via `hover-link` event
- Drag support (wikilink insertion)
- Right-click: "Open in new tab" + Obsidian file menu
- Middle-click / Ctrl+click: open in new pane
- X button on hover to remove from list
- Respect omitted paths/tags filter (from settings)
- Max length configurable
### 3. Favorites / Bookmarks Panel (`favorites-panel.ts`)
**Data model:**
```typescript
interface BookmarkItem {
id: string; // unique ID
type: 'file' | 'group';
label: string; // display name (can differ from file name)
filePath: string; // path to the Obsidian file (empty for groups)
icon: string; // Lucide icon name (default: 'file')
children: BookmarkItem[]; // for groups
collapsed: boolean; // group fold state
indent: number; // indent level (0 = top level)
}
```
**Visual layout:**
```
── Waypoint Bookmarks ────
📁 Projects ← group (collapsible)
📄 Fabrique ← file bookmark
📄 Haro dashboard ← file bookmark
📁 References ← group
📄 CSS grid notes
📄 Inbox ← ungrouped bookmark
```
**Behavior:**
- **Click file bookmark** → opens the file
- **Click group** → toggles collapse/expand
- **Drag to reorder** (stretch goal — use Obsidian's drag system)
- **Right-click on file bookmark** → context menu:
- Rename bookmark
- Change icon (opens icon picker)
- Remove bookmark
- Move to group → submenu of existing groups
- **Right-click on group** → context menu:
- Rename group
- Change icon
- Remove group (and all children)
- Add bookmark to this group
- New sub-group
- **Right-click on empty space** → context menu:
- New group
- Add current file
**Add current file command:**
- Command ID: `waypoint:add-bookmark`
- Picks up the active file
- Shows a prompt to set the display name (defaults to file's basename)
- Shows an icon picker (default: file icon)
- Adds to root level (or active group if one is right-clicked)
### 4. Settings Tab (`settings.ts`)
```
┌── Waypoint Settings ──────────────────┐
│ │
│ 📅 Calendar │
│ ┌─ General ─────────────────────────┐ │
│ │ First day of week [Monday ▼] │ │
│ │ Week number standard [ISO ▼] │ │
│ │ Show note indicators [toggle] │ │
│ └──────────────────────────────────┘ │
│ │
│ ┌─ Periodic Note Paths ─────────────┐ │
│ │ Daily note │ │
│ │ Folder: [periodic/daily ] │ │
│ │ Template: [templates/daily ] │ │
│ │ Name: [yyyy-MM-dd ] │ │
│ │ Type: [daily-note ] │ │
│ │ │ │
│ │ Weekly note │ │
│ │ Folder: [periodic/weekly ] │ │
│ │ Template: [templates/weekly ] │ │
│ │ Name: [GGGG-[W]WW ] │ │
│ │ Type: [weekly-note ] │ │
│ │ │ │
│ │ Monthly note │ │
│ │ Folder: [periodic/monthly ] │ │
│ │ ... │ │
│ │ │ │
│ │ Quarterly note │ │
│ │ ... │ │
│ │ │ │
│ │ Yearly note │ │
│ │ ... │ │
│ └──────────────────────────────────┘ │
│ │
│ 📄 Recent Files │
│ ┌──────────────────────────────────┐ │
│ │ Max items: [50 ] │ │
│ │ Update on: [File opened ▼] │ │
│ │ Omitted paths: [textarea ] │ │
│ │ Omitted tags: [textarea ] │ │
│ └──────────────────────────────────┘ │
│ │
│ ⭐ Favorites │
│ ┌──────────────────────────────────┐ │
│ │ (No specific settings yet) │ │
│ └──────────────────────────────────┘ │
└────────────────────────────────────────┘
```
---
## Implementation Steps
### Step 1: Project scaffolding
- Create `manifest.json`, `package.json`, `tsconfig.json`, `esbuild.config.mjs`
- Install deps: `obsidian`, `builtin-modules`, typescript
- Create folder structure
### Step 2: Settings
- Define interfaces: `WaypointSettings`, `PeriodNoteSettings`
- Defaults matching O-vault convention:
- Daily: `periodic/daily/`, template `Templates/Daily note`, name `yyyy-MM-dd`
- Weekly: `periodic/weekly/`, template `Templates/Weekly note`, name `GGGG-[W]WW`
- Monthly: `periodic/monthly/`, template `Templates/Monthly note`, name `yyyy-MM`
- Quarterly: `periodic/quarterly/`, template `Templates/Quarterly note`, name `yyyy-[Q]Q`
- Yearly: `periodic/yearly/`, template `Templates/Yearly note`, name `yyyy`
- Implement `WaypointSettingTab` with sections for each period + recent files
### Step 3: Calendar Service
- `getMonthGrid(year, month, firstDayOfWeek)` → array of weeks with day objects
- `getPeriodFromDate(date)` → { day, week, month, quarter, year }
- `findOrCreateNote(period, settings)` → checks vault, creates if missing
- Date formatting using `moment()` (bundled in Obsidian)
### Step 4: Calendar Panel (ItemView section)
- Render the calendar grid using Obsidian DOM (`createDiv`, `createSpan`)
- Period header row (year/quarter/week)
- Month header with nav arrows
- Day-of-week header row
- Day cells (with today highlight, note indicators, other-month dimming)
- Arrow navigation for months
- Click handlers for each period type
### Step 5: Recent Files Service
- Track `file-open` events
- Maintain ordered list (max length, dedup)
- Support omitted paths/tags filtering
### Step 6: Recent Files Panel
- Render the list in `nav-folder` style
- Click, hover, drag, right-click, middle-click, delete button
### Step 7: Favorites Service
- CRUD operations on `BookmarkItem[]`
- Persist via `Plugin.loadData/saveData`
- Add current file command
- Rename, icon change, remove, grouping
### Step 8: Favorites Panel
- Render tree with collapsible groups
- Context menus for items and groups
- Icon display using `setIcon()`
- Drag support (stretch)
### Step 9: Waypoint View (main orchestrator)
- `ItemView` subclass
- On open: create three sections inside `contentEl`
- Redraw on data changes
- Register as sidebar view type `waypoint-view`
### Step 10: Main Plugin
- `onload()`: load data, register view, register commands, register events, add settings tab
- Auto-open on right sidebar on first load
- Commands:
- `waypoint:open-view` → reveal the waypoint sidebar
- `waypoint:add-bookmark` → add current file as bookmark
- `waypoint:go-to-today` → open today's daily note
- Events:
- `file-open` → update recent files + redraw
- `create`, `delete`, `rename` → update calendar note indicators + redraw
- Midnight check → refresh today highlight
---
## Key Design Decisions
1. **No React** — Using native Obsidian DOM APIs avoids build complexity and keeps the bundle small. The calendar grid is straightforward enough to render imperatively.
2. **Flat data storage** — Bookmarks and recent files stored via Plugin.loadData/saveData as JSON. This makes them portable and compatible with Obsidian sync.
3. **Separate from native bookmarks** — We never touch `app.internalPlugins.getEnabledPluginById('bookmarks')`. These are entirely custom bookmarks with their own data store.
4. **Icon picker** — We'll build a simple icon picker modal using Obsidian's `SuggestModal` or a grid of Lucide icons that are commonly used (file, folder, star, heart, bookmark, flag, pin, etc.). We won't implement a searchable full icon browser initially — a curated selection of ~40 icons plus a text input for any Lucide icon name.
5. **O-vault aware** — Default paths match Olivier's vault structure. All settings are overridable.
---
## Stretch Goals (after MVP)
- Drag-and-drop reordering in favorites panel
- Search/filter within bookmarks
- Multiple bookmark lists / profiles
- Sync bookmarks with Obsidian Sync
- Show note previews on calendar hover
- Custom CSS classes per bookmark (color coding)
- Nested groups beyond 2 levels
- Collapse/expand all in favorites
- Keyboard shortcuts for bookmark navigation