Skip to content

btallitsch/mini-notion

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

30 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

๐Ÿ—’๏ธ Mini Notion โ€” Collaborative Document Editor

A full-stack, Notion-inspired document editor built with React 18, Zustand, and Firebase. Features real-time cloud sync, Google + email authentication, offline support, drag-and-drop reordering, and full version history โ€” all deployable to the web with zero local development environment required.


๐ŸŒ Live Demo

Deployed on Vercel โ†’ mini-notion-nine.vercel.app


โœจ Features

Feature Description
โ˜๏ธ Cloud Sync Real-time Firestore sync โ€” edits appear across all devices instantly
๐Ÿ” Authentication Google OAuth + Email/Password sign-in via Firebase Auth
๐Ÿ“ด Offline Support IndexedDB persistence โ€” the app works fully without internet
๐Ÿ“„ Nested Documents Create pages inside pages with unlimited hierarchy depth
๐Ÿ”„ Drag & Drop Reorder pages in the sidebar โ€” persisted to Firestore
๐Ÿ’พ Autosave Debounced 800ms autosave with optimistic updates
โฐ Version History Up to 25 restorable cloud snapshots per document
๐Ÿ‘๏ธ Role System Toggle between Editor and Read-only mode
๐Ÿ“ Markdown Full Markdown editing with live preview
๐ŸŽจ Emoji Icons Per-page emoji picker
โŒจ๏ธ Keyboard Shortcuts Ctrl+B sidebar toggle, Ctrl+N new page

๐Ÿงฑ Tech Stack

Layer Technology
UI Framework React 18 with Hooks
State Management Zustand + Immer
Cloud Database Firebase Firestore
Authentication Firebase Auth (Google + Email/Password)
Offline Persistence Firestore IndexedDB cache
Drag & Drop HTML5 native drag-and-drop
Build Tool Vite
Deployment Vercel

๐Ÿ“ Project Structure

mini-notion/
โ”œโ”€โ”€ .env.example                              # Firebase env vars template (safe to commit)
โ”œโ”€โ”€ index.html                                # App entry point
โ”œโ”€โ”€ package.json
โ”œโ”€โ”€ vite.config.js
โ”œโ”€โ”€ tailwind.config.js
โ”œโ”€โ”€ postcss.config.js
โ”‚
โ””โ”€โ”€ src/
    โ”œโ”€โ”€ main.jsx                              # React root
    โ”œโ”€โ”€ App.jsx                               # Auth gate + Firestore sync bootstrap
    โ”œโ”€โ”€ index.css                             # Global styles + animations
    โ”‚
    โ”œโ”€โ”€ firebase/
    โ”‚   โ”œโ”€โ”€ config.js                         # Firebase init + IndexedDB offline persistence
    โ”‚   โ”œโ”€โ”€ auth.js                           # Auth helpers: Google, email, sign-out
    โ”‚   โ””โ”€โ”€ firestore.js                      # All Firestore reads, writes, listeners
    โ”‚
    โ”œโ”€โ”€ store/
    โ”‚   โ”œโ”€โ”€ documentStore.js                  # Zustand: documents, versions, Firebase writes
    โ”‚   โ””โ”€โ”€ uiStore.js                        # Zustand: role, sidebar, selection state
    โ”‚
    โ”œโ”€โ”€ hooks/
    โ”‚   โ”œโ”€โ”€ useAuth.js                        # Firebase auth state observer
    โ”‚   โ”œโ”€โ”€ useFirestoreSync.js               # Bootstrap + real-time onSnapshot subscriptions
    โ”‚   โ”œโ”€โ”€ useAutosave.js                    # Debounced Firestore persistence hook
    โ”‚   โ””โ”€โ”€ useDebounce.js                    # Generic debounce hook
    โ”‚
    โ”œโ”€โ”€ utils/
    โ”‚   โ”œโ”€โ”€ immutable.js                      # Immutable tree helpers (Immer patterns)
    โ”‚   โ””โ”€โ”€ dateUtils.js                      # Timestamp formatting utilities
    โ”‚
    โ””โ”€โ”€ components/
        โ”œโ”€โ”€ Auth/
        โ”‚   โ””โ”€โ”€ AuthScreen.jsx                # Sign-in / Sign-up / Password reset UI
        โ”œโ”€โ”€ Header/
        โ”‚   โ””โ”€โ”€ Header.jsx                    # Top bar: sync status, user menu, sign-out
        โ”œโ”€โ”€ RoleToggle/
        โ”‚   โ””โ”€โ”€ RoleToggle.jsx                # Editor / Read-only segmented control
        โ”œโ”€โ”€ EmojiPicker/
        โ”‚   โ””โ”€โ”€ EmojiPicker.jsx               # Floating emoji grid
        โ”œโ”€โ”€ Sidebar/
        โ”‚   โ”œโ”€โ”€ Sidebar.jsx                   # Sidebar shell + New Page button
        โ”‚   โ””โ”€โ”€ DocumentItem.jsx              # Draggable, collapsible tree node
        โ”œโ”€โ”€ Editor/
        โ”‚   โ”œโ”€โ”€ Editor.jsx                    # Main editor + autosave orchestration
        โ”‚   โ”œโ”€โ”€ EditorToolbar.jsx             # Markdown formatting toolbar
        โ”‚   โ””โ”€โ”€ MarkdownView.jsx              # Read-only Markdown renderer
        โ””โ”€โ”€ VersionHistory/
            โ””โ”€โ”€ VersionPanel.jsx              # Version list + Firestore restore

