A Notion-like note-taking app with rich-text editing, page hierarchy, and drag-and-drop. Built with Next.js 16 + Plate.js v52 + Drizzle + BetterAuth.
Status: Active development. Phase A (foundation), Phase B (features), and Phase C (quality & polish) are implemented; QA blockers are being worked on in
fix/qa-blockersbranch.
| Layer | Technology |
|---|---|
| Framework | Next.js 16 (App Router, Turbopack) |
| Language | TypeScript (strict) |
| UI | Tailwind CSS v4 + shadcn/ui + Radix UI |
| Editor | Plate.js (platejs) v52 |
| State | Redux Toolkit + @laststance/redux-storage-middleware |
| Database | PostgreSQL 16 (Docker) + Drizzle ORM |
| Auth | BetterAuth (email/password) |
| Validation | Zod |
| Pattern Match | ts-pattern |
| DnD | @dnd-kit/react |
| Test | Vitest (unit/browser) + Playwright (E2E) |
pnpm install
cp .env.example .env.local # then fill in BETTER_AUTH_SECRET etc.
pnpm db:up # start Postgres in Docker
pnpm db:push # push Drizzle schema
pnpm db:seed # optional: seed test data
pnpm dev # http://localhost:3737| Command | Purpose |
|---|---|
pnpm dev |
Dev server with Turbopack (port 3737) |
pnpm lint |
ESLint with zero warnings allowed |
pnpm typecheck |
TypeScript strict check |
pnpm build |
Production build |
pnpm test |
Vitest unit tests |
pnpm test:browser |
Vitest browser tests |
pnpm e2e |
Playwright E2E tests |
pnpm db:up |
Start Postgres (Docker Compose) |
pnpm db:down |
Stop Postgres |
pnpm db:push |
Push Drizzle schema to DB |
pnpm db:seed |
Seed test data |
pnpm db:studio |
Drizzle Studio GUI |
Server Components → Drizzle ORM → PostgreSQL
Client Components → Redux (useAppSelector/useAppDispatch) → API Routes → Drizzle → PostgreSQL
→ localStorage (via redux-storage-middleware for hydration)
app/ Next.js App Router pages & API routes
api/ REST API endpoints
auth/ Auth pages (sign-in, sign-up)
workspace/ Main workspace (sidebar + editor)
components/
editor/ Plate.js editor & plugins
sidebar/ Sidebar navigation (page tree, user menu)
workspace/ Layout shell
search/ Command palette (Cmd+K)
ui/ shadcn/ui primitives
store/
slices/ Redux slices
hooks.ts Typed useAppSelector/useAppDispatch
db/
schema.ts Drizzle schema
index.ts DB connection
seed.ts Seed script
lib/ Shared utilities (auth, utils)
types/ TypeScript type definitions
Uses useSyncExternalStore for concurrent-safe Redux hydration from localStorage. The redux-storage-middleware persists selected Redux slices and restores them on app load without hydration mismatches.
- Content-first — UI recedes, content shines (Notion-inspired)
- Warm minimalism — Clean but not cold; subtle warmth through OKLCH color tokens
- Always a way back — Every hidden panel has a visible affordance to restore it
- Consistent rhythm — 4/8px grid, spacing scale for visual harmony
- Accessible by default — WCAG 2.2 AA, keyboard navigation, screen reader support
Work follows Plan files in order:
| File | Scope |
|---|---|
Plan-Phase-A.md |
Foundation (Infra, DB, Auth, State) |
Plan-Phase-B.md |
Features (UI, API, Editor, Search, DnD) |
Plan-Phase-C.md |
Quality & Polish (Seed, Test, E2E, Landing) |
MIT — see LICENSE.