# 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. ```sql 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 `!`.)