๐Ÿš€ Deployment Guide

This project is designed to be deployed entirely through the browser โ€” no local development environment needed.

Step 1 โ€” Set Up Firebase

Create a Firebase project:

  1. Go to firebase.google.com and sign in with your Google account
  2. Click Create a project, name it mini-notion, disable Google Analytics, click Create
  3. Once ready, click Continue

Register a Web App:

  1. On the project dashboard, click the Web icon (</>)
  2. Give it a nickname like mini-notion-web and click Register app
  3. Copy the firebaseConfig values shown โ€” you'll need these in Step 3

Enable Authentication:

  1. Go to Build โ†’ Authentication โ†’ Get started
  2. Click Google โ†’ toggle Enable โ†’ add your support email โ†’ Save
  3. Click Email/Password โ†’ toggle Enable โ†’ Save

Create Firestore Database:

  1. Go to Build โ†’ Firestore Database โ†’ Create database
  2. Choose Production mode, pick a region close to you, click Enable
  3. Go to the Rules tab and replace the contents with:
rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /workspaces/{userId}/{document=**} {
      allow read, write: if request.auth != null && request.auth.uid == userId;
    }
  }
}
  1. Click Publish

Step 2 โ€” Push Code to GitHub

  1. Go to github.com โ†’ New repository โ†’ name it mini-notion
  2. Upload the contents of the mini-notion-firebase.zip (unzipped) to the repo
  3. Make sure package.json and index.html are at the root level
  4. โš ๏ธ Do not upload .env.local โ€” only .env.example is safe to commit

Step 3 โ€” Deploy on Vercel

  1. Go to vercel.com โ†’ Sign up with GitHub
  2. Click Add New โ†’ Project โ†’ import your mini-notion repository
  3. Vercel auto-detects Vite โ€” the default settings are correct
  4. Before clicking Deploy, scroll to Environment Variables and add all 6 Firebase values:
Variable Name Where to find the value
VITE_FIREBASE_API_KEY Firebase โ†’ Project Settings โ†’ Your App
VITE_FIREBASE_AUTH_DOMAIN Firebase โ†’ Project Settings โ†’ Your App
VITE_FIREBASE_PROJECT_ID Firebase โ†’ Project Settings โ†’ Your App
VITE_FIREBASE_STORAGE_BUCKET Firebase โ†’ Project Settings โ†’ Your App
VITE_FIREBASE_MESSAGING_SENDER_ID Firebase โ†’ Project Settings โ†’ Your App
VITE_FIREBASE_APP_ID Firebase โ†’ Project Settings โ†’ Your App
  1. Click Deploy โ€” your live URL will be ready in about 60 seconds

Step 4 โ€” Authorize Your Domain for Google Sign-In

Google sign-in requires two separate places to be updated. Both are required.

In Firebase Console:

  1. Go to Authentication โ†’ Settings โ†’ Authorized domains
  2. Click Add domain and enter your Vercel URL without https://:
    your-app.vercel.app
    

In Google Cloud Console:

  1. Go to console.cloud.google.com
  2. Select your Firebase project from the top-left dropdown
  3. Go to APIs & Services โ†’ Credentials
  4. Click the Web client (auto created by Google Service) OAuth 2.0 client
  5. Under Authorized JavaScript origins click Add URI and enter:
    https://your-app.vercel.app
    
  6. Under Authorized redirect URIs click Add URI and enter:
    https://your-app.vercel.app/__/auth/handler
    
  7. Click Save and wait 5 minutes for the changes to take effect

Step 5 โ€” Verify Everything Works

  1. Open your Vercel URL
  2. Sign in with Google or create an email/password account
  3. Create a page, type something, and look for โœ“ Saved to cloud in the header
  4. Open Firebase Console โ†’ Firestore Database โ†’ Data โ€” a workspaces collection will appear with your user ID inside it

The database starts completely empty โ€” this is normal. Firestore creates all collections and documents automatically the first time a user signs in.


โ™พ๏ธ Making Updates (No Local Environment Needed)

Once deployed, all code changes follow this simple workflow:

  1. Open any file in your GitHub repository
  2. Click the pencil โœ๏ธ icon to edit it directly in the browser
  3. Make your changes and click Commit changes
  4. Vercel automatically detects the new commit and redeploys in ~60 seconds
  5. Your live URL updates โ€” no terminal, no local setup required

