# Nocal product and interaction specification Nocal is a local-first, keyboard-driven month calendar for Linux terminals. Its visual target is the information density of a desktop month view without pretending that a terminal is a pixel canvas. The terminal emulator owns the typeface and palette; Nocal owns hierarchy, spacing, and restrained emphasis. ## Product principles 1. **The month is the home screen.** Launching Nocal immediately shows six complete Monday-first weeks. There is no dashboard or splash screen. 2. **Useful at a glance.** Every visible day shows as many appointments as fit, ordered as all-day first and then by start time. A final `+N more` line is used instead of clipping silently. 3. **Keyboard-native.** Arrow keys and Vim keys move by day or week; month and today jumps are single keystrokes. Every action remains discoverable in the footer and help overlay. 4. **Terminal-native aesthetics.** Nocal uses default foreground/background and the terminal's ANSI semantic colors. It never paints a fixed RGB theme over the user's Kitty, foot, Alacritty, or WezTerm theme. 5. **Local-first, sync-ready.** The canonical domain model is independent of iCalendar files and of any future remote API. Sync engines translate into domain objects and never leak provider-specific types into the UI. 6. **Fast enough to feel instant.** Startup should remain below 50 ms for a normal local calendar and redraw should be flicker-free at interactive resize rates. ## Month view The full terminal is treated as a responsive canvas: ```text JULY 2026 Today Fri 17 Jul Mon Tue Wed Thu Fri Sat Sun ┌────────────┬────────────┬────────────┬────────────┬────────────┬────────────┬────────────┐ │ 29 │ 30 │ 1 │ 2 │ 3 │ 4 │ 5 │ │ │ │ 09:30 Team │ │ All day … │ │ │ ├────────────┼────────────┼────────────┼────────────┼────────────┼────────────┼────────────┤ │ … │ └─────────────────────────────────────────────────────────────────────────────────────────┘ ←↓↑→ move PgUp/PgDn month t today ? help q quit 2 appointments ``` - At 100 columns and above, Nocal draws the full bordered grid. - Narrow cells abbreviate times and ellipsize summaries by display width. - When height is constrained, appointment lines are reduced before structural chrome. At extremely small sizes a clear minimum-size message replaces a broken grid. - Days outside the focused month remain visible but dim. - The selected date is reverse-video, today is bold/underlined, and collisions use semantic ANSI accents. These attributes work on monochrome terminals. - The footer reports the selected day's appointment count and the most useful keys for the available width. ## Interaction map | Action | Keys | | --- | --- | | Previous/next day | `Left` / `Right`, `h` / `l` | | Previous/next week | `Up` / `Down`, `k` / `j` | | Previous/next month | `PageUp` / `PageDown`, `p` / `n` | | Jump to today | `t` | | Next/previous appointment | `Tab` / `Shift-Tab` | | Read focused appointment | `Enter` | | Browse inside reader | arrows, `h j k l`, `Tab` / `Shift-Tab` | | Add appointment | `a` | | Edit focused appointment | `e` | | Delete focused appointment | `d`, then `y` to confirm | | Undo/redo successful mutation | `u` / `Ctrl-R` | | Move between editor fields | `Tab` / `Shift-Tab`, arrows | | Save/cancel editor | `Ctrl-S` / `Esc` | | Return to month/unfocus | `Esc` | | Search appointments | `/`, then type and press `Enter` | | Choose search result | arrows, `j` / `k`, then `Enter` | | Toggle calendar visibility | `c`, arrows or `j` / `k`, then `Enter` | | Help | `?` | | Quit | `q` | The first usable foundation supports day and appointment navigation, a full-frame reader, validated add/edit/delete forms, and atomic `.ics` writes. Dense days keep every appointment keyboard-reachable even when all lines do not fit in the cell. Unknown or unsupported iCalendar content makes a source read-only instead of being discarded. Saves reject external changes, retain a last-known-good backup, and feed bounded session undo/redo history. Supported recurring instances appear throughout the month, preserve civil time across daylight-saving changes, and expose their source zone and whole-series mutation semantics in the reader. `/` searches occurrence-aware title, description, location, and calendar-ID matches in a finite ten-year window centered on the selected date. `c` toggles session-only calendar visibility consistently across the grid, appointment focus, and search without filtering the model supplied to persistence. The next local-data work adds an agenda view, then advanced recurrence overrides and rule editing. ## Accessibility - Information is never encoded by color alone. - `NO_COLOR` and terminals without color remain fully usable. - Borders and icons have ASCII fallbacks; Unicode width is calculated rather than assumed. - Focus is always visible and keyboard operation is complete. - Motion is limited to direct redraws; there are no decorative animations.