Import documentation: PLAN.md
Import the existing local project snapshot. This commit organizes existing files; it does not represent newly developed functionality.
This commit is contained in:
@@ -0,0 +1,247 @@
|
|||||||
|
# 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 `!`.)
|
||||||
Reference in New Issue
Block a user