๐Ÿ—๏ธ Architecture

Firebase Data Model

Firestore
โ””โ”€โ”€ workspaces/
    โ””โ”€โ”€ {userId}/                     โ† isolated workspace per user
        โ”œโ”€โ”€ meta/
        โ”‚   โ””โ”€โ”€ workspace             โ† { rootDocumentIds: string[] }
        โ”œโ”€โ”€ documents/
        โ”‚   โ””โ”€โ”€ {docId}               โ† document content + metadata
        โ””โ”€โ”€ versions/
            โ””โ”€โ”€ {docId}/
                โ””โ”€โ”€ snapshots/
                    โ””โ”€โ”€ {snapId}      โ† immutable version snapshot

Each user gets a fully isolated workspace. The Firestore security rules ensure users can only access their own data โ€” no user can read or write another user's workspace.

Optimistic Updates

The UI never waits for Firestore. Every change is applied to the Zustand store immediately, then persisted to Firestore after an 800ms debounce. The editor always feels instant regardless of network speed.

User types
  โ†’ Local Zustand state updates instantly  (no lag)
  โ†’ [800ms pause after last keystroke]
  โ†’ Firestore write fires
  โ†’ Version snapshot saved
  โ†’ "โœ“ Saved to cloud" indicator shown

Conflict Resolution

If a remote Firestore update arrives while the user is actively editing, the local version is preserved when its updatedAt timestamp is newer. This prevents cloud sync from overwriting unsaved in-progress edits.

Offline Support

enableIndexedDbPersistence() in firebase/config.js caches all Firestore data locally. When offline, reads are served from cache and writes are queued. Everything syncs automatically the moment connectivity is restored โ€” no extra code required.


โŒจ๏ธ Keyboard Shortcuts

Shortcut Action
Ctrl / โŒ˜ + B Toggle sidebar open and closed
Ctrl / โŒ˜ + N Create a new root-level page
Auto All edits save 800ms after you stop typing

๐Ÿ› ๏ธ Troubleshooting

Problem Most Likely Cause Fix
Google button โ€” "This site can't be reached" Missing OAuth origins in Google Cloud Console Add your Vercel domain to Authorized JavaScript Origins in Google Cloud โ†’ APIs & Services โ†’ Credentials
auth/unauthorized-domain in console Vercel domain not added to Firebase Firebase โ†’ Auth โ†’ Settings โ†’ Authorized Domains โ†’ Add domain
auth/popup-closed-by-user Browser blocked the popup Disable popup blocker for your site, or switch to signInWithRedirect
Firebase values showing as undefined Env vars missing or app not redeployed Vercel โ†’ Settings โ†’ Environment Variables โ†’ verify all 6 exist โ†’ Redeploy
Firestore data tab stays empty Rules not published or auth failing Re-publish Firestore security rules; check F12 console for auth errors
Build fails on Vercel package.json not at repo root Ensure files were uploaded to repo root, not inside a subfolder
"โœ“ Saved to cloud" never appears Firestore write failing silently Open F12 โ†’ Console and look for Firebase error messages
Data disappears after page refresh Firestore write not completing before navigation Check F12 โ†’ Network tab for failed requests to Firestore
Google sign-in works locally but not on Vercel Production domain not authorized Repeat Step 4 with your exact Vercel URL

๐Ÿ”ฎ Roadmap

  • Real-time collaboration โ€” Yjs + y-firestore for CRDT-based concurrent editing with live cursors
  • Rich text editor โ€” TipTap or Slate.js replacing the plain <textarea>
  • Workspace sharing โ€” invite other users with editor or read-only roles
  • Full-text search โ€” Algolia or Typesense connected via Cloud Functions
  • Export โ€” download any page as Markdown or PDF
  • Mobile responsive layout โ€” collapsible sidebar for phones and tablets
  • Tests โ€” Vitest unit tests for store actions, Playwright E2E tests for key flows

๐ŸŽจ Design System

Built with the Catppuccin Mocha dark color palette.

Token Hex Usage
Base #1e1e2e Main editor background
Mantle #181825 Sidebar and toolbar backgrounds
Crust #11111b Header bar
Surface 0 #313244 Buttons and input backgrounds
Overlay 0 #6c7086 Muted text and icons
Text #cdd6f4 Primary text
Mauve #cba6f7 Accent color, active selections
Green #a6e3a1 Save confirmation, success states
Yellow #f9e2af Saving in progress indicator
Red #f38ba8 Delete actions and error states

๐Ÿ“„ License

MIT โ€” free to use, modify, and distribute.


Built with React 18 ยท Zustand ยท Firebase ยท Vite ยท Deployed on Vercel

About

Collaborative Document Editor

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages