A full-stack collaborative workspace built with modern web technologies. Real-time sync, authentication, file storage, and production-ready patterns.
| Layer | Technology | Purpose |
|---|---|---|
| Framework | Next.js 13 (App Router) | SSR, routing, API routes |
| UI | React 18, Tailwind, Radix UI | Components, styling, accessibility |
| Editor | BlockNote | Rich block-based editing |
| Backend | Convex | Real-time DB, serverless functions |
| Auth | Clerk | Auth + Convex integration |
| Files | EdgeStore | Cover images, inline uploads |
| State | Zustand | Client-side state (search, modals) |
| Directory | Purpose |
|---|---|
app/(marketing)/ |
Landing page (public) |
app/(main)/ |
Authenticated app (sidebar, documents) |
app/(public)/ |
Published document preview |
app/api/edgestore/ |
EdgeStore Next.js handler |
convex/ |
Schema, mutations, queries |
components/ |
Shared UI, editor, toolbar, modals |
hooks/ |
Custom hooks (search, settings, cover image) |
- Document CRUD: Convex mutations (
create,update,archive,restore,remove) with auth checks - Real-time: Convex
useQuery/useMutationfor live updates - Hierarchy:
parentDocument+by_user_parentindex for nested documents - Publish:
isPublishedflag allows public read viagetByIdwithout auth
- Clerk handles sign-in/sign-up
ConvexProviderWithClerkpasses JWT to ConvexuseConvexAuth()in main layout redirects unauthenticated users to/- All Convex handlers validate
ctx.auth.getUserIdentity()anduserId
Core
- Real-time editing
- Infinite document nesting
- Trash with restore
UX
- Command palette (Cmd+K)
- Collapsible sidebar
- Light/dark mode
- Mobile responsive
Content
- BlockNote editor
- Emoji icons
- Cover images
- Publish to web
Infrastructure
- Type-safe Convex API
- EdgeStore file handling
- Zod validation
Prerequisites: Node 18.x.x
Clone and install
git clone https://github.com/AntonioErdeljac/notion-clone-tutorial.git
cd notion-clone-tutorial
npm iEnvironment variables
Create .env.local with:
CONVEX_DEPLOYMENT=
NEXT_PUBLIC_CONVEX_URL=
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=
CLERK_SECRET_KEY=
EDGE_STORE_ACCESS_KEY=
EDGE_STORE_SECRET_KEY=
Run Convex
npx convex devStart the app
npm run dev
