Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aebf8be37a | ||
|
|
c077917c4e | ||
|
|
85bfafa1a1 | ||
|
|
0d248125ae | ||
|
|
a98c8800ff | ||
|
|
22fa31b595 | ||
|
|
8d6f3be87a | ||
|
|
2de618a9d9 | ||
|
|
55cdcb8a3c | ||
|
|
f5853cbc45 |
@@ -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 `!`.)
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
# Tauri + React + Typescript
|
||||||
|
|
||||||
|
This template should help get you started developing with Tauri, React and Typescript in Vite.
|
||||||
|
|
||||||
|
## Recommended IDE Setup
|
||||||
|
|
||||||
|
- [VS Code](https://code.visualstudio.com/) + [Tauri](https://marketplace.visualstudio.com/items?itemName=tauri-apps.tauri-vscode) + [rust-analyzer](https://marketplace.visualstudio.com/items?itemName=rust-lang.rust-analyzer)
|
||||||
@@ -0,0 +1,294 @@
|
|||||||
|
# Notion App Feature and UI UX Specification
|
||||||
|
|
||||||
|
## Executive summary
|
||||||
|
|
||||||
|
Notion is a block-based workspace available on desktop, web, and mobile, organized around pages, databases, views, and collaboration controls. Its most distinctive product model is that nearly everything is either a page or a block on a page, while databases are collections of pages enriched with properties, multiple saved views, filters, sorts, groups, formulas, relations, and rollups. Official documentation now also references data sources as a first-class concept in the product and developer platform, indicating a deeper separation between database containers and underlying structured sources in newer API versions. citeturn11search0turn19view0turn18view0turn20view0turn44search11turn44search8
|
||||||
|
|
||||||
|
Across platforms, the UX is intentionally consistent in information architecture but not identical in interaction model. Desktop and web emphasize hover-revealed controls, keyboard accelerators, tabs, side peeks, and deep settings access. Mobile prioritizes compact navigation, persistent tap targets, a keyboard-adjacent editing toolbar, and reduced administrative scope. Official docs explicitly note that mobile has no hover states, collapses desktop column layouts into a single column, and does not support some actions such as imports, many account and billing changes, or workspace security editing. citeturn31view0turn31view1turn24search8
|
||||||
|
|
||||||
|
The discoverable feature surface is broader than classic note-taking. In addition to writing, blocks, and databases, Notion includes forms, charts, buttons, database automations, page analytics, sites publishing, a web clipper, external embeds, public and internal API connections, webhook actions, AI connectors, and MCP-based AI-app access. Enterprise layers add SAML SSO, SCIM, audit log, domain verification and management, security/compliance connections, private teamspaces, and advanced workspace controls. citeturn16view2turn21view0turn16view3turn26search2turn23search8turn40search7turn39search8turn41view0turn41view1turn41view2turn41view3turn22view5turn22view6turn16view9turn29view1turn40search18
|
||||||
|
|
||||||
|
From a UI/UX standpoint, Notion uses a sparse, high-density interface with progressive disclosure. Block handles, slash commands, view settings, peek modes, page-level menus, and sidebar nesting let novices start with plain text and gradually discover advanced behaviors. The design relies heavily on hover affordances, contextual menus, command/search entry points, drag-and-drop blue placement guides, and modal or side-peek editing surfaces. Official docs are good on user-facing behavior, but they do **not** publish a full formal design system, component token inventory, animation timing spec, or ARIA role map. Where those details are not public, this report marks them as **unspecified**. citeturn11search0turn22view3turn18view0turn34view0turn35view0turn31view0
|
||||||
|
|
||||||
|
Accessibility and localization are mixed. Officially, Notion supports extensive keyboard shortcuts, dark/light/system appearance, many interface languages, mirrored UI for Arabic and Hebrew, block-level text direction, and RTL auto-detection in most text blocks except simple tables. However, public official documentation does not publish WCAG conformance tables or ARIA implementation details, and independent accessibility reviews have reported issues in desktop flows involving contrast, alt text, and tabbing. The most defensible conclusion is that accessibility support exists and is improving, but a complete component-level accessibility spec is **not publicly discoverable**. citeturn34view0turn36view0turn36view2turn24search0turn12search10turn32search15
|
||||||
|
|
||||||
|
## Research basis and product model
|
||||||
|
|
||||||
|
This report is grounded primarily in Notion’s Help Center, official pricing and product pages, official developer documentation, public release/changelog material, public app-store listings, and public product screenshots/help screenshots. Third-party material is used only where official sources are silent, most notably for accessibility gaps. Because the Notion product changes frequently and some behaviors are controlled by plan, workspace policy, or experimental rollout, the catalog below focuses on what is **publicly documented or directly visible in public materials** as of July 2026. Details not described by those sources are labeled **unspecified** rather than inferred as fact. citeturn29view1turn24search4turn44search12turn14search0turn14search1turn12search10turn32search15
|
||||||
|
|
||||||
|
At the model level, Notion can be understood as a hierarchy of workspace containers, navigational surfaces, content pages, composable blocks, and structured databases. Pages can contain freeform blocks, inline databases, linked databases, forms, charts, embeds, comments, backlinks, and page discussions. Database entries are themselves pages, which is why table rows, board cards, calendar items, and gallery cards all open into full page bodies with additional content and properties. citeturn22view7turn11search0turn16view7turn16view2turn21view0turn18view0
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
flowchart LR
|
||||||
|
Workspace --> Sidebar
|
||||||
|
Sidebar --> Favorites
|
||||||
|
Sidebar --> Teamspaces
|
||||||
|
Sidebar --> Shared
|
||||||
|
Sidebar --> Private
|
||||||
|
Teamspaces --> Pages
|
||||||
|
Shared --> Pages
|
||||||
|
Private --> Pages
|
||||||
|
Pages --> Blocks
|
||||||
|
Pages --> Subpages
|
||||||
|
Pages --> Databases
|
||||||
|
Databases --> Views
|
||||||
|
Databases --> Properties
|
||||||
|
Properties --> Formula
|
||||||
|
Properties --> Relation
|
||||||
|
Relation --> Rollup
|
||||||
|
Databases --> Templates
|
||||||
|
Databases --> Automations
|
||||||
|
Databases --> Forms
|
||||||
|
Databases --> Charts
|
||||||
|
Pages --> Comments
|
||||||
|
Pages --> Backlinks
|
||||||
|
Pages --> Publish
|
||||||
|
```
|
||||||
|
|
||||||
|
The same structure also explains why Notion’s permission model is unusually granular. Pages can be shared directly, accessible through teamspaces, exposed via general access, or published to the web; database pages can additionally use row/page-level access rules based on people properties; and API connections inherit a page-scoped access model that closely mirrors human sharing. citeturn42view0turn41view1
|
||||||
|
|
||||||
|
The chart below is an analytical grouping used for this report, not a vendor taxonomy.
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
pie showData
|
||||||
|
title Analytical grouping of discoverable Notion feature families
|
||||||
|
"Core authoring and page composition" : 24
|
||||||
|
"Structured databases and analytics" : 26
|
||||||
|
"Collaboration and permissions" : 18
|
||||||
|
"Integrations and developer platform" : 16
|
||||||
|
"Admin, security, and billing" : 16
|
||||||
|
"Platform-specific and UI UX behaviors" : 20
|
||||||
|
```
|
||||||
|
|
||||||
|
## Exhaustive feature catalog
|
||||||
|
|
||||||
|
### Core authoring, page, and content features
|
||||||
|
|
||||||
|
| Feature family | Discoverable capabilities | Notes |
|
||||||
|
|---|---|---|
|
||||||
|
| Page fundamentals | Top-level pages, nested subpages, page titles, icons, covers, breadcrumbs, favorites, link-to-page blocks, page links via `@`, `[[`, and `+` commands. | Pages are the primary content unit; pages can live in teamspaces, shared, private, or favorites sections. Breadcrumb blocks and page links are official block-level features. citeturn22view7turn22view3turn11search0turn35view0 |
|
||||||
|
| Basic blocks | Text, page, to-do, headings, simple table, bulleted list, numbered list, toggle list, quote, divider, link to page, callout. | Official block menu documentation lists these as native block types. Toggles currently must be opened/closed manually; official docs note no “open or close all by default” setting in that page. citeturn11search0 |
|
||||||
|
| Media and code blocks | Image, video, audio, file, code block, PDF, bookmarks, embeds, equations. | Media can be uploaded or embedded; code blocks support languages and formatting; equations support TeX. citeturn11search0turn41view0turn35view0 |
|
||||||
|
| Advanced page utilities | Table of contents, breadcrumbs, button blocks, synced blocks, inline equations, reminders and date mentions. | Buttons can insert blocks, add pages, edit pages, send notifications, send Gmail mail, send webhooks, and show confirmations; synced blocks replicate shared content across locations. citeturn16view3turn16view6turn11search0 |
|
||||||
|
| Text styling and layout | Rich-text selection toolbar, bold, italics, underline, strikethrough, inline code, links, comments, text color/highlight, three typography styles, small text, full width. | Page-level style controls include Default, Serif, and Mono; layout toggles include small text and full width. citeturn36view3turn11search0 |
|
||||||
|
| Page customization | Backlinks visibility, page discussions toggle, database-page heading customization, inline comment display mode, database-page layout builder with pinned properties, property groups, modules, and side panels. | Some of these controls are page-type specific; database pages expose deeper layout controls than standard pages. citeturn24search7turn16view8 |
|
||||||
|
| History and lifecycle | Version history, restore previous versions, archive/unarchive, trash and restore, workspace export backups. | Version history is page-level; archive shows a yellow banner; workspace exports send a download link by email; public docs distinguish trash restore from version restore. citeturn23search0turn23search12turn28view2 |
|
||||||
|
|
||||||
|
### Structured databases, properties, views, and analytics
|
||||||
|
|
||||||
|
| Database capability | Discoverable scope | Notes |
|
||||||
|
|---|---|---|
|
||||||
|
| Database object model | Databases are collections of pages; rows/cards/items are pages that open into full page bodies. | This is foundational to Notion’s data model and drives uniform editing across table, board, list, calendar, and gallery surfaces. citeturn18view0turn15search9 |
|
||||||
|
| View types | Table, Board, Timeline, Calendar, List, Gallery, Chart; forms are connected to databases. | Chart view supports vertical bar, horizontal bar, line, donut, and number charts; forms store responses in a database and create a default `Responses` table view. citeturn17view2turn21view0turn16view2 |
|
||||||
|
| View settings | Layout, property visibility, filter, sort, group, sub-group, copy link to view, open pages in side peek/center peek/full page. | View tabs can be reordered; view-tab display can be icon only, text only, or both, but that preference is personal to the viewer. citeturn18view0 |
|
||||||
|
| Filters and advanced filters | Simple filters, personal vs save-for-everyone filters, advanced filters with nested `AND`/`OR` groups up to three layers deep. | Sub-item visibility can affect filtered results. citeturn18view0 |
|
||||||
|
| Sorts and groups | Multi-sort, alphabetic/numeric/select-order sorting, manual group sorting, hide empty groups, sub-grouping. | Table columns can be frozen for comparison during horizontal scrolling. citeturn18view0 |
|
||||||
|
| Database search | Title-and-property search within databases that have at least three pages. | Search narrows results as you type. citeturn18view0 |
|
||||||
|
| Conditional color | Rule-based page background color based on property conditions. | Requires content-edit or stronger permissions to configure; viewers without edit rights can still see the color. citeturn19view0 |
|
||||||
|
| Property types | Text, Number, Select, Status, Multi-select, Date, Formula, Relation, Rollup, Person, File, Checkbox, URL, Email, Phone, Created time, Created by, Last edited time, Last edited by, Button, ID, Place. | Official docs describe 22 property types and note a database limit of up to 500 properties to preserve performance and reliability. citeturn19view0 |
|
||||||
|
| Property behaviors | Date ranges, reminders, timezone/date-format control, select-option editing, multi-file fields, person tagging, direct property comments, show/hide by view. | Property comments appear in database pages; some property-type settings are type-specific, such as text wrapping or select-option order. citeturn19view0 |
|
||||||
|
| Relations | One-way or two-way relations, self-relations, relation display options, shown/hidden properties for related pages, optional one-page limit. | Relations connect pages across databases and can surface related-page properties inline in the relation field. citeturn20view0 |
|
||||||
|
| Rollups | Aggregation over related pages, including showing originals, unique values, counts, sums, and other calculations. | Rollups depend on an existing relation, then choose relation property, target property, aggregation, and formatting. citeturn20view0 |
|
||||||
|
| Formulas | Formula properties operate over database properties, built-ins, operators, dates, lists, and style/text functions. | Official docs describe properties, built-ins, operators, list functions such as `map`, `filter`, `find`, `some`, `every`, and style functions such as `style()` and `unstyle()`. citeturn16view4turn16view5turn37view1turn37view3turn37view4turn37view5 |
|
||||||
|
| Linked databases | Linked views of the same database can appear across multiple pages with different filters and sorts. | This is a canonical dashboard pattern in Notion. citeturn16view7turn18view0 |
|
||||||
|
| Database templates | New-page templates, repeating templates, nested templates with limits, edit/duplicate/delete template actions. | Repeating templates can recur daily, weekly, monthly, or yearly; nested recurring templates have depth and cadence limits. citeturn38search2turn38search0 |
|
||||||
|
| Database automations | Trigger-and-action automations on paid plans; Slack notifications on Free; variables, formulas, Gmail send, webhook send, property edits, page creation, notifications. | Automations cannot trigger other automations, but button actions can trigger database automations. Slack automations can only be edited by their creator. citeturn26search2turn27search10 |
|
||||||
|
| Charts | Bar, line, donut, number charts; configurable axes, visible/hidden groups, cumulative mode, legends, labels, style palettes, drilldowns. | Charts cannot edit database entries directly; large databases may update more slowly; chart groups/subgroups have published display limits. citeturn21view0 |
|
||||||
|
| Forms | Form builder with title, description, icon, cover, required questions, descriptions, list/dropdown presentation, response settings, shareable submission flow. | Form question names typically sync to database property names; form-view export is not supported. citeturn16view2turn28view1 |
|
||||||
|
| Granular row access | Database page-level access rules based on people or created-by properties. | Available on Business and Enterprise; applies across all views, including linked views. citeturn42view0 |
|
||||||
|
|
||||||
|
### Integrations, API surface, embeds, and external content
|
||||||
|
|
||||||
|
| Integration surface | Discoverable capabilities | Notes |
|
||||||
|
|---|---|---|
|
||||||
|
| Native/embed surface | Embeds from 1,900+ domains via Iframely; common examples include Framer, Figma, Loom, Miro, Typeform, Google Maps, GitHub Gist, Excalidraw, and many more. | If a source site blocks embeddability, Notion shows a `Failed to Load` error. Link previews and bookmarks are distinct surfaces in the embed family. citeturn41view0turn11search1 |
|
||||||
|
| Workspace connections | Members and owners can add connections in `Settings → Connections`; those connections can then be attached to particular pages/databases from the page `•••` menu. | Enterprise can restrict who can add and page-connect connections; page disconnection is exposed inline in the page menu. citeturn41view1 |
|
||||||
|
| Notion API | Official REST/developer platform exposing Authentication, Blocks, Pages, Databases, Data sources, Comments, Views, File uploads, Search, Users, and Custom emojis. | API is versioned by date and requires the `Notion-Version` header; latest public version in the cited documentation is `2026-03-11`. citeturn44search0turn44search4turn44search11 |
|
||||||
|
| API pagination and limits | Cursor-based pagination; search/list endpoints paginate; default list size is 10 in the introduction docs. | Request limits include a per-connection average of 3 requests/sec plus a per-workspace limit scaled to plan; 429 `rate_limited` and 529 `service_overload` responses should be retried/backed off. citeturn44search12turn44search0 |
|
||||||
|
| API webhooks | Connection webhooks deliver real-time HTTP POST events for pages, databases, data sources, comments, file uploads, and views. | Official webhook docs position this as an alternative to polling and document verification-token setup and event subscriptions. citeturn44search1turn44search3 |
|
||||||
|
| No-code and low-code automation | Zapier and Make are explicitly supported through Notion’s connection marketplace and webhook actions, alongside more general partner connections. | Notion’s own guides also recommend webhook actions with platforms like Zapier and Make. citeturn27search1turn27search2turn27search9turn27search8 |
|
||||||
|
| AI connectors | Cross-app search and answer retrieval from Slack, Google Drive, Jira, Gmail, Notion Mail, MS Teams, SharePoint/OneDrive, GitHub, Outlook, Notion Calendar, Linear, and Google Calendar. | Available from Business/Enterprise for third-party apps; Notion Mail and Notion Calendar connectors are available on all plans. Search surface appears in AI chat, sidebar AI, and sidebar Search. citeturn41view2 |
|
||||||
|
| MCP access | Notion MCP connects AI apps such as Claude, ChatGPT, and Cursor to read from and write to Notion. | This is distinct from AI connectors; MCP is documented as AI-agent-oriented workspace access. citeturn41view3 |
|
||||||
|
| Web clipper | Browser extension for Chrome and Safari on desktop saves web content into Notion. | Saved pages can populate databases and carry imported text/images from web pages. citeturn39search8turn33image1 |
|
||||||
|
|
||||||
|
### Import, export, backup, sites, and portability
|
||||||
|
|
||||||
|
| Portability capability | Discoverable behavior | Notes |
|
||||||
|
|---|---|---|
|
||||||
|
| Imports | Desktop and web only; direct file imports include TXT, Markdown, DOCX, CSV, HTML, PDF, ZIP, plus app imports such as Confluence, Asana, Evernote, and Trello. | The import UI tracks upload size, time, and status. Mobile import is explicitly unsupported in official help docs. citeturn28view0turn31view0 |
|
||||||
|
| Page/database export | PDF export from desktop and mobile; export modal allows page-format and inclusion choices. | PDF export can fail over to HTML; form view cannot be exported, and users are told to export the equivalent table instead. citeturn28view1turn16view2 |
|
||||||
|
| Full workspace export | HTML, Markdown, CSV for databases, uploaded files, and on Business/Enterprise also workspace-wide PDF export. | Whole-workspace export is desktop/web only and sent as an emailed link expiring after seven days; inaccessible/private pages not available to the exporter are excluded. citeturn28view2turn30view3 |
|
||||||
|
| Member export | Business and Enterprise can export workspace members as CSV with email, names, role, permission groups, and user ID. | Administrative portability feature for governance and audits. citeturn30view3 |
|
||||||
|
| Backups | Official help says Notion keeps per-minute backups of page content on its server; security docs also say automated backups of all customer/system data are enabled and monitored, with daily minimum backup cadence. | The two statements are not contradictory, but they describe different layers of backup policy; exact retention architecture is not fully specified publicly. citeturn28view2turn29view0 |
|
||||||
|
| Notion Sites | Pages can be published to the web; plans add custom site controls, branding removal, analytics integrations, and domains. | Free includes unlimited sites, one `notion.site` domain claim, and search indexing; Plus adds custom sites, and custom domains are an add-on with billing aligned to workspace billing cadence. citeturn40search7turn25search7turn25search10 |
|
||||||
|
|
||||||
|
## Collaboration, administration, security, and billing
|
||||||
|
|
||||||
|
### Collaboration, sharing, comments, mentions, and activity
|
||||||
|
|
||||||
|
Notion’s collaboration model combines page sharing, role-based permissions, live presence, comments, mentions, notifications, suggestions, and historical activity. Official docs state that unlimited people can edit the same page at once, with avatar presence tracking where collaborators are reading or editing. The page updates surface highlights additions in blue, removals in gray strikethrough, and can also show comments and revisions over time. citeturn22view1
|
||||||
|
|
||||||
|
The `Share` menu is the central collaboration control. From there, users can invite individuals or groups, share with a teamspace, copy links, publish to the web, assign access levels, and set general access to `Only people invited`, `Everyone at {workspace}`, or `Anyone on the web with link`. Public links can expire, and Enterprise workspaces can disable publishing/public links altogether. citeturn42view0
|
||||||
|
|
||||||
|
Permission levels are explicitly differentiated. Notion documents `Full access`, `Can edit`, `Can edit content` for databases, `Can create` for submit-only database contribution on Business/Enterprise, `Can comment`, and `Can view`. This means Notion’s access model is not just “viewer/editor,” but a layered mix of document and structured-data permissions. citeturn42view0
|
||||||
|
|
||||||
|
Comments can be attached to selected text, blocks, and properties; mentions can target people, pages, dates, and reminders; replies and mentions route into Inbox and optional email, push, desktop, and Slack notifications. Users can also configure page-specific notification scope, such as `All comments`, and desktop meeting-detection notifications can prompt AI Meeting Notes under certain conditions. citeturn11search0turn35view0turn36view1turn22view2
|
||||||
|
|
||||||
|
Page analytics extend activity visibility. Owners and editors can open `••• → Updates & analytics → Analytics` to see total and unique views over time as well as who created, edited, or viewed the page and when. Workspace-level settings can also toggle whether page view analytics are saved and displayed. citeturn40search1turn30view2turn30view3
|
||||||
|
|
||||||
|
### Teamspaces, members, guests, groups, and organization features
|
||||||
|
|
||||||
|
| Governance surface | Discoverable behavior | Notes |
|
||||||
|
|---|---|---|
|
||||||
|
| Workspace roles | Workspace owner, membership admin, member, guest; temporary members for consultants are also documented. | Temporary members do not consume a paid seat and can have expiration dates up to one year. citeturn25search0turn25search6 |
|
||||||
|
| Guests | Guests are external collaborators invited to specific pages. | Guest additions can be blocked by guest limits, workspace/teamspace settings, or allowed-domain policies; on some Enterprise configurations, inviting a guest can convert them to a member. citeturn42view0 |
|
||||||
|
| Groups | Notion supports permission groups for more granular sharing and teamspace membership. | Official group-management details are distributed across member and teamspace docs rather than a single product spec. citeturn25search11turn40search12 |
|
||||||
|
| Teamspaces | Dedicated collaborative spaces with open, closed, private, and default variants. | Default teamspaces auto-include all workspace members; private teamspaces are available on Business and Enterprise. citeturn40search2turn40search6turn40search8turn40search16 |
|
||||||
|
| Allowed email domains | Workspaces can set trusted/allowed domains so users with matching emails are prompted to join automatically. | On paid plans, domain-joined members affect billing. citeturn30view0turn30view1 |
|
||||||
|
| Workspace export and analytics | Owners can export all workspace content, export members CSV, and toggle page analytics visibility. | Many of these settings are unavailable on mobile and restricted to admins/owners or certain plans. citeturn22view4turn30view3 |
|
||||||
|
| Enterprise security controls | Disable publishing/forms, disable export, disable moving pages to other workspaces, restrict guest/member requests, configure restricted-member rules, choose trash-retention behavior. | These settings are surfaced in `Settings → Security` and are documented as Enterprise-only for the deeper controls. citeturn30view2 |
|
||||||
|
| Domain verification and management | Business adds domain verification; Enterprise adds domain management actions such as claim, transfer-request, or delete for workspaces on the verified domain. | These are plan-differentiating organization features, not just cosmetic settings. citeturn29view1 |
|
||||||
|
|
||||||
|
### Security, privacy, auditability, and billing
|
||||||
|
|
||||||
|
Security documentation states that customer data is encrypted at rest using AES-256 and in transit using TLS 1.2 or greater; Notion is hosted on AWS; critical-system logging is enabled; backups are monitored; threat modeling, code review, security scans, penetration testing, and bug bounty/responsible disclosure are part of the application security program. citeturn29view0
|
||||||
|
|
||||||
|
Business and Enterprise plans add federated identity and governance. SAML SSO is documented for Business and Enterprise, while SCIM user-and-group provisioning is Enterprise-only. Enterprise also adds audit log, advanced security and controls, zero data retention with LLM providers for Enterprise AI use, domain management, and security/compliance connections for SIEM and DLP workflows. citeturn22view5turn22view6turn29view1turn40search18
|
||||||
|
|
||||||
|
The audit log is broad. Official help categorizes events into page, workspace, workers, account, teamspace, form, and data-source events, including page edited, property edited, page viewed, page created, page suggestions created/accepted/rejected, comments read by external AI tools, page locked/unlocked, and other security-relevant events. citeturn16view9turn23search13
|
||||||
|
|
||||||
|
Billing is seat-based for members rather than guests. Official billing docs explain that workspace owners can track paid seats and member counts in `Settings → People`, and that adding or removing members changes usage against seats rather than charging every time a specific human identity changes. Public pricing also distinguishes Free, Plus, Business, and Enterprise plan bundles with increasingly advanced collaboration, charts, files, connections, AI, row-level permissions, private teamspaces, SSO, SCIM, audit log, and domain controls. citeturn25search2turn25search3turn29view1
|
||||||
|
|
||||||
|
A concise plan comparison focused on app capabilities is below.
|
||||||
|
|
||||||
|
| Plan | Key app capabilities publicly emphasized |
|
||||||
|
|---|---|
|
||||||
|
| Free | Basic forms, basic sites, Notion Calendar, Notion Mail sync, databases with subtasks/dependencies/custom properties, trial AI, one chart trial. citeturn29view1turn25search5 |
|
||||||
|
| Plus | Custom forms, custom sites, unlimited charts, unlimited collaborative blocks, unlimited uploads, basic connections. citeturn29view1 |
|
||||||
|
| Business | Agent, AI Meeting Notes, Enterprise Search beta, SAML SSO, granular database permissions, verified pages, private teamspaces, domain verification, premium connections. citeturn29view1 |
|
||||||
|
| Enterprise | Zero data retention with LLM providers, SCIM, advanced security controls, audit log, SIEM/DLP connections, domain management, additional connection options. citeturn29view1turn40search18 |
|
||||||
|
|
||||||
|
## UI UX specification
|
||||||
|
|
||||||
|
### Layout patterns, navigation surfaces, and responsive structure
|
||||||
|
|
||||||
|
Notion’s cross-platform layout uses a persistent hierarchical navigation model, but the container chrome changes by platform. Desktop and web center on a left sidebar with sections such as Favorites, Teamspaces, Shared, and Private, plus page nesting, drag-reordering, and sidebar collapse/resize. Database views expose tab-like view selectors and top-right settings affordances, while pages expose a title area, collaborator avatars, share control, overflow menu, and contextual block handles inside the content canvas. citeturn22view3turn30view5turn15search3turn18view0
|
||||||
|
|
||||||
|
Mobile keeps the same conceptual structure but compresses it into tap-first navigation. Official docs note that hover-revealed controls disappear, columns collapse into one column, and editing controls move to a toolbar near the keyboard. The mobile shell also exposes `+` and `•••` icons persistently rather than relying on cursor hover. citeturn31view0turn11search0
|
||||||
|
|
||||||
|
The public screenshots below illustrate the consistent information architecture across desktop and mobile, the database-centric learning flow, and the compressed mobile database UI.
|
||||||
|
|
||||||
|
iturn33image0turn33image2turn33image1turn33image3
|
||||||
|
|
||||||
|
On desktop specifically, Notion adds tabbed browsing, new windows, tab hover previews, and a global Command Search surface accessible even outside the foreground app. Official docs describe smooth tab switching, optional “open search when creating a new tab,” and customizable keyboard shortcuts for global command search, along with menu-bar/task-bar presence and optional open-at-login behavior. citeturn31view1turn34view0
|
||||||
|
|
||||||
|
The overall navigation flow can be reduced to a small set of repeated patterns.
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
flowchart TB
|
||||||
|
Launch --> Sidebar
|
||||||
|
Sidebar --> ExistingPage
|
||||||
|
Sidebar --> NewPage
|
||||||
|
ExistingPage --> PageHeader
|
||||||
|
PageHeader --> ShareMenu
|
||||||
|
PageHeader --> OverflowMenu
|
||||||
|
ExistingPage --> ContentCanvas
|
||||||
|
ContentCanvas --> SlashMenu
|
||||||
|
ContentCanvas --> BlockHandleMenu
|
||||||
|
ExistingPage --> InlineDatabase
|
||||||
|
InlineDatabase --> ViewTabs
|
||||||
|
ViewTabs --> PeekOpen
|
||||||
|
PeekOpen --> SidePeek
|
||||||
|
PeekOpen --> CenterPeek
|
||||||
|
PeekOpen --> FullPage
|
||||||
|
Sidebar --> Search
|
||||||
|
Search --> JumpToPage
|
||||||
|
Search --> NewTab
|
||||||
|
Search --> AIChat
|
||||||
|
```
|
||||||
|
|
||||||
|
### Component-level UI specification
|
||||||
|
|
||||||
|
The table below catalogs the major discoverable UI elements, their states, and their main behaviors. Where a state is not documented in public materials, it is marked **unspecified**.
|
||||||
|
|
||||||
|
| Component | Principal states | Main interactions | Platform notes |
|
||||||
|
|---|---|---|---|
|
||||||
|
| Sidebar | Expanded, collapsed, resized, section-collapsed, drag-reordered. | Resize by dragging edge; collapse with `<<`/`>>`; drag pages to reorder/nest; hover reveals `+` and `•••` on pages and teamspaces. citeturn22view3turn15search0 | Sections include Favorites, Teamspaces, Shared, Private; views for full-page databases appear nested with a dot marker. citeturn30view5turn18view0 |
|
||||||
|
| Page header | Normal, collaborative-presence, published, archived, analytics-enabled. | Title editing, icon/cover set, share, `•••`, collaborator avatars, updates/history access. citeturn15search3turn42view0turn23search8turn23search12 | Archived pages surface a yellow banner; official archive-state spec is page-level. citeturn23search12 |
|
||||||
|
| Block handle region | Resting, hover-revealed, selected, drag-active. | `+` opens block inserter; `⋮⋮` opens block actions or allows drag; blue guides appear on drag target placement. citeturn11search0 | Mobile replaces hover with persistent tap-first controls. citeturn31view0 |
|
||||||
|
| Slash menu | Closed, open, filtered by query, dismissed. | Type `/` then block or action name; can add blocks, transform blocks, color text, invoke embeds, buttons, TOC, math, and more. `Esc` dismisses. citeturn11search0turn35view0 | Official mobile docs say there are no slash commands on mobile editing; mobile uses the editing toolbar instead. citeturn11search0turn31view0 |
|
||||||
|
| Database toolbar | Viewing, filters open, sorts open, groups open, properties open, layout open. | Create/switch views, toggle property visibility, filter/sort/group, set open mode, copy link to view, search, freeze columns. citeturn18view0 | Different layouts default to different page-open modes: side peek for table/board/list/timeline, center peek for gallery/calendar. citeturn17view0turn17view2 |
|
||||||
|
| View tabs | Default, reordered, icon-only, text-only, icon+text. | Drag to reorder; change personal display style. citeturn18view0 | Personal preference only; not global for all users. citeturn18view0 |
|
||||||
|
| Peek surfaces | Side peek, center peek, full page. | Open database rows/cards/pages into chosen presentation. citeturn18view0 | Systematically used to preserve context while editing structured items. |
|
||||||
|
| Share panel | Invite, general access, publish, role-change, link-expiry, remove access. | Invite members/groups/guests, set access levels, publish to web, create expiring public links, stop sharing. citeturn42view0 | Database pages add row-level/page-level access rules in Business/Enterprise. citeturn42view0 |
|
||||||
|
| Search and Command Search | Inline quick find, global command search, AI search augmentation. | `cmd/ctrl + P` or `K`, jump to recent page, create page, start AI chat, search from menu bar/task bar. citeturn34view0turn31view1turn41view2 | Desktop-only global command-search shell is documented; full equivalent is unspecified for web. |
|
||||||
|
| Inbox and notifications | Badge idle, unread badge, inbox list, email/push/desktop delivery. | Mentions, replies, reminders, person-property assignments, page updates. citeturn36view1turn22view2 | Mobile settings route through `Settings → My notifications`; desktop includes badge icons and meeting-detection notifications. citeturn24search5turn24search9 |
|
||||||
|
| Comments and discussions | Inline visible, minimal inline count, property comment, page discussion. | Add comment to text with selection toolbar or shortcut; property comments in database pages; page discussions configurable in page customization. citeturn11search0turn19view0turn24search7 | Public docs do not publish a complete statechart for moderation or resolution; partially unspecified. |
|
||||||
|
| Forms | Builder, question-hover menu, required-on/off, description-on/off, shareable response mode. | Add title/description/icon/cover, add questions, set required, choose list/dropdown for multi-choice, map to database properties. citeturn16view2 | Exporting the form view itself is unsupported. citeturn16view2turn28view1 |
|
||||||
|
| Settings surfaces | Workspace-general, account, preferences, notifications, security, connections, AI. | Access from workspace switcher down-arrow or settings entry points; configure appearance, language, notifications, connections, domains, exports, billing, and security. citeturn36view0turn24search5turn22view4turn41view1turn41view2 | Many advanced workspace settings do not appear in mobile. citeturn22view4turn31view0 |
|
||||||
|
|
||||||
|
### Microinteractions, discoverability, empty states, and error states
|
||||||
|
|
||||||
|
Notion’s discoverability strategy is heavily contextual rather than explicit. New users encounter a blank page plus a slash menu, a left-margin `+`, and block handles; when they create databases, they encounter view tabs, a settings icon, page peeks, and the `New` button/dropdown for templates. Database views can be linked into pages, and full-page database views appear nested in the sidebar, reinforcing navigation discoverability through repetition. citeturn11search0turn15search2turn18view0turn16view7
|
||||||
|
|
||||||
|
Official docs also expose several “empty-state” launch patterns. Creating a new page from the sidebar opens a preview mode where users can start typing before deciding final placement. The template gallery is explicitly positioned as a starting point for structure when users are unsure how to begin. Import and chart flows also present staged creation prompts rather than blank-screen dead ends. Public docs do **not** enumerate every empty state across the product, so a complete empty-state inventory is **unspecified**. citeturn15search0turn38search17turn28view0turn21view0
|
||||||
|
|
||||||
|
The most visible microinteractions documented publicly are hover-revealed controls, drag-and-drop blue guides, smooth tab switching, tab hover preview on desktop, live collaborative cursors/presence, chart hover labels, comment/revision highlighting in updates, and notification badges. Official docs describe these behaviors but do **not** publish animation durations, easing curves, or haptic/motion token values; those remain **unspecified**. citeturn11search0turn22view1turn31view1turn21view0
|
||||||
|
|
||||||
|
Notion’s documented error states are functional rather than theatrical. Examples include `Failed to Load` for blocked embeds, exclamation-mark failure state and auto-pause for failed webhook automations, property-count-limit errors at 500 properties, unsupported export from form view, unsupported import on mobile, and archive-state warning banners. The public help center does not expose a complete platform-wide error taxonomy, so an exhaustive error catalog is **unspecified**. citeturn41view0turn27search8turn19view0turn16view2turn31view0turn23search12
|
||||||
|
|
||||||
|
### Keyboard shortcuts and command surfaces
|
||||||
|
|
||||||
|
Notion is unusually keyboard-forward. Official docs say shortcuts cover navigation, creation, styling, block movement, slash commands, mentions, page linking, toggles, comments, zoom, table fills, and block transformations. The international keyboard story is still incomplete: Notion’s shortcut documentation explicitly says the published instructions are for English/QWERTY keyboards and that internationalization is on the roadmap. citeturn34view0turn35view0
|
||||||
|
|
||||||
|
A concise high-value shortcut catalog is below.
|
||||||
|
|
||||||
|
| Category | Shortcut examples | Effect |
|
||||||
|
|---|---|---|
|
||||||
|
| Search and navigation | `cmd/ctrl + F`, `cmd/ctrl + P` or `K`, `cmd/ctrl + [` and `]`, `cmd/ctrl + L` | Search within page, quick find / jump to recent page, back/forward, copy page URL. citeturn34view0 |
|
||||||
|
| Desktop shell | `cmd/ctrl + N`, `cmd/ctrl + shift + N`, `cmd/ctrl + T`, `cmd/ctrl + click`, `option + shift + click` | New page, new window, new tab, open link in new tab, open page in new window. citeturn34view0 |
|
||||||
|
| Theme | `cmd/ctrl + shift + L` | Toggle dark/light mode. citeturn24search0turn34view0 |
|
||||||
|
| Commenting and formatting | `cmd/ctrl + shift + M`, `B`, `I`, `U`, `shift + S`, `E`, `K` | Create comment, bold, italic, underline, strikethrough, inline code, add link. citeturn34view0 |
|
||||||
|
| Block manipulation | `Esc`, `cmd/ctrl + /`, `cmd/ctrl + D`, `cmd/ctrl + shift + arrows`, `cmd/ctrl + enter` | Select block, edit/change selected blocks, duplicate, move block, modify current block. citeturn35view0 |
|
||||||
|
| Hierarchy and nesting | `Tab`, `shift + Tab`, `cmd/ctrl + shift + U` | Nest, un-nest, go up one level in page hierarchy. citeturn34view0turn35view0 |
|
||||||
|
| Toggle control | `cmd/ctrl + option/alt + T` | Expand or close all toggles in a toggle list. citeturn35view0 |
|
||||||
|
| Database peek navigation | Mac `ctrl + shift + K/J`, Windows `ctrl + K/J` | Previous/next database page while in peek view. citeturn34view0 |
|
||||||
|
| Slash, mention, page-linking | `/`, `@`, `[[`, `+` | Block insertion/transformation, mentions/reminders, link/create pages, page creation-first alternate linking flow. citeturn35view0 |
|
||||||
|
|
||||||
|
## Platform differences, performance, accessibility, localization, and unspecified details
|
||||||
|
|
||||||
|
### Platform comparison
|
||||||
|
|
||||||
|
| Surface | Desktop app | Web app | Mobile app |
|
||||||
|
|---|---|---|---|
|
||||||
|
| Primary strengths | Distraction-free shell, tabs, windows, push notifications, Command Search outside foreground app. citeturn31view1turn34view0 | Broad access on supported browsers; deepest parity with desktop for general editing and admin tasks. citeturn39search2turn39search4 | Tap-first editing, reading, comments, AI access on the go, AI widget/shortcuts. citeturn31view0 |
|
||||||
|
| Interaction model | Hover-rich, keyboard-heavy, drag-heavy. citeturn11search0turn31view1 | Similar to desktop, browser-contained. citeturn39search2 | No hover; `+` and `•••` replace hover discoverability; columns collapse. citeturn31view0 |
|
||||||
|
| Tabs and windows | Yes, including new tab, new window, tab preview. citeturn31view1turn34view0 | Browser tabs/windows, but official “Notion tab” behaviors are desktop-specific. | Native app tabs/windows are **unspecified** in public docs. |
|
||||||
|
| Imports | Supported. citeturn28view0 | Supported. citeturn28view0 | Unsupported. citeturn31view0 |
|
||||||
|
| Admin/billing/security settings | Supported. citeturn22view4turn36view0 | Supported. citeturn22view4turn36view0 | Many are explicitly unavailable. citeturn31view0 |
|
||||||
|
| Theme/language | System/light/dark; language selector in Preferences. citeturn24search0turn36view2 | Same general settings surface. citeturn24search0turn36view2 | Appearance setting exists; language follows system ranking. citeturn24search0turn36view2 |
|
||||||
|
| Browser / runtime support | Native Mac/Windows app. citeturn31view1 | Chrome supported across last eight extended stable releases; Firefox, Safari, and Edge for last two major releases; Internet Explorer unsupported. citeturn39search4turn39search2 | iOS and Android native apps. citeturn31view0turn14search0turn14search1 |
|
||||||
|
|
||||||
|
### Performance and offline behavior
|
||||||
|
|
||||||
|
Public official performance documentation is selective rather than exhaustive. Notion has publicly documented Android launch-performance work and stated that the Android app launches more than twice as quickly as it did at the start of 2023. Official chart-view documentation also warns that charts in large databases may update more slowly, and database-property documentation explains that the 500-property ceiling exists to keep databases fast and reliable. citeturn14search11turn21view0turn19view0
|
||||||
|
|
||||||
|
A fully current, platform-by-platform offline specification is **not completely published** in today’s help-center materials. Public desktop and mobile help pages focus more on download, editing differences, and platform restrictions than on a full sync/conflict matrix. Accordingly, the safest conclusion is that offline behavior exists in some form for installed apps and cached content, but the exact rules for every block type, database interaction, view, and conflict condition are **partially unspecified in public documentation**. citeturn31view0turn31view1
|
||||||
|
|
||||||
|
### Accessibility and localization
|
||||||
|
|
||||||
|
Officially documented accessibility-related capabilities include dark mode, extensive keyboard shortcuts, Markdown shortcuts, interface-language selection, week-start preferences, RTL interface mirroring for Arabic and Hebrew, auto-detected text direction in most text blocks except simple tables, manual block-level text-direction controls, and an “always show direction controls” preference. citeturn24search0turn34view0turn36view2
|
||||||
|
|
||||||
|
What official docs do **not** publish is equally important: there is no public ARIA role inventory, no official WCAG conformance matrix, no keyboard focus-order specification, no contrast-ratio token sheet, and no screen-reader support matrix broken down by component. Those details are therefore **unspecified** in official public sources. citeturn24search4turn36view2
|
||||||
|
|
||||||
|
Unofficial accessibility analyses fill part of that gap, but should be treated as supplementary rather than normative. Independent public reviews from Pratt and Navya Thakkar’s assessment both reported issues in desktop flows involving contrast, alt text, and keyboard tabbing. That does not negate Notion’s documented keyboard and RTL features; it indicates the public accessibility picture is mixed and still incomplete. citeturn32search15turn12search10turn34view0turn36view2
|
||||||
|
|
||||||
|
Localization support is broad. The public language list includes English, English (GB), Japanese, French, German, Spanish (Spain), Spanish (Latin America), Portuguese (Brazil), Chinese simplified and traditional, Dutch, Norwegian, Swedish, Danish, Finnish, Korean, Vietnamese, Thai, Bahasa Indonesia, Arabic, Hebrew, and Italian. Help-center footers and download pages also visibly surface a similar multilingual set across product pages. citeturn36view2turn14search10turn18view0
|
||||||
|
|
||||||
|
### Explicitly unspecified or only partially discoverable details
|
||||||
|
|
||||||
|
The following details were **not** fully discoverable in current public official sources and should be treated as unspecified unless verified directly inside a live product build or private enterprise documentation:
|
||||||
|
|
||||||
|
The complete ARIA map and screen-reader announcement behavior for each component; animation timing tokens and easing curves; a full catalog of loading, error, and empty states; a fully up-to-date offline-sync matrix for web, desktop, and mobile across all block and database operations; exact parity tables for every minor mobile interaction; and a complete public design-system inventory for every primitive component, token, and spacing rule. This is not a weakness in the research process so much as a boundary of what Notion publishes openly today. citeturn24search4turn31view0turn31view1turn12search10turn32search15
|
||||||
|
|
||||||
|
Even with those gaps, the overall picture is clear. Notion’s public product surface is unusually deep: block-based authoring, page-centric knowledge management, database-driven workflows, rich permissions, multi-surface collaboration, strong customization, a serious developer platform, expanding AI access patterns, and a UI architecture that scales from plain-text note-taking to enterprise knowledge operations. The remaining uncertainty is concentrated not in major feature existence, but in the undocumented microscopic details of implementation. citeturn11search0turn18view0turn42view0turn41view1turn29view1
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
<svg width="206" height="231" viewBox="0 0 206 231" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M143.143 84C143.143 96.1503 133.293 106 121.143 106C108.992 106 99.1426 96.1503 99.1426 84C99.1426 71.8497 108.992 62 121.143 62C133.293 62 143.143 71.8497 143.143 84Z" fill="#FFC131"/>
|
||||||
|
<ellipse cx="84.1426" cy="147" rx="22" ry="22" transform="rotate(180 84.1426 147)" fill="#24C8DB"/>
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M166.738 154.548C157.86 160.286 148.023 164.269 137.757 166.341C139.858 160.282 141 153.774 141 147C141 144.543 140.85 142.121 140.558 139.743C144.975 138.204 149.215 136.139 153.183 133.575C162.73 127.404 170.292 118.608 174.961 108.244C179.63 97.8797 181.207 86.3876 179.502 75.1487C177.798 63.9098 172.884 53.4021 165.352 44.8883C157.82 36.3744 147.99 30.2165 137.042 27.1546C126.095 24.0926 114.496 24.2568 103.64 27.6274C92.7839 30.998 83.1319 37.4317 75.8437 46.1553C74.9102 47.2727 74.0206 48.4216 73.176 49.5993C61.9292 50.8488 51.0363 54.0318 40.9629 58.9556C44.2417 48.4586 49.5653 38.6591 56.679 30.1442C67.0505 17.7298 80.7861 8.57426 96.2354 3.77762C111.685 -1.01901 128.19 -1.25267 143.769 3.10474C159.348 7.46215 173.337 16.2252 184.056 28.3411C194.775 40.457 201.767 55.4101 204.193 71.404C206.619 87.3978 204.374 103.752 197.73 118.501C191.086 133.25 180.324 145.767 166.738 154.548ZM41.9631 74.275L62.5557 76.8042C63.0459 72.813 63.9401 68.9018 65.2138 65.1274C57.0465 67.0016 49.2088 70.087 41.9631 74.275Z" fill="#FFC131"/>
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M38.4045 76.4519C47.3493 70.6709 57.2677 66.6712 67.6171 64.6132C65.2774 70.9669 64 77.8343 64 85.0001C64 87.1434 64.1143 89.26 64.3371 91.3442C60.0093 92.8732 55.8533 94.9092 51.9599 97.4256C42.4128 103.596 34.8505 112.392 30.1816 122.756C25.5126 133.12 23.9357 144.612 25.6403 155.851C27.3449 167.09 32.2584 177.598 39.7906 186.112C47.3227 194.626 57.153 200.784 68.1003 203.846C79.0476 206.907 90.6462 206.743 101.502 203.373C112.359 200.002 122.011 193.568 129.299 184.845C130.237 183.722 131.131 182.567 131.979 181.383C143.235 180.114 154.132 176.91 164.205 171.962C160.929 182.49 155.596 192.319 148.464 200.856C138.092 213.27 124.357 222.426 108.907 227.222C93.458 232.019 76.9524 232.253 61.3736 227.895C45.7948 223.538 31.8055 214.775 21.0867 202.659C10.3679 190.543 3.37557 175.59 0.949823 159.596C-1.47592 143.602 0.768139 127.248 7.41237 112.499C14.0566 97.7497 24.8183 85.2327 38.4045 76.4519ZM163.062 156.711L163.062 156.711C162.954 156.773 162.846 156.835 162.738 156.897C162.846 156.835 162.954 156.773 163.062 156.711Z" fill="#24C8DB"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.5 KiB |
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
|
||||||
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 3.4 KiB |
|
After Width: | Height: | Size: 6.8 KiB |
|
After Width: | Height: | Size: 974 B |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 3.8 KiB |
|
After Width: | Height: | Size: 3.9 KiB |
|
After Width: | Height: | Size: 7.6 KiB |
|
After Width: | Height: | Size: 903 B |
|
After Width: | Height: | Size: 8.4 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 85 KiB |
|
After Width: | Height: | Size: 14 KiB |
@@ -0,0 +1,55 @@
|
|||||||
|
import Database from "@tauri-apps/plugin-sql";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Thin typed data layer over the Tauri SQL plugin (SQLite).
|
||||||
|
* All persistence goes through here — components never touch SQL directly.
|
||||||
|
*/
|
||||||
|
|
||||||
|
let db: Database | null = null;
|
||||||
|
|
||||||
|
export async function getDb(): Promise<Database> {
|
||||||
|
if (!db) {
|
||||||
|
// Migrations (src-tauri/migrations) run automatically on first load.
|
||||||
|
db = await Database.load("sqlite:workspace.db");
|
||||||
|
}
|
||||||
|
return db;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface WorkspaceMeta {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
theme: "light" | "dark" | "system";
|
||||||
|
accent: string;
|
||||||
|
onboarded: number;
|
||||||
|
last_page_id: string | null;
|
||||||
|
settings: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getWorkspaceMeta(): Promise<WorkspaceMeta> {
|
||||||
|
const d = await getDb();
|
||||||
|
const rows = await d.select<WorkspaceMeta[]>(
|
||||||
|
"SELECT * FROM workspace_meta WHERE id = 1",
|
||||||
|
);
|
||||||
|
return rows[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function updateWorkspaceMeta(
|
||||||
|
patch: Partial<Omit<WorkspaceMeta, "id">>,
|
||||||
|
): Promise<void> {
|
||||||
|
const d = await getDb();
|
||||||
|
const keys = Object.keys(patch) as (keyof typeof patch)[];
|
||||||
|
if (keys.length === 0) return;
|
||||||
|
const sets = keys.map((k, i) => `${k} = $${i + 1}`).join(", ");
|
||||||
|
await d.execute(
|
||||||
|
`UPDATE workspace_meta SET ${sets} WHERE id = 1`,
|
||||||
|
keys.map((k) => patch[k]),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function newId(): string {
|
||||||
|
return crypto.randomUUID();
|
||||||
|
}
|
||||||
|
|
||||||
|
export function now(): number {
|
||||||
|
return Date.now();
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
import React from "react";
|
||||||
|
import ReactDOM from "react-dom/client";
|
||||||
|
import App from "./App";
|
||||||
|
import "@fontsource-variable/inter";
|
||||||
|
import "./styles.css";
|
||||||
|
|
||||||
|
ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
|
||||||
|
<React.StrictMode>
|
||||||
|
<App />
|
||||||
|
</React.StrictMode>,
|
||||||
|
);
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import { create } from "zustand";
|
||||||
|
|
||||||
|
export type Theme = "light" | "dark" | "system";
|
||||||
|
|
||||||
|
interface UiState {
|
||||||
|
theme: Theme;
|
||||||
|
sidebarWidth: number;
|
||||||
|
sidebarCollapsed: boolean;
|
||||||
|
setTheme: (t: Theme) => void;
|
||||||
|
setSidebarWidth: (w: number) => void;
|
||||||
|
toggleSidebar: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useUi = create<UiState>((set) => ({
|
||||||
|
theme: "system",
|
||||||
|
sidebarWidth: 240,
|
||||||
|
sidebarCollapsed: false,
|
||||||
|
setTheme: (theme) => set({ theme }),
|
||||||
|
setSidebarWidth: (sidebarWidth) => set({ sidebarWidth }),
|
||||||
|
toggleSidebar: () =>
|
||||||
|
set((s) => ({ sidebarCollapsed: !s.sidebarCollapsed })),
|
||||||
|
}));
|
||||||
|
|
||||||
|
/** Apply the theme by toggling the `dark` class on <html>. */
|
||||||
|
export function applyTheme(theme: Theme) {
|
||||||
|
const prefersDark = window.matchMedia(
|
||||||
|
"(prefers-color-scheme: dark)",
|
||||||
|
).matches;
|
||||||
|
const dark = theme === "dark" || (theme === "system" && prefersDark);
|
||||||
|
document.documentElement.classList.toggle("dark", dark);
|
||||||
|
}
|
||||||
@@ -0,0 +1,114 @@
|
|||||||
|
@import "tailwindcss";
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------------
|
||||||
|
Notara design tokens — matched to Notion's light/dark palette (PLAN.md
|
||||||
|
"Visual Fidelity"). All UI colors must come from these variables.
|
||||||
|
--------------------------------------------------------------------------- */
|
||||||
|
:root {
|
||||||
|
/* surfaces */
|
||||||
|
--bg: #ffffff;
|
||||||
|
--bg-sidebar: #f7f7f5;
|
||||||
|
--bg-hover: rgba(55, 53, 47, 0.06);
|
||||||
|
--bg-active: rgba(55, 53, 47, 0.1);
|
||||||
|
--bg-modal: #ffffff;
|
||||||
|
|
||||||
|
/* text */
|
||||||
|
--text: #37352f;
|
||||||
|
--text-secondary: rgba(55, 53, 47, 0.65);
|
||||||
|
--text-tertiary: rgba(55, 53, 47, 0.45);
|
||||||
|
|
||||||
|
/* lines & accents */
|
||||||
|
--border: rgba(55, 53, 47, 0.09);
|
||||||
|
--divider: rgba(55, 53, 47, 0.06);
|
||||||
|
--accent: #2383e2;
|
||||||
|
--accent-bg: rgba(35, 131, 226, 0.14);
|
||||||
|
--selection: rgba(35, 131, 226, 0.28);
|
||||||
|
--danger: #eb5757;
|
||||||
|
|
||||||
|
/* shadows */
|
||||||
|
--shadow-popover: rgba(15, 15, 15, 0.05) 0px 0px 0px 1px,
|
||||||
|
rgba(15, 15, 15, 0.1) 0px 3px 6px, rgba(15, 15, 15, 0.2) 0px 9px 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark {
|
||||||
|
--bg: #191919;
|
||||||
|
--bg-sidebar: #202020;
|
||||||
|
--bg-hover: rgba(255, 255, 255, 0.055);
|
||||||
|
--bg-active: rgba(255, 255, 255, 0.09);
|
||||||
|
--bg-modal: #252525;
|
||||||
|
|
||||||
|
--text: rgba(255, 255, 255, 0.81);
|
||||||
|
--text-secondary: rgba(255, 255, 255, 0.46);
|
||||||
|
--text-tertiary: rgba(255, 255, 255, 0.3);
|
||||||
|
|
||||||
|
--border: rgba(255, 255, 255, 0.094);
|
||||||
|
--divider: rgba(255, 255, 255, 0.06);
|
||||||
|
--accent: #2383e2;
|
||||||
|
--accent-bg: rgba(35, 131, 226, 0.2);
|
||||||
|
--selection: rgba(35, 131, 226, 0.35);
|
||||||
|
--danger: #eb5757;
|
||||||
|
|
||||||
|
--shadow-popover: rgba(15, 15, 15, 0.2) 0px 0px 0px 1px,
|
||||||
|
rgba(15, 15, 15, 0.4) 0px 3px 6px, rgba(15, 15, 15, 0.6) 0px 9px 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@theme inline {
|
||||||
|
--color-bg: var(--bg);
|
||||||
|
--color-bg-sidebar: var(--bg-sidebar);
|
||||||
|
--color-bg-hover: var(--bg-hover);
|
||||||
|
--color-bg-active: var(--bg-active);
|
||||||
|
--color-bg-modal: var(--bg-modal);
|
||||||
|
--color-text: var(--text);
|
||||||
|
--color-text-secondary: var(--text-secondary);
|
||||||
|
--color-text-tertiary: var(--text-tertiary);
|
||||||
|
--color-border: var(--border);
|
||||||
|
--color-divider: var(--divider);
|
||||||
|
--color-accent: var(--accent);
|
||||||
|
--color-accent-bg: var(--accent-bg);
|
||||||
|
--color-danger: var(--danger);
|
||||||
|
--font-sans: "Inter Variable", ui-sans-serif, -apple-system,
|
||||||
|
BlinkMacSystemFont, "Segoe UI Variable Display", "Segoe UI", Helvetica,
|
||||||
|
"Apple Color Emoji", Arial, sans-serif, "Segoe UI Emoji", "Segoe UI Symbol";
|
||||||
|
}
|
||||||
|
|
||||||
|
html,
|
||||||
|
body,
|
||||||
|
#root {
|
||||||
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: var(--font-sans);
|
||||||
|
background: var(--bg);
|
||||||
|
color: var(--text);
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 1.5;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
user-select: none; /* app chrome is not selectable; editor opts back in */
|
||||||
|
}
|
||||||
|
|
||||||
|
::selection {
|
||||||
|
background: var(--selection);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Notion-style thin scrollbars */
|
||||||
|
*::-webkit-scrollbar {
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
}
|
||||||
|
*::-webkit-scrollbar-thumb {
|
||||||
|
background: rgba(55, 53, 47, 0.2);
|
||||||
|
border-radius: 5px;
|
||||||
|
border: 2px solid transparent;
|
||||||
|
background-clip: content-box;
|
||||||
|
}
|
||||||
|
.dark *::-webkit-scrollbar-thumb {
|
||||||
|
background: rgba(255, 255, 255, 0.18);
|
||||||
|
background-clip: content-box;
|
||||||
|
border: 2px solid transparent;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
*::-webkit-scrollbar-track {
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
/// <reference types="vite/client" />
|
||||||