Edit Notes like in Notion.so. Full-Stack App using React/Express.

Overview

📓 Notion Clone

Create and Edit Notes like in Notion

This clone tries to replicate some of the great note-taking features Notion has. If you don't know Notion.so yet, I highly recommend to check it out!

📌 Live Demo: notion-clone.kmuenster.com

📌 Medium Article: How To Build A Text Editor Like Notion


notion clone screenshot


Features

  • Slash Commands (Type / to turn the block into different content types)
  • HTML Support (Use regular HTML tags like <a> in text blocks)
  • Image Support (Upload images by using the /image command)
  • Drag And Drop (Reorder blocks easily by drag and drop)
  • Guest Editing (Anyone can create public pages and share them via link)
  • User Management (Create an account to create private pages)
  • Scheduled Jobs (Delete inactive pages and accounts automatically)

Tech Stack

The frontend is built with Next.js and fully server-side rendered. On the backend, a REST API handles saving user content and user management.

Frontend

Next.js · React.js · SCSS/SASS

Backend

Express.js · MongoDB with Mongoose · Nodemailer · JWT (Cookie-based)

Installation

  1. Clone the project

     git clone https://github.com/konstantinmuenster/notion-clone.git
     cd notion-clone
  2. Add environment variables

    Backend: Create an .env file in the backend directory:

    FRONTEND_URL="http://localhost:3000"
    DOMAIN="localhost"
    JWT_KEY="yourSecretForTokenGeneration"
    PORT=8080
    MONGO_URI="mongodb+srv://username:[email protected]/database?retryWrites=true&w=majority"
    MAIL_HOST="smtp.sendgrid.net"
    MAIL_PORT=465
    MAIL_USER="apiKey"
    MAIL_SENDER="Your Name <[email protected]>"
    MAIL_PASSWORD="yourSendGridApiKey"
    

    Frontend: Create an .env.local file in the frontend directory:

    NEXT_PUBLIC_API="http://localhost:8080" // references your Backend API endpoint
    
  3. Install and run backend (http://localhost:8080)

    cd backend
    npm install
    npm start
  4. Install and run frontend (http://localhost:3000)

    cd frontend
    npm install
    npm run dev

Hosting

You can host the application on almost any provider that supports Node applications and custom domains. I decided to host the frontend on vercel.com and the backend on heroku.com. But you can host both, frontend and backend, on the same provider if you like to.

MongoDB Atlas

You have to create a new MongoDB cluster upfront. It will store all of your page and block data. You can create one for free on MongoDB Atlas.

Make sure, you create the following collections:

  • pages
  • users

Make sure, you allow network access to everyone (due to Heroku).

Backend

If you want to deploy the backend on heroku.com, create a new app in your preferred region on heroku.com.

Make sure, you add all production environmental variables for the backend. You can see which variables are needed in the Installation part of this readme.

Make sure, you add a custom domain for your backend API. Since the application uses a Cookie-based authentication, we have to run backend and frontend on the same domain. I, for example, run the frontend on www.notion-clone.kmuenster.com and the backend on api.notion-clone.kmuenster.com.

Want to run scheduled jobs? To delete inactive pages and users, I run scheduled jobs frequently. If you want this feature as well, you have to add more dynos to your application and run the job $ node jobs/index.js via Heroku Scheduler.

Lastly, you can deploy your app using Heroku Git.

Make sure, that when you push the backend to Heroku, you make a Git subtree push since notion-clone is a mono-repo containing backend and frontend. So run git subtree push --prefix backend heroku master instead of git push heroku master. Thus, we only push the backend part.

Frontend

If you want to deploy the frontend on vercel.com, you can so easily using the Vercel CLI.

With the Vercel CLI, we don't have to make a subtree push, instead we can just switch to the frontend folder and run the vercel command to deploy:

cd frontend
vercel

This will lead you through the setup guide for your frontend application. Afterwards the app should be successfully deployed.

Make sure, you add the Backend API endpoint as a production environmental variable on Vercel.com.

Make sure, you add a custom domain for your frontend (that ideally matches the domain which you have specified in your backend environmental variables 😉 )

About

Buy Me A Coffee

Konstantin Münster – konstantin.digital

Distributed under the MIT license. See LICENSE for more information.

https://github.com/konstantinmuenster

Comments
  • logout feature not working

    logout feature not working

    hi, when i clone this repo and connect it to my mongodb instance, i can successfully sign up and it will sign me in properly the first time. it seems like the signup function in the users controller is what is called when the user is first signing up to log them in. i'm able to log out successfully from here. when i log in again (and my user already exists) it looks like you log in via the login function in the users controller. it logs me in successfully, but when i try to log out, i get this error and can't figure out where headers are being set after they're already sent to the client.

    wait  - compiling...
    event - compiled successfully
    Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
        at ServerResponse.setHeader (_http_outgoing.js:558:11)
        at DevServer.sendHTML (/Users//Documents//temp/notion-clone/frontend/node_modules/next/dist/server/next-dev-server.js:35:5)
        at DevServer.render (/Users//Documents//temp/notion-clone/frontend/node_modules/next/dist/next-server/server/next-server.js:56:37)
        at async Object.fn (/Users//Documents//temp/notion-clone/frontend/node_modules/next/dist/next-server/server/next-server.js:32:556)
        at async Router.execute (/Users//Documents//temp/notion-clone/frontend/node_modules/next/dist/next-server/server/router.js:23:67)
        at async DevServer.run (/Users//Documents//temp/notion-clone/frontend/node_modules/next/dist/next-server/server/next-server.js:49:656)
        at async DevServer.handleRequest (/Users//Documents//temp/notion-clone/frontend/node_modules/next/dist/next-server/server/next-server.js:20:388) {
      code: 'ERR_HTTP_HEADERS_SENT'
    }
    events.js:292
          throw er; // Unhandled 'error' event
          ^
    
    Error [ERR_STREAM_WRITE_AFTER_END]: write after end
        at writeAfterEnd (_http_outgoing.js:668:15)
        at ServerResponse.end (_http_outgoing.js:788:7)
        at ServerResponse.end (/Users//Documents//temp/notion-clone/frontend/node_modules/next/dist/compiled/compression/index.js:1:142407)
        at DevServer.handleRequest (/Users//Documents//temp/notion-clone/frontend/node_modules/next/dist/next-server/server/next-server.js:20:476)
    Emitted 'error' event on ServerResponse instance at:
        at writeAfterEndNT (_http_outgoing.js:727:7)
        at processTicksAndRejections (internal/process/task_queues.js:81:21) {
      code: 'ERR_STREAM_WRITE_AFTER_END'
    }
    

    i noticed this isn't an issue on the deployed site link in this repo, am i missing something?

    bug 
    opened by sayemmh 11
  • frontend on npm start failed

    frontend on npm start failed

    PS C:\notion-clone\frontend> npm start

    [email protected] start next start -p $PORT

    Error: Could not find a valid build in the 'C:\notion-clone\frontend.next' directory! Try building your app with 'next build' before starting the server. at Server.readBuildId (C:\notion-clone\frontend\node_modules\next\dist\next-server\server\next-server.js:120:355) at new Server (C:\notion-clone\frontend\node_modules\next\dist\next-server\server\next-server.js:3:120) at createServer (C:\notion-clone\frontend\node_modules\next\dist\server\next.js:2:638) at start (C:\notion-clone\frontend\node_modules\next\dist\server\lib\start-server.js:1:323) at nextStart (C:\notion-clone\frontend\node_modules\next\dist\cli\next-start.js:19:125) at C:\notion-clone\frontend\node_modules\next\dist\bin\next:26:341 PS C:\notion-clone\frontend>

    opened by loveJasmine 2
  • Why not contributing to https://editorjs.io/ ?

    Why not contributing to https://editorjs.io/ ?

    Simple question

    • Why not contributing to https://editorjs.io/ ?

    • [x] They still have a wide community

    • [x] They support many plugins

    • [x] They are still used by many production projects

    opened by Aarbel 2
  • Added Server run status and  status of Initial Database connection setup

    Added Server run status and status of Initial Database connection setup

    Hi, these new features are very useful for developers..

    I have added a feature which will display status of sever running on port and then it will check connection with database... if there any error encounter while connecting with DB, it display it on console......

    opened by saurabh-kumar88 2
  • .env.sample is missing

    .env.sample is missing

    Both backend and frontend directories are missing .env.sample and it is a hurdle to start the app on my localhost. I'd be a great help if you could add a .env.sample in your project to help us get started quickly.

    Thanks!

    opened by iamsaumya 2
  • Two simple questions

    Two simple questions

    Very nice project and serious effort, congrats.

    1. In the frontend/pages/account.js in getServerSideProps() why do you make http call when that function runs on server and it can query database directly?
    export const getServerSideProps = async (context) => {
      ...
      try {
        const response = await fetch(
          `${process.env.NEXT_PUBLIC_API}/users/account`,
    
    1. In the frontend/context/UserContext.js why do you create 2 separate contexts
    <UserStateContext.Provider value={state}>
      <UserDispatchContext.Provider value={dispatch}>
    

    instead of one?

    <UserContext.Provider value={{state, dispatch}}>
    
    opened by nemanjam 1
  • Cancelling image on page title makes page unusable

    Cancelling image on page title makes page unusable

    Steps to recreate:

    1. Select the page title region
    2. Type "/" and then select the image type
    3. When the image selection window pops up, select "Cancel" or close the window
    4. The page becomes unusable
    bug 
    opened by JTHEN-DEV 1
  • Deleting title causes the page to be unusable

    Deleting title causes the page to be unusable

    Steps to recreate:

    1. Go to the demo website which will automatically create a new page
    2. Instead of entering a page title, press backspace

    Upon pressing backspace, all functionality of the page is removed. A new title cannot be added and no contents on the page can be created

    opened by JTHEN-DEV 1
  • match-sorter import statement change

    match-sorter import statement change

    Thanks for the tutorial. It was excellent. I am coming back to JavaScript and React after a hiatus of 4.5 years.

    I had to change the following line:

    import matchSorter from "match-sorter";
    

    to import { matchSorter } from "match-sorter";

    I am on version match-sorter 6.3.1 (the latest version)

    opened by neerajsangal 0
  •  about adding block freely

    about adding block freely

    hello, dev bro. If i click on the page freely, hopefully, there will add a block automatically. i should repeatedly click "enter" to go to the place where i prefer to. 😂

    enhancement 
    opened by Shianiiiu 0
👀 ✏️ Edit your react-three-fiber scene with a visual editor without giving up control over your code.

React Three Editable React Three Editable is a library for React and react-three-fiber that lets you edit your scene in a visual editor while requirin

Andrew Prifer 344 Dec 23, 2022
A React & Electron editor keeping track of notes on a daily basis

Electron React Boilerplate uses Electron, React, React Router, Webpack and React Fast Refresh. Install Clone the repo and install dependencies: git cl

Zahyr Seferina 0 Dec 27, 2021
⚡️ Full-featured visual editor and code generator for React using Chakra UI

OpenChakra is a visual editor for the best component library in town: Chakra UI ?? . Quickly draft components with the simple drag and drop UI.

Premier Octet 2.7k Jan 5, 2023
Codeone is a web app built on top of React which includes an IDE supporting multiple languages for programming in addition with a highly customizable Web Editor supporting real time changes

Codeone is a web app built on top of React which includes an IDE supporting multiple languages for programming in addition with a highly customizable Web Editor supporting real time changes

Dhruv Pasricha 20 Dec 14, 2022
✏️ A very simple but useful Markdown Previewer and Markdown Editor with CodeMirror, Markedjs, and Create-react-app

Markdown Editor A very simple but useful Markdown Previewer and Markdown Editor with CodeMirror, Markedjs and Create-react-app Preview Markdown Editor

Lam Pham 30 Dec 20, 2022
Frond-end react app to model in 3d space with css only

Getting Started with Create React App This project was bootstrapped with Create React App. Available Scripts In the project directory, you can run: np

null 1 Jan 1, 2022
Wysiwyg / Text editor components built using React and Prosemirror

Wysiwyg / Text editor components built using React and Prosemirror

Nib 220 Dec 13, 2022
(alpha) Compose a React-based text editor using a suite of standard plugins

React Editor Kit (currently in alpha) A suite of plugins for composing react-based text editors. Editor Kit is built using Slate (v0.50+) - the fantas

Michael Kelly 21 Apr 10, 2022
Wysiwyg / Text editor components built using React and Prosemirror

NIB Demo Despite various options available for rich text editing in html, it continues to be extremely challenging area. I found prosemirror to be the

Nib 220 Dec 13, 2022
A simple Rich Text Editor created using TypeScript and React

TSRTE This is a very simple Rich Text Editor created using TypeScript. Its purpose is nothing more than to help me practice using TypeScript and React

Tommy Adams 2 Jun 1, 2022
Image editor using react native for iOS and Android

React Native Photo Editor (RNPE) ?? Image editor using native modules for iOS and Android. Inherit from 2 available libraries, ZLImageEditor (iOS) and

Suman Kamilya 9 Aug 16, 2022
Monaco Editor for React - use the monaco-editor in any React application

Monaco Editor for React - use the monaco-editor in any React application without needing to use webpack (or rollup/parcel/etc) configuration files / plugins

Suren Atoyan 2.2k Dec 31, 2022
React Trix rich text editor is react wrapper built for the Trix editor

React wrapper for Trix rich text editor created by Basecamp

Abhay Nikam 66 Dec 3, 2022
Official CKEditor 4 React component.

CKEditor 4 WYSIWYG editor component for React Official CKEditor 4 WYSIWYG editor component for React. We are looking forward to your feedback! You can

CKEditor Ecosystem 80 Dec 21, 2022
Official CKEditor 5 React component.

CKEditor 5 rich text editor component for React Official CKEditor 5 rich text editor component for React. Developer Documentation ?? See the "Rich tex

CKEditor Ecosystem 356 Jan 2, 2023
A React framework for building text editors.

Draft.js Draft.js is a JavaScript rich text editor framework, built for React and backed by an immutable model. Extensible and Customizable: We provid

Facebook 22.3k Jan 8, 2023
React Ace Component

React-Ace A set of react components for Ace NOTE FOR VERSION 8! : We have stopped support for Brace and now use Ace-builds. Please read the documentat

James Hrisho 3.7k Dec 27, 2022
Codemirror Component for React.js

Codemirror The excellent CodeMirror editor as a React.js component. Demo & Examples Live demo: JedWatson.github.io/react-codemirror To build the examp

Jed Watson 1.5k Dec 8, 2022
React component for a div with editable contents

react-contenteditable React component for a div with editable contents Install npm install react-contenteditable Usage import React from 'react' impor

Ophir LOJKINE 1.4k Dec 31, 2022