Files
Notion/PLAN.md
T
arsam 85bfafa1a1 Import documentation: PLAN.md
Import the existing local project snapshot. This commit organizes existing files; it does not represent newly developed functionality.
2026-09-18 23:14:14 +03:30

18 KiB
Raw Blame History

Plan: "Notara" — A Private, Superfast, Beautifully-Crafted Notion for Windows 11

Context

You want a personal, single-user Notion replacement for Windows 11 that is fast, not Electron, built on Rust, and — most importantly — a real, polished, installable app with a guided first-run wizard and a genuinely great experience for you. START.md catalogs the entire Notion product, but ~60% of it (SSO, SCIM, teamspaces, sharing, comments, audit logs, the public API, billing, mobile) is multi-user/enterprise and irrelevant here. We keep the hard, valuable core and pour the saved effort into craft: onboarding, microinteractions, keyboard-first flow, templates, and stability.

Confirmed decisions:

  • Tauri v2 — Rust backend + web UI in WebView2 (tiny binary, low RAM, not bundled Chromium).
  • All 4 pillars in v1: block editor + page tree, databases + views, global search, deep polish.
  • Local-first, sync-ready: SQLite on your PC now; pages stored as Yjs CRDTs so self-hosted sync later is plug-in, not rewrite.
  • This is a product, not a prototype: a first-run setup wizard, a proper .msi/.exe installer, starter templates, auto-backups, a settings screen, and Notion-grade microinteractions.

Why these tech choices (grounded in current docs):

  • BlockNote (@blocknote/react) is a Notion-style block editor on ProseMirror/TipTap — it hands us the single hardest part of any Notion clone, and is Yjs-native.
  • Yjs (CRDT) is the page document format from day one → sync later = "attach a provider," no storage rewrite.
  • Tauri v2 SQL plugin (SQLite + migrations) for storage; SQLite FTS5 for instant search; Tauri updater + bundler for a real installer and future auto-updates.

"GPU / superfast" reality: no hand-written shaders. Speed = Rust I/O + local SQLite + WebView2's own GPU compositing + a disciplined, virtualized frontend. This beats Notion/Electron on cold-start and RAM. A pure GPU-native editor (egui/GPUI) was rejected — it means building rich text from scratch (months–years), the wrong trade for a solo build.


Architecture Overview

┌───────────────────────────────────────────────────────────┐
│  WebView2 (Windows built-in)  —  Frontend (TypeScript)     │
│                                                            │
│  React + Vite + Tailwind + Framer Motion                   │
│   ├─ First-run WIZARD (welcome → workspace → theme →       │
│   │                     templates → done)                  │
│   ├─ Sidebar (page tree, favorites, trash, search entry)   │
│   ├─ Editor  = BlockNote  ⇄  Yjs (Y.Doc per page)          │
│   ├─ Databases = TanStack Table/Virtual (Table/Board/...)  │
│   ├─ Side-peek / center-peek for DB rows                   │
│   ├─ Command palette + quick-switcher (Ctrl+P / Ctrl+K)    │
│   └─ Settings (theme, backups, shortcuts, about)           │
│              │  @tauri-apps/api  invoke()  │               │
└──────────────┼────────────────────────────┼───────────────┘
               ▼                            ▼
┌───────────────────────────────────────────────────────────┐
│  Rust core (Tauri v2)                                      │
│   ├─ tauri-plugin-sql  → SQLite  (pages, blocks, dbs, FTS) │
│   ├─ tauri-plugin-fs   → asset files (images, uploads)     │
│   ├─ tauri-plugin-updater → future auto-updates            │
│   ├─ commands → export, import, backup, heavy search       │
│   └─ (LATER) yrs-based self-hosted sync server             │
└───────────────────────────────────────────────────────────┘
                     │
                     ▼
   %APPDATA%\Notara\  →  workspace.db  +  \assets\  +  \backups\

First-Run Setup Wizard (a headline feature)

On first launch (no workspace.db yet), a polished full-window wizard runs — this is the "wizard and everything" you asked for. It sets workspace_meta.onboarded = 1 when finished so it never re-appears (re-openable from Settings → "Run setup again").

  1. Welcome — app name, one-line pitch, animated logo; "Get started".
  2. Workspace — name your workspace; choose data folder (default %APPDATA%\Notara, changeable); we create the DB + folders here.
  3. Appearance — pick Dark / Light / System; pick accent color; font (Default/Serif/Mono). Live preview pane updates instantly.
  4. Import (optional) — "Bring your notes": import Markdown/.md folder, or a Notion Markdown+CSV export ZIP, or start empty. Progress bar with counts.
  5. Templates — check the starter pages/databases to seed (see gallery below), or "Empty workspace".
  6. Done — quick 4-tip cheat sheet (slash /, Ctrl+P, drag to reorder, right-click menus) → drops you into your new home page.

Starter templates gallery (also reachable later via "New → From template"): Daily Journal, Tasks board (To-do/Doing/Done), Reading list (database), Meeting notes, Project tracker, Quick note. Each is just seed pages/DB rows created in SQLite.


Experience & Polish Principles ("best experience")

These are first-class requirements, verified per milestone — not "nice later":

  • Keyboard-first: command palette (Ctrl+K) for every action; quick-switcher (Ctrl+P); full editing/nav shortcut map; markdown input rules (# →H1, - →bullet, [] →todo).
  • Microinteractions (Framer Motion, subtle & fast, ~120–180ms): sidebar expand/collapse, page open cross-fade, drag-and-drop blue placement guides, hover-revealed block handles (+ / ⋮⋮), toast confirmations, skeleton loaders.
  • Right-click context menus everywhere (pages, blocks, rows): rename, duplicate, delete, move, copy link, favorite.
  • Side-peek / center-peek: open a database row in a side panel (Notion's signature flow) without leaving the list; Esc closes.
  • Empty states, not blank screens: every empty page/DB/search shows a friendly prompt + one-click action (Notion's discoverability model).
  • Native-feeling chrome: custom title bar, window controls, remembers size/position, opens where you left off, launch-on-startup option, tray icon.
  • Instant everywhere: virtualized lists (TanStack Virtual) so a 5,000-row database and a 1,000-page sidebar stay smooth.
  • Zero data loss: debounced autosave + crash-safe Yjs persistence + rolling local backups.

Visual Fidelity — an exact, modern Notion-like interface

A hard goal: someone glancing at the screen should read it as Notion. We replicate Notion's actual layout, spacing, type, and color system (a clean-room rebuild of the look & feel — our own code/assets, no copied proprietary files):

  • Overall layout: left sidebar (~240px, resizable, collapsible with <<) + main content area; centered page column (~708px content width, "Full width" toggle expands it); generous whitespace, calm density.
  • Sidebar look: subtle gray background, small uppercase section labels (Favorites / Private / Shared), page rows with emoji/icon + title, hover-revealed + and ⋮ (•••) controls, disclosure triangles for nesting, drag handles. Workspace switcher at top, Search + Settings + Trash near it.
  • Typography: Notion uses a system UI stack (Inter-like sans) — ship Inter as the default, plus Serif (Lyon-like → Georgia/serif) and Mono page styles; heading sizes and line-heights matched to Notion (H1 ~1.875rem, body ~16px, ~1.5 line-height); "Small text" and "Full width" page toggles.
  • Color system (CSS variables, light + dark): near-white #ffffff / dark #191919 backgrounds, #37352f text on light / #e9e9e7 on dark, Notion's exact block highlight palette (gray/brown/orange/yellow/green/blue/purple/pink/red for text + backgrounds), #2383e2-style blue accents and selection.
  • Editor chrome: hover block handle (⋮⋮ drag + + insert) in the left gutter, / slash menu styled like Notion's (grouped, icons, search), the bubble/selection toolbar (B/I/U/S, code, link, color), placeholder text ("Type '/' for commands"), the "Press Enter to continue" empty-line feel.
  • Page header: hover-revealed Add icon / Add cover / Add comment row, large title, breadcrumb bar up top, Share-less (private) but with ••• menu (style, small text, full width, export, move to trash) and updates/history.
  • Database chrome: view tabs row with + New view, right-aligned Filter/Sort/Search/•••/blue New button; table with resizable/reorderable columns, property-type icons, row hover ⋮⋮, the blue + New row; Board columns with count badges.
  • Icons: Lucide chosen to match Notion's line-icon weight; emoji picker for page icons like Notion.

We'll tune this against Notion side-by-side (screenshots from START.md's UI/UX spec) each milestone until it reads as a match. Fidelity is a verification item, not an afterthought.


Tech Stack (pinned)

Layer Choice Why
Shell Tauri v2 (+ updater + bundler) Rust, WebView2, ~10MB, real installer
Backend Rust Speed; yrs for future sync
Frontend React 18 + TypeScript + Vite BlockNote is React; best ecosystem for a novice
Editor BlockNote (@blocknote/react, /core) Notion-style, Yjs-native
Doc format Yjs CRDT → sync-ready day one
Styling Tailwind CSS + CSS vars Theming (dark/light/accent)
Motion Framer Motion Polished, restrained animations
DB grids TanStack Table + Virtual Fast virtualized database views
App state Zustand Tiny client state
Storage SQLite via tauri-plugin-sql (+FTS5) Local, instant, migrations
Assets/backup tauri-plugin-fs Images/uploads + backup files
Icons Lucide Clean, Notion-like

Data Model (SQLite)

Structured metadata in relational tables; page bodies as Yjs binary blobs (editor's source of truth) — keeps tree/search/DB queries fast while keeping rich text conflict-free and sync-ready.

CREATE TABLE workspace_meta (       -- single row: name, data_dir, theme, accent, onboarded, last_page
  id INTEGER PRIMARY KEY CHECK (id=1), name TEXT, theme TEXT, accent TEXT,
  onboarded INTEGER DEFAULT 0, last_page_id TEXT, settings JSON
);
CREATE TABLE pages (
  id TEXT PRIMARY KEY, parent_id TEXT REFERENCES pages(id),
  title TEXT DEFAULT '', icon TEXT, cover TEXT,
  sort_order REAL, is_favorite INTEGER DEFAULT 0, in_trash INTEGER DEFAULT 0,
  created_at INTEGER, updated_at INTEGER
);
CREATE TABLE page_docs ( page_id TEXT PRIMARY KEY REFERENCES pages(id), ydoc BLOB );
CREATE TABLE databases ( id TEXT PRIMARY KEY, page_id TEXT, name TEXT );
CREATE TABLE db_properties ( id TEXT PRIMARY KEY, database_id TEXT, name TEXT, type TEXT, config JSON, sort_order REAL );
CREATE TABLE db_rows ( id TEXT PRIMARY KEY, database_id TEXT, page_id TEXT REFERENCES pages(id), sort_order REAL );
CREATE TABLE db_values ( row_id TEXT, property_id TEXT, value JSON, PRIMARY KEY(row_id, property_id) );
CREATE TABLE db_views ( id TEXT PRIMARY KEY, database_id TEXT, name TEXT, type TEXT,
  filters JSON, sorts JSON, groups JSON, visible_props JSON, sort_order REAL );
CREATE VIRTUAL TABLE pages_fts USING fts5(page_id UNINDEXED, title, body);
  • Fractional sort_order → drag-reorder is a one-row update.
  • DB rows are pages (Notion's model) → reuse the editor + page_docs for row bodies.
  • FTS mirror updated on save from the Y.Doc's plain text → instant search.

Phased Roadmap

Ships a usable app early, then layers craft. Each milestone runs and is verified independently.

Milestone 0 — Environment, scaffold, installer skeleton (1 day)

  • Install prerequisites (below). Scaffold create-tauri-app (React+TS+Vite). Wire Tailwind, Zustand, Framer Motion, Lucide.
  • Add tauri-plugin-sql+tauri-plugin-fs; first migration creates all tables. Custom title bar + window state persistence.
  • Confirm npm run tauri build produces a working .msi/.exe you can install. Create project PLAN.md (this file).

Milestone 1 — First-run wizard + pages + block editor (the core) (2 weeks)

  • The wizard (all 6 steps above), gated on workspace_meta.onboarded.
  • Sidebar tree: create/rename/delete, drag-reorder & nest with blue guides, favorites, trash + restore, right-click menus.
  • Editor: BlockNote bound to a per-page Y.Doc; debounced persist to page_docs + FTS mirror; page header (title, emoji icon, cover).
  • Starter templates seeding.
  • Outcome: a real, private note app with onboarding you'd use daily.

Milestone 2 — Search + command palette (3–4 days)

  • Ctrl+P quick-switcher; Ctrl+K command palette (all actions); FTS full-text search, instant + keyboard-navigable; empty/no-result states.

Milestone 3 — Databases & views (3–4 weeks; second pillar)

  • Inline & full-page databases; property types: text, number, select, multi-select, status, date, checkbox, URL, created/edited time.
  • Views: Table (TanStack Table+Virtual), Board (group-by), List, Gallery, Calendar; per-view filters/sorts/groups/column-visibility.
  • Side-peek row → full page editor (reuses M1). Row context menus.

Milestone 4 — Deep polish, settings, backups, export/import (2 weeks)

  • Settings screen: appearance (theme/accent/font), backups, shortcuts reference, data folder, launch-on-startup, "run setup again", about/version.
  • Dark/light/system + accent theming; finalize all shortcuts & markdown rules; motion pass.
  • Auto-backups: rolling timestamped copies of workspace.db to \backups\ (on close + interval); restore-from-backup UI.
  • Export: page/workspace → Markdown & HTML (Rust command); PDF via WebView print. Import: Markdown folder + Notion export ZIP (also used in wizard).
  • Tray icon, launch-on-startup, remembers last page.

Milestone 5 (LATER, optional) — Self-hosted sync + auto-update

  • Pages are already Yjs → add a client provider + small yrs (Rust) self-hosted server, single shared secret. Wire tauri-plugin-updater for one-click app updates. No data-model change.

Proposed Directory Structure

D:\Projects\Notion\
├─ PLAN.md
├─ package.json  vite.config.ts  index.html
├─ src\                        # FRONTEND
│  ├─ main.tsx  App.tsx
│  ├─ wizard\          # first-run onboarding steps + templates
│  ├─ store\           # Zustand: workspace, ui, theme
│  ├─ db\              # TS data layer over sql plugin / invoke()
│  ├─ editor\          # BlockNote + Yjs binding + persistence hook
│  ├─ sidebar\         # page tree, drag-reorder, context menus
│  ├─ database\        # views: table/board/calendar/gallery/list + peek
│  ├─ search\          # quick-switcher + command palette + FTS
│  ├─ settings\        # settings screen, backups UI
│  └─ components\      # title bar, menus, modals, toasts, empty states
└─ src-tauri\                  # BACKEND (Rust)
   ├─ Cargo.toml  tauri.conf.json
   ├─ migrations\0001_init.sql
   └─ src\ lib.rs  main.rs  commands\ (export, import, backup, search)

First files (M0–M1): src-tauri/src/lib.rs (plugin init + migrations), migrations/0001_init.sql, src/db/index.ts (typed helpers), src/editor/useYjsPage.ts (load blob→hydrate Y.Doc→bind BlockNote→debounced persist+FTS), src/wizard/Wizard.tsx, src/App.tsx, custom TitleBar.tsx.


Prerequisites (Milestone 0 — you run these; prefix with ! in the session or use a terminal)

  1. Rust via rustup (https://rustup.rs). 2. Node.js LTS v20+. 3. Microsoft C++ Build Tools (MSVC). 4. WebView2 Runtime (preinstalled on Win11 — verify). The Tauri bundler produces the .msi; WebView2 is auto-bootstrapped in the installer.

Verification (per milestone — prove it actually works)

  • M0: tauri dev opens; SQLite insert/read round-trips; tauri build yields an .msi that installs and launches; custom title bar drags/resizes.
  • M1: Fresh profile → wizard runs end-to-end, seeds templates, never reappears. Create nested pages, drag-reorder, rich blocks; close & reopen → content persists; kill mid-edit → no loss.
  • M2: ~50 pages: Ctrl+P and search return correct results <50ms; Ctrl+K runs actions.
  • M3: DB with 3–4 property types; switch Table↔Board↔Calendar; filter/sort/group; side-peek a row and edit its body.
  • M4: Toggle theme/accent live; export a tree to Markdown and diff; trigger a backup and restore it; import a Markdown folder.
  • Perf throughout: cold-start & idle RAM measured vs. Notion (expect large wins); 1k-page sidebar + 5k-row DB stay smooth.
  • Fidelity throughout: side-by-side against real Notion screenshots each milestone — sidebar, page column width, type scale, color/highlight palette, block handles, slash menu, and database chrome must read as a visual match.

Risks & Mitigations

  • Scope: dropped all multi-user/enterprise; strict phasing; M1 alone is usable.
  • Databases (biggest sub-project): isolated to M3; can ship M1–M2 and live in it first.
  • Yjs persistence: start with full-state blob per page (simple/correct); move to incremental updates only if a page grows large.
  • Rust curve: most logic is TypeScript; Rust ≈ plugin config + a few export/import/backup commands.
  • Polish creep: motion/interaction budget fixed (fast, subtle) so it never balloons.

What comes first when building starts

  1. Scaffold Tauri v2 + React + TS; custom title bar; confirm it launches and builds an installer.
  2. Wire SQLite migrations + the M1 wizard/editor/sidebar skeleton.
  3. (Interactive installs of Rust/Node/Build Tools are run by you with !.)