cli + tui to publish to leaflet (wip) & manage tasks, notes & watch/read lists 🍃
charm leaflet readability golang
29

Configure Feed

Select the types of activity you want to include in your feed.

docs: add tui & reference pages

* update favicon

* update styling of site to use application palette

+438 -77
-34
website/TODO.md
··· 2 2 3 3 This document tracks documentation coverage for the Noteleaf website. The goal is to provide comprehensive documentation for both the productivity system features and the leaflet.pub publishing capabilities. 4 4 5 - ## TUI (Terminal UI) 6 - 7 - - [ ] Interactive Mode 8 - - [ ] Navigation 9 - - [ ] Keyboard shortcuts 10 - - [ ] Selection and actions 11 - - [ ] Help screens 12 - - [ ] Static Mode 13 - - [ ] Command-line output 14 - - [ ] Scripting with Noteleaf 15 - - [ ] Output formatting 16 - - [ ] JSON output 17 - 18 5 ## Integration and Workflows 19 6 20 7 - [ ] External Integrations ··· 31 18 - [ ] Exporting data 32 19 - [ ] Backup and restore 33 20 - [ ] Migration from other tools 34 - 35 - ## CLI Reference 36 - 37 - - [ ] Command Structure 38 - - [ ] Global flags 39 - - [ ] Command hierarchy 40 - - [ ] Help system 41 - - [ ] Commands by Category 42 - - [ ] `task` commands 43 - - [ ] `note` commands 44 - - [ ] `media` commands (book, movie, tv) 45 - - [ ] `article` commands 46 - - [ ] `pub` commands (leaflet publishing) 47 - - [ ] `config` commands 48 - - [ ] `setup` commands 49 - - [ ] `status` commands 50 - - [ ] Development Tools 51 - - [ ] `tools` subcommand 52 - - [ ] Documentation generation 53 - - [ ] Lexicon fetching 54 - - [ ] Database utilities 55 21 56 22 ## Development 57 23
+18 -9
website/docusaurus.config.ts
··· 12 12 label: "Concepts", 13 13 items: [{ type: "autogenerated", dirName: "concepts" }], 14 14 }, 15 + { type: "doc", id: "configuration" }, 15 16 { 16 17 type: "category", 17 18 label: "Tasks", ··· 24 25 }, 25 26 { 26 27 type: "category", 28 + label: "Leaflet.pub", 29 + items: [{ type: "autogenerated", dirName: "leaflet" }], 30 + }, 31 + { 32 + type: "category", 27 33 label: "Media", 28 34 items: [{ type: "autogenerated", dirName: "media" }], 29 35 }, ··· 32 38 label: "Articles", 33 39 items: [{ type: "autogenerated", dirName: "articles" }], 34 40 }, 35 - { 36 - type: "category", 37 - label: "Leaflet Publishing", 38 - items: [{ type: "autogenerated", dirName: "leaflet" }], 39 - }, 40 - { type: "doc", id: "configuration" }, 41 41 ]; 42 42 43 43 const config: Config = { 44 44 title: "Noteleaf", 45 - tagline: 46 - "Terminal-based personal information manager for tasks, notes, and media", 47 - favicon: "img/favicon.ico", 45 + tagline: "Notes, blog posts, and productivity from the terminal", 46 + favicon: "img/logo.svg", 48 47 // Improve compatibility with the upcoming Docusaurus v4 49 48 future: { v4: true }, 50 49 url: "https://stormlightlabs.github.io/", ··· 72 71 logo: { alt: "Noteleaf Logo", src: "img/logo.svg" }, 73 72 items: [ 74 73 { 74 + type: "doc", 75 + docId: "quickstart", 76 + position: "left", 77 + label: "Quickstart", 78 + }, 79 + { 75 80 type: "docSidebar", 76 81 sidebarId: "manualSidebar", 77 82 position: "left", ··· 89 94 { 90 95 label: "Quickstart", 91 96 to: "/docs/quickstart", 97 + }, 98 + { 99 + label: "Manual", 100 + to: "/docs/concepts/overview", 92 101 }, 93 102 ], 94 103 },
+119
website/docs/concepts/cli-reference.md
··· 1 + --- 2 + title: CLI Reference 3 + sidebar_label: CLI Reference 4 + description: Overview of Noteleaf’s command hierarchy, flags, and developer utilities. 5 + sidebar_position: 7 6 + --- 7 + 8 + # CLI Reference 9 + 10 + This reference is a map of the top-level commands exposed by `noteleaf`. For flag-by-flag detail run `noteleaf <command> --help`—the human-friendly Fang help screens are always the source of truth. 11 + 12 + ## Command Structure 13 + 14 + ### Global flags 15 + 16 + | Flag | Description | 17 + | ------------------------- | ----------------------------------------------------------------- | 18 + | `--help`, `-h` | Show help for any command or subcommand | 19 + | `--version` | Print the Noteleaf build string (includes git SHA when available) | 20 + | `--color <auto\|on\|off>` | Optional Fang flag to control ANSI colors | 21 + 22 + Environment variables such as `NOTELEAF_CONFIG`, `NOTELEAF_DATA_DIR`, and `EDITOR` affect how commands behave but are not flags. 23 + 24 + ### Command hierarchy 25 + 26 + - Root command: `noteleaf` 27 + - Task commands live under the `todo` alias (e.g., `noteleaf todo add`). 28 + - Media commands are grouped and require a subtype: `noteleaf media book`, `noteleaf media movie`, `noteleaf media tv`. 29 + - Publishing flows live under `noteleaf pub`. 30 + - Management helpers (`config`, `setup`, `status`, `reset`) sit at the top level. 31 + 32 + ### Help system 33 + 34 + Every command inherits Fang’s colorized help plus Noteleaf-specific additions: 35 + 36 + - `noteleaf article --help` prints the supported parser domains and storage directory by calling into the handler. 37 + - Interactive commands show the keyboard shortcuts inside their help output. 38 + - You can always drill down: `noteleaf todo add --help`, `noteleaf media book list --help`, etc. 39 + 40 + ## Commands by Category 41 + 42 + ### `todo` / `task` 43 + 44 + Add, list, view, update, complete, and annotate tasks. Supports priorities, contexts, tags, dependencies, recurrence, and JSON output for scripting. Related metadata commands (`projects`, `tags`, `contexts`) summarize usage counts. 45 + 46 + ### `note` 47 + 48 + Create Markdown notes (inline, from files, or via the interactive editor), list them with the TUI, search, view, edit in `$EDITOR`, archive/unarchive, and delete. Notes share IDs with leaflet publishing so they can be synced later. 49 + 50 + ### `media` 51 + 52 + Umbrella group for personal queues: 53 + 54 + - `noteleaf media book` — Search Open Library, add books, update status (`queued`/`reading`/`finished`), edit progress percentages, and remove titles. 55 + - `noteleaf media movie` — Search Rotten Tomatoes, queue movies, mark them watched, or remove them. 56 + - `noteleaf media tv` — Same as movies but with watching/watched states and optional season/episode tracking. 57 + 58 + Each subtype has its own `list`, status-changing verbs, and removal commands. Use `-i/--interactive` on `add` to open the TUI selector (books today, other media soon). 59 + 60 + ### `article` 61 + 62 + Parse and save web articles with `add <url>`, inspect them via `list`, `view`, or `read`, and delete them with `remove`. All commands operate on the local Markdown/HTML archive referenced in the handler output. 63 + 64 + ### `pub` 65 + 66 + Leaflet.pub commands for AT Protocol publishing: 67 + 68 + - `pull` / `push` to sync notes with the remote publication. 69 + - `status`, `list`, and `diff` to inspect what is linked. 70 + - Support for working drafts, batch pushes, and file-based imports (`--file`) when publishing is combined with local markdown. 71 + 72 + ### `config` 73 + 74 + Inspect and mutate `~/.noteleaf.conf.toml`: 75 + 76 + - `noteleaf config show` (or `get <key>`) prints values. 77 + - `noteleaf config set <key> <value>` writes back to disk. 78 + - `noteleaf config path` reveals the file location. 79 + - `noteleaf config reset` rewinds to defaults. 80 + 81 + ### `setup` 82 + 83 + `noteleaf setup` initializes the database, config file, and data directories if they do not exist. `noteleaf setup seed` can load sample data (pass `--force` to wipe existing rows first). 84 + 85 + ### `status` 86 + 87 + `noteleaf status` prints absolute paths for the config file, data directory, database, and media folders along with environment overrides—handy for debugging or verifying a portable install. 88 + 89 + ## Development Tools 90 + 91 + `noteleaf tools ...` is available in development builds (`task build:dev`, `go run ./cmd`). It bundles maintenance utilities: 92 + 93 + ### Documentation generation 94 + 95 + ``` 96 + noteleaf tools docgen --format docusaurus --out website/docs/manual 97 + noteleaf tools docgen --format man --out docs/manual 98 + ``` 99 + 100 + Generates reference docs straight from the command definitions, keeping terminal help and published docs in sync. 101 + 102 + ### Lexicon fetching 103 + 104 + ``` 105 + noteleaf tools fetch lexicons 106 + noteleaf tools fetch lexicons --sha <commit> 107 + ``` 108 + 109 + Pulls the latest `leaflet.pub` lexicons from GitHub so the AT Protocol client stays current. You can point it at a specific commit for reproducible builds. 110 + 111 + ### Database utilities 112 + 113 + ``` 114 + noteleaf tools fetch gh-repo --repo owner/repo --path schemas --output tmp/schemas 115 + ``` 116 + 117 + Provides generic fetchers plus helpers used by CI and local testing to refresh schema files, warm caches, or introspect the SQLite database. 118 + 119 + These tools intentionally live behind the dev build tag so production binaries stay lean. Use them when contributing documentation or publishing features.
+92
website/docs/concepts/tui.md
··· 1 + --- 2 + title: Terminal UI 3 + sidebar_label: Terminal UI 4 + description: Navigate Noteleaf’s Bubble Tea interfaces and their script-friendly counterparts. 5 + sidebar_position: 6 6 + --- 7 + 8 + # Terminal UI 9 + 10 + Most list-style commands (tasks, notes, books) have two personalities: an interactive Bubble Tea view for exploration and a static text output for piping into other tools. This page explains how both modes behave. 11 + 12 + ## Interactive Mode 13 + 14 + ### Navigation 15 + 16 + - Launch the TUI with the default command (`noteleaf todo list`, `noteleaf note list`, `noteleaf media book add -i`, etc.). 17 + - Use `j`/`k` or the arrow keys to move the selection. Page Up/Down jump faster, while `g`/`G` (or Home/End) snap to the top or bottom depending on the view. 18 + - Search is always available—press `/` and start typing to filter titles, tags, projects, or notes in real time. 19 + 20 + ### Keyboard shortcuts 21 + 22 + All interactive components reuse the same key map defined in `internal/ui/data_list.go` and `internal/ui/data_table.go`: 23 + 24 + | Keys | Action | 25 + |------|--------| 26 + | `j` / `↓` | Move down | 27 + | `k` / `↑` | Move up | 28 + | `enter` | Select the highlighted row | 29 + | `v` | Open the detail preview (when supported) | 30 + | `/` | Start search | 31 + | `r` | Refresh data from the database | 32 + | `1-9` | Jump directly to a row index | 33 + | `q`, `ctrl+c` | Quit the view | 34 + 35 + The shortcuts appear in the on-screen help so you never have to memorize them all. 36 + 37 + ### Selection and actions 38 + 39 + - Press `enter` to activate the primary action (open a note, view a task, confirm a media selection, etc.). 40 + - Some screens expose extra actions on letter keys (e.g., `a` to archive, `e` to edit). They are listed alongside the contextual help (`?`). 41 + - Interactive prompts such as `noteleaf media movie add` use the same selection model, so keyboard muscle memory carries over. 42 + 43 + ### Help screens 44 + 45 + Hit `?` at any time to open the inline help overlay. It mirrors the bindings configured for the active component and also hints at hidden actions. Press `esc`, `backspace`, or `?` again to exit. 46 + 47 + ## Static Mode 48 + 49 + ### Command-line output 50 + 51 + Add `--static` (or remove `-i`) to force plain text output. Examples: 52 + 53 + ```sh 54 + noteleaf todo list --static 55 + noteleaf note list --static --tag meeting 56 + noteleaf media book list --all --static 57 + ``` 58 + 59 + Static mode prints tables with headings so they are easy to read or parse. Commands that default to prompts (like `noteleaf media movie add`) fall back to a numbered list when you omit `-i`. 60 + 61 + ### Scripting with Noteleaf 62 + 63 + Static output is predictable, making it straightforward to combine with familiar utilities: 64 + 65 + ```sh 66 + noteleaf todo list --static --project docs | rg "pending" 67 + noteleaf note list --static | fzf 68 + ``` 69 + 70 + Because each row includes the record ID, you can feed the result back into follow-up commands (`noteleaf note view 42`, `noteleaf todo done 128`, etc.). 71 + 72 + ### Output formatting 73 + 74 + The task viewer supports the `--format` flag for quick summaries: 75 + 76 + ```sh 77 + noteleaf todo view 12 --format brief 78 + noteleaf todo view 12 --format detailed # default 79 + ``` 80 + 81 + Brief mode hides timestamps and auxiliary metadata, which keeps CI logs or chat snippets short. Future commands will inherit the same pattern. 82 + 83 + ### JSON output 84 + 85 + Use `--json` wherever it exists (currently on task views/lists) for structured output: 86 + 87 + ```sh 88 + noteleaf todo view 12 --json | jq '.status' 89 + noteleaf todo list --static --json | jq '.[] | select(.status=="pending")' 90 + ``` 91 + 92 + JSON mode ignores terminal colors and uses machine-friendly field names so you can script exports without touching the SQLite file directly.
+5
website/src/css/custom.css
··· 74 74 75 75 --docusaurus-highlighted-code-line-bg: rgba(0, 164, 255, 0.15); 76 76 } 77 + 78 + .footer { 79 + background: var(--ifm-background-color); 80 + color: var(--ifm-font-color-base); 81 + }
+39 -15
website/src/pages/index.module.css
··· 1 - /** 2 - * CSS files with the .module.css suffix will be treated as CSS modules 3 - * and scoped locally. 4 - */ 5 - 6 1 .heroBanner { 7 - padding: 4rem 0; 8 - text-align: center; 9 - position: relative; 10 - overflow: hidden; 2 + padding: 4rem 0; 3 + text-align: center; 4 + position: relative; 5 + overflow: hidden; 6 + background: var(--ifm-background-color); 7 + color: var(--ifm-font-color-base); 8 + } 9 + 10 + .heroTitle { 11 + font-size: clamp(2.5rem, 6vw, 4.5rem); 12 + font-weight: 700; 13 + background: linear-gradient( 14 + 100deg, 15 + var(--ifm-color-primary-lightest), 16 + var(--ifm-color-success), 17 + var(--ifm-color-warning) 18 + ); 19 + -webkit-background-clip: text; 20 + -webkit-text-fill-color: transparent; 21 + text-shadow: 0 10px 30px rgba(0, 0, 0, 0.25); 22 + position: relative; 23 + z-index: 1; 24 + } 25 + 26 + .heroSubtitle { 27 + font-size: 1.4rem; 28 + max-width: 720px; 29 + margin: 1.5rem auto 0; 30 + color: var(--ifm-font-color-secondary); 31 + font-weight: 500; 32 + position: relative; 33 + z-index: 1; 11 34 } 12 35 13 36 @media screen and (max-width: 996px) { 14 - .heroBanner { 15 - padding: 2rem; 16 - } 37 + .heroBanner { 38 + padding: 2rem; 39 + } 17 40 } 18 41 19 42 .buttons { 20 - display: flex; 21 - align-items: center; 22 - justify-content: center; 43 + margin-top: 24px; 44 + display: flex; 45 + align-items: center; 46 + justify-content: center; 23 47 }
+9 -4
website/src/pages/index.tsx
··· 11 11 function HomepageHeader() { 12 12 const { siteConfig } = useDocusaurusContext(); 13 13 return ( 14 - <header className={clsx("hero hero--primary", styles.heroBanner)}> 14 + <header className={clsx("hero", styles.heroBanner)}> 15 15 <div className="container"> 16 - <Heading as="h1" className="hero__title"> 16 + <Heading 17 + as="h1" 18 + className={clsx("hero__title", styles.heroTitle)} 19 + > 17 20 {siteConfig.title} 18 21 </Heading> 19 - <p className="hero__subtitle">{siteConfig.tagline}</p> 22 + <p className={clsx("hero__subtitle", styles.heroSubtitle)}> 23 + {siteConfig.tagline} 24 + </p> 20 25 <div className={styles.buttons}> 21 26 <Link 22 - className="button button--secondary button--lg" 27 + className="button button--info button--lg" 23 28 to="/docs/quickstart" 24 29 > 25 30 Get Started
website/static/img/favicon.ico

This is a binary file and will not be displayed.

+2 -2
website/static/img/logo.svg
··· 1 1 <svg xmlns="http://www.w3.org/2000/svg" width="200" height="200" viewBox="0 0 512 512"> 2 2 <defs> 3 3 <linearGradient id="leafGradient" x1="0%" y1="0%" x2="100%" y2="100%"> 4 - <stop offset="0%" style="stop-color:#00FFB2;stop-opacity:1" /> 5 - <stop offset="100%" style="stop-color:#12C78F;stop-opacity:1" /> 4 + <stop offset="0%" style="stop-color:#00A4FF;stop-opacity:1" /> 5 + <stop offset="100%" style="stop-color:#00A4FF;stop-opacity:1" /> 6 6 </linearGradient> 7 7 </defs> 8 8 <path fill="none" stroke="url(#leafGradient)" stroke-linecap="round" stroke-linejoin="round" stroke-width="32"
+55 -8
website/src/components/HomepageFeatures/index.tsx
··· 6 6 type FeatureItem = { 7 7 title: string; 8 8 description: ReactNode; 9 + theme: keyof typeof themeClassMap; 10 + }; 11 + 12 + const themeClassMap = { 13 + primary: styles.featureCardPrimary, 14 + info: styles.featureCardInfo, 15 + success: styles.featureCardSuccess, 16 + warning: styles.featureCardWarning, 17 + accent: styles.featureCardAccent, 18 + plum: styles.featureCardPlum, 19 + danger: styles.featureCardDanger, 9 20 }; 10 21 11 22 const FeatureList: FeatureItem[] = [ ··· 14 25 description: ( 15 26 <> 16 27 Built for the command line with a beautiful, keyboard-driven interface 17 - using the Bubble Tea framework. 28 + powered by Bubble Tea and Fang. 18 29 </> 19 30 ), 31 + theme: 'primary', 20 32 }, 21 33 { 22 34 title: 'Task Management', 23 35 description: ( 24 36 <> 25 - Organize your tasks with projects, priorities, tags, and due dates. 26 - Track your progress with statuses and time estimates. 37 + Organize your tasks with projects, priorities, tags, contexts, due 38 + dates, and recurrence—all from a single CLI. 27 39 </> 28 40 ), 41 + theme: 'danger', 42 + }, 43 + { 44 + title: 'Leaflet.pub Publishing', 45 + description: ( 46 + <> 47 + Sync Markdown notes with leaflet.pub, push updates over AT Protocol, and 48 + manage drafts without leaving the terminal. 49 + </> 50 + ), 51 + theme: 'accent', 52 + }, 53 + { 54 + title: 'Articles & Readability', 55 + description: ( 56 + <> 57 + Capture the clean content of any article, store Markdown + HTML copies, 58 + and enjoy a terminal reader inspired by Readability. 59 + </> 60 + ), 61 + theme: 'warning', 29 62 }, 30 63 { 31 64 title: 'Knowledge Base', 32 65 description: ( 33 66 <> 34 67 Keep notes, track books, movies, and TV shows. Link everything together 35 - with tags and projects. 68 + with tags, IDs, and shared metadata. 36 69 </> 37 70 ), 71 + theme: 'info', 72 + }, 73 + { 74 + title: 'Open Source & MIT Licensed', 75 + description: ( 76 + <> 77 + Built in the open on GitHub under the MIT license. Fork it, extend it, 78 + and make Noteleaf part of your own workflows. 79 + </> 80 + ), 81 + theme: 'plum', 38 82 }, 39 83 ]; 40 84 41 - function Feature({title, description}: FeatureItem) { 85 + function Feature({title, description, theme}: FeatureItem) { 86 + const cardClass = themeClassMap[theme] ?? themeClassMap.primary; 42 87 return ( 43 88 <div className={clsx('col col--4')}> 44 - <div className="text--center padding-horiz--md"> 45 - <Heading as="h3">{title}</Heading> 46 - <p>{description}</p> 89 + <div className={clsx('text--left padding-horiz--md', styles.featureCard, cardClass)}> 90 + <Heading as="h3" className={styles.featureTitle}> 91 + {title} 92 + </Heading> 93 + <p className={styles.featureCopy}>{description}</p> 47 94 </div> 48 95 </div> 49 96 );
+99 -5
website/src/components/HomepageFeatures/styles.module.css
··· 1 1 .features { 2 2 display: flex; 3 - align-items: center; 4 - padding: 2rem 0; 3 + align-items: stretch; 4 + padding: 3rem 0; 5 5 width: 100%; 6 + background: var(--ifm-background-surface-color); 6 7 } 7 8 8 - .featureSvg { 9 - height: 200px; 10 - width: 200px; 9 + .featureCard { 10 + border-radius: 1.25rem; 11 + padding: 2rem 1.75rem; 12 + min-height: 220px; 13 + border: 1px solid var(--ifm-color-emphasis-300); 14 + background: var(--ifm-background-color); 15 + margin-bottom: 1.5rem; 16 + } 17 + 18 + .featureCardPrimary { 19 + border-top: 4px solid var(--ifm-color-primary); 20 + } 21 + 22 + .featureCardSuccess { 23 + border-top: 4px solid var(--ifm-color-success); 24 + } 25 + 26 + .featureCardInfo { 27 + border-top: 4px solid var(--ifm-color-info); 28 + } 29 + 30 + .featureCardWarning { 31 + border-top: 4px solid var(--ifm-color-warning); 32 + } 33 + 34 + .featureCardAccent { 35 + border-top: 4px solid #00ffb2; 36 + } 37 + 38 + .featureCardPlum { 39 + border-top: 4px solid #c259ff; 40 + } 41 + 42 + .featureCardDanger { 43 + border-top: 4px solid #eb4268; 44 + } 45 + 46 + .featureTitle { 47 + font-size: 1.3rem; 48 + font-weight: 700; 49 + letter-spacing: 0.04em; 50 + text-transform: uppercase; 51 + margin-bottom: 0.75rem; 52 + } 53 + 54 + .featureCopy { 55 + font-size: 1.05rem; 56 + line-height: 1.6; 57 + color: var(--ifm-font-color-secondary); 58 + margin: 0; 59 + } 60 + 61 + .featureCardPrimary .featureTitle { 62 + background: linear-gradient(120deg, var(--ifm-color-primary), #66c9ff); 63 + -webkit-background-clip: text; 64 + -webkit-text-fill-color: transparent; 65 + } 66 + 67 + .featureCardSuccess .featureTitle { 68 + background: linear-gradient(120deg, var(--ifm-color-success), #1ccb92); 69 + -webkit-background-clip: text; 70 + -webkit-text-fill-color: transparent; 71 + } 72 + 73 + .featureCardInfo .featureTitle { 74 + background: linear-gradient(120deg, var(--ifm-color-info), #8ef7f5); 75 + -webkit-background-clip: text; 76 + -webkit-text-fill-color: transparent; 77 + } 78 + 79 + .featureCardWarning .featureTitle { 80 + background: linear-gradient(120deg, var(--ifm-color-warning), #ffbd85); 81 + -webkit-background-clip: text; 82 + -webkit-text-fill-color: transparent; 83 + } 84 + 85 + .featureCardAccent .featureTitle { 86 + background: linear-gradient(120deg, #5cdf8a, #00ffb2); 87 + -webkit-background-clip: text; 88 + -webkit-text-fill-color: transparent; 89 + } 90 + 91 + .featureCardPlum .featureTitle { 92 + background: linear-gradient(120deg, #c259ff, #ff66c4); 93 + -webkit-background-clip: text; 94 + -webkit-text-fill-color: transparent; 95 + } 96 + 97 + .featureCardDanger .featureTitle { 98 + background: linear-gradient(120deg, #eb4268, #ff7b8d); 99 + -webkit-background-clip: text; 100 + -webkit-text-fill-color: transparent; 101 + } 102 + 103 + .features :global(.container) { 104 + background: transparent; 11 105 }