Skip to content

arkcode369/notion-clone

Repository files navigation

Jotion - A Notion Clone

A full-stack Notion clone built with Next.js 14, featuring a real-time block-based editor, recursive document tree, authentication, file uploads, and publishing.

Features

  • Real-time Block Editor - Notion-style block editor powered by BlockNote with slash commands, drag-and-drop blocks, and rich text formatting (bold, italic, underline, strikethrough, code)
  • Recursive Document Tree - Infinite nesting of documents with expandable/collapsible sidebar navigation
  • Authentication - Secure user authentication via Clerk with sign-in/sign-up flows
  • Real-time Database - Convex backend-as-a-service for real-time data synchronization
  • File Uploads - Cover image uploads and in-editor image uploads via EdgeStore
  • Publishing - Publish documents to a shareable public URL
  • Trash & Restore - Soft-delete documents to trash with restore and permanent delete
  • Emoji Icons - Add emoji icons to documents via emoji-mart picker
  • Cover Images - Add, change, or remove cover images on documents
  • Dark Mode - Full dark mode support with next-themes
  • Command Palette - Cmd+K search across all documents using cmdk
  • Responsive Design - Mobile-friendly collapsible sidebar
  • Resizable Sidebar - Drag to resize the sidebar width

Tech Stack

Technology Purpose
Next.js 14 React framework (App Router)
TypeScript Type safety
Tailwind CSS Utility-first styling
Convex Real-time backend & database
Clerk Authentication
EdgeStore File uploads
BlockNote Block-based editor
shadcn/ui UI component library
Radix UI Headless UI primitives
Zustand State management
cmdk Command palette
emoji-mart Emoji picker
sonner Toast notifications
next-themes Dark mode
Lucide React Icons

Getting Started

Prerequisites

1. Clone the repository

git clone <repository-url>
cd notion-clone

2. Install dependencies

npm install

3. Set up environment variables

Copy the example env file and fill in your credentials:

cp .env.example .env.local

Required environment variables:

Variable Description
CONVEX_DEPLOYMENT Your Convex deployment ID
NEXT_PUBLIC_CONVEX_URL Your Convex deployment URL
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY Clerk publishable key
CLERK_SECRET_KEY Clerk secret key
EDGE_STORE_ACCESS_KEY EdgeStore access key
EDGE_STORE_SECRET_KEY EdgeStore secret key

4. Set up Convex

npx convex dev

This will push the schema and functions to your Convex deployment.

5. Configure Clerk for Convex

In your Clerk dashboard:

  1. Go to JWT Templates
  2. Create a new template for Convex
  3. Set the issuer domain in convex/auth.config.js

6. Run the development server

npm run dev

Open http://localhost:3000 in your browser.

Project Structure

notion-clone/
+-- app/
|   +-- (main)/                    # Authenticated app routes
|   |   +-- _components/           # Sidebar & navigation components
|   |   |   +-- banner.tsx         # Archive banner
|   |   |   +-- confirm-modal.tsx  # Confirmation dialog
|   |   |   +-- document-list.tsx  # Recursive document tree
|   |   |   +-- item.tsx           # Sidebar item
|   |   |   +-- menu.tsx           # Document menu dropdown
|   |   |   +-- navbar.tsx         # Top navbar
|   |   |   +-- navigation.tsx     # Main sidebar
|   |   |   +-- publish.tsx        # Publish popover
|   |   |   +-- title.tsx          # Editable title
|   |   |   +-- trash-box.tsx      # Trash panel
|   |   |   +-- user-item.tsx      # User profile
|   |   +-- (routes)/
|   |       +-- documents/
|   |           +-- page.tsx       # Documents list
|   |           +-- [documentId]/
|   |               +-- page.tsx   # Document editor page
|   +-- (marketing)/               # Public marketing pages
|   |   +-- _components/
|   |   |   +-- footer.tsx
|   |   |   +-- heading.tsx
|   |   |   +-- heroes.tsx
|   |   |   +-- logo.tsx
|   |   |   +-- navbar.tsx
|   |   +-- layout.tsx
|   |   +-- page.tsx
|   +-- (public)/                  # Published document preview
|   |   +-- (routes)/
|   |       +-- preview/
|   |           +-- [documentId]/
|   |               +-- page.tsx
|   +-- api/
|   |   +-- edgestore/
|   |       +-- [...edgestore]/
|   |           +-- route.ts       # EdgeStore API route
|   +-- error.tsx
|   +-- globals.css
|   +-- layout.tsx
+-- components/
|   +-- modals/
|   |   +-- cover-image-modal.tsx
|   |   +-- settings-modal.tsx
|   +-- providers/
|   |   +-- convex-provider.tsx
|   |   +-- modal-provider.tsx
|   |   +-- theme-provider.tsx
|   +-- ui/                        # shadcn/ui components
|   |   +-- alert-dialog.tsx
|   |   +-- avatar.tsx
|   |   +-- button.tsx
|   |   +-- command.tsx
|   |   +-- dialog.tsx
|   |   +-- dropdown-menu.tsx
|   |   +-- input.tsx
|   |   +-- label.tsx
|   |   +-- popover.tsx
|   |   +-- skeleton.tsx
|   +-- cover.tsx
|   +-- editor.tsx                 # BlockNote editor wrapper
|   +-- icon-picker.tsx
|   +-- mode-toggle.tsx
|   +-- search-command.tsx
|   +-- single-image-dropzone.tsx
|   +-- spinner.tsx
|   +-- toolbar.tsx
+-- convex/
|   +-- auth.config.js
|   +-- documents.ts               # All mutations & queries
|   +-- schema.ts                  # Database schema
+-- hooks/
|   +-- use-cover-image.ts
|   +-- use-origin.ts
|   +-- use-scroll-top.ts
|   +-- use-search.ts
|   +-- use-settings.ts
+-- lib/
|   +-- edgestore.ts
|   +-- utils.ts
+-- .env.example
+-- .gitignore
+-- components.json
+-- next.config.js
+-- package.json
+-- postcss.config.js
+-- tailwind.config.ts
+-- tsconfig.json

Database Schema

The Convex database has a single documents table:

Field Type Description
title string Document title
userId string Owner user ID (from Clerk)
isArchived boolean Whether document is in trash
parentDocument Id<"documents">? Optional parent for nesting
content string? BlockNote JSON content
coverImage string? Cover image URL
icon string? Emoji icon
isPublished boolean Whether publicly accessible

Indexes:

  • by_user - Query documents by userId
  • by_user_parent - Query documents by userId + parentDocument (for sidebar tree)

API (Convex Functions)

Queries

  • getSidebar - Get documents for sidebar tree (by parent)
  • getById - Get single document (auth-checked)
  • getByIdPublic - Get published document (no auth)
  • getTrash - Get all archived documents
  • getSearch - Get all non-archived documents for search

Mutations

  • create - Create new document
  • update - Update document fields
  • archive - Recursively archive document and children
  • restore - Restore document from trash
  • remove - Permanently delete document
  • removeIcon - Remove emoji icon
  • removeCoverImage - Remove cover image

License

This project is for educational purposes. Feel free to use it as a reference or starting point for your own projects.

About

A full-stack Notion clone built with Next.js 14, BlockNote editor, Convex real-time backend, Clerk authentication, and EdgeStore file uploads. Features include block-based editing, nested document tree, dark mode, publishing, and Cmd+K search.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors