Skip to content

About

Real-time collaborative document workspace — rich block editor, workspaces, threaded comments, @mentions and notifications. Built with Next.js 16, React 19, Clerk, Firestore, Liveblocks and Tailwind CSS.

Topics

Resources

Stars

1 star

Watchers

1 watching

Forks

Repository files navigation

Document Planner logo

Document Planner

A real-time collaborative document workspace for modern teams.

Write together in a rich block editor, organize work into workspaces, discuss ideas in threaded comments with @mentions, and stay in the loop with an inbox for notifications. It works on desktop, tablet and mobile.

Live Demo · Report a Bug · Request a Feature


Next.js React Tailwind CSS Firebase Clerk Liveblocks

License: MIT npm audit PRs Welcome GitHub stars Last commit


📑 Table of Contents


📖 About the Project

Document Planner is a full-stack, Notion-style collaboration app built with the Next.js App Router. Teams create workspaces, fill them with documents, and edit them together in real time. Every document has a cover image, an emoji and a block-based editor. Comment threads, @mentions and an inbox keep the whole team in sync.

It shows how to put together a production-grade stack:

  • Clerk for authentication and organizations
  • Cloud Firestore for storage and live sync
  • Liveblocks for comments, mentions and notifications
  • Editor.js for rich, structured content

Why Document Planner?

Problem How Document Planner solves it
Notes and plans are scattered across tools One workspace per team or project, with every document in it
Feedback gets lost in chat apps Threaded comments and @mentions right next to the content
You never know what changed while you were away A notifications inbox with an unread counter
Personal and team work get mixed Clerk Organizations keep personal and team workspaces separate
Collaboration tools feel clunky on phones A fully responsive UI with a mobile drawer navigation

📸 Screenshots

Landing page (desktop)

Landing page on desktop



Mobile Authentication
Landing page on mobile Sign-in page

✨ Key Features

🔐 Authentication & Organizations

  • Secure sign-in and sign-up with Clerk (email, Google and other social providers)
  • Organization switcher: move between personal and team spaces
  • Protected routes for the dashboard, workspaces and API

🗂️ Workspaces

  • Create workspaces with a name, emoji and cover image
  • Switch between a grid and a list view on the dashboard
  • Rename or delete workspaces (deleting removes all their documents)
  • Workspaces belong to the active organization or to your personal account

📝 Documents

  • Create, rename, delete (with confirmation) and share documents
  • A cover image and emoji for each document, plus an inline-editable title
  • Shareable links: copy a direct URL in one click

✍️ Rich Block Editor

Built on Editor.js, with these blocks:

Headings · Paragraphs · Bulleted & numbered lists · Checklists · Tables · Code blocks · Alerts · Delimiters · Images

  • Autosave: changes are debounced and saved to Firestore
  • Smooth live sync: block-level merging shows collaborators' edits instantly without moving your cursor or closing the mobile keyboard

💬 Collaboration

  • Threaded comments powered by Liveblocks
  • @mentions with autocomplete, limited to members of the workspace organization
  • Notifications inbox on the dashboard and in workspaces: shows document names, links straight to the comment and clears the unread badge when opened

📱 Responsive Design

  • A slide-in sidebar drawer on mobile, and a fixed sidebar on desktop
  • Headers, dialogs, the editor, comments and notifications adapt to every screen size

🛠️ Tech Stack

Layer Technology
Framework Next.js 16 (App Router, Turbopack, Server Components)
UI Library React 19
Styling Tailwind CSS 4, shadcn/ui, Radix UI
Authentication Clerk (users, sessions, organizations)
Database Cloud Firestore (Firebase JS SDK v12, Admin SDK v13) with security rules
Real-time Liveblocks (comments, mentions, inbox notifications)
Editor Editor.js and plugins
Icons Lucide
Toasts Sonner
Emoji Picker emoji-picker-react
Hosting Vercel

🏗️ Architecture

flowchart LR
    U["👤 User (Browser)"] -->|Sign in| C[Clerk]
    U -->|Pages & UI| N["Next.js 16 App"]
    N -->|proxy.js route protection| C
    U -->|Exchange Clerk session| T["/api/firebase-token"]
    T -->|Custom token with<br/>email + org claims| U
    U <-->|Read / write documents<br/>enforced by security rules| F[("Cloud Firestore")]
    U <-->|Comments, mentions,<br/>notifications| L[Liveblocks]
    L -->|Request access token| A["/api/liveblocks-auth"]
    A -->|Verify session| C
    A -->|Check workspace access<br/>via Admin SDK| F
Loading

How a document session works:

  1. Clerk signs the user in. proxy.js blocks protected routes for anyone who isn't signed in.
  2. Firebase sign-in: /api/firebase-token exchanges the Clerk session for a Firebase custom token that carries the user's email and organization ids. The app signs in to Firebase with it, and Firestore security rules only allow access to workspaces owned by that email or organizations.
  3. The workspace layout loads the sidebar and starts a live Firestore listener for the workspace's documents.
  4. Opening a document joins a Liveblocks room whose id is the document id. Before it issues a token, /api/liveblocks-auth checks that the user owns the workspace or belongs to its organization.
  5. Editor.js loads the saved content from Firestore and autosaves changes after a short delay. Collaborators' edits are merged block by block, so your cursor and mobile keyboard are never disturbed.

🚀 Getting Started

Prerequisites

Requirement Version / Notes
Node.js 20.9 or newer
npm Comes with Node.js
Clerk account Free tier is enough
Firebase project Cloud Firestore + Authentication enabled
Liveblocks account Free tier is enough

Installation

1. Clone the repository

git clone https://github.com/ethical0101/Document-Planner.git
cd Document-Planner

2. Install dependencies

npm install

3. Configure environment variables

cp .env.example .env.local

Then fill in your keys. See Environment Variables.

4. Set up the services

Clerk
  1. Create an application in the Clerk Dashboard.
  2. Enable the sign-in methods you want (Email, Google, ...).
  3. Turn on Organizations under Configure → Organizations.
  4. Copy the Publishable key and Secret key into .env.local.
Firebase
  1. Create a project in the Firebase Console.
  2. Add a Web app and copy its config values into the NEXT_PUBLIC_FIREBASE_* variables.
  3. Enable Cloud Firestore.
  4. Open Authentication and click Get started. This enables Firebase Auth, which the app uses with custom tokens; no sign-in provider needs to be turned on.
  5. Go to Project settings → Service accounts → Generate new private key. From the downloaded JSON, copy project_id, client_email and private_key into FIREBASE_PROJECT_ID, FIREBASE_CLIENT_EMAIL and FIREBASE_PRIVATE_KEY.
  6. Deploy the security rules from firestore.rules:
    npx firebase-tools login
    npx firebase-tools deploy --only firestore:rules --project <your-project-id>
  7. Upgrading an existing project? Run the one-time migration so older documents get their orgId (dry run first, then apply):
    npm run migrate
    npm run migrate -- --apply
Liveblocks
  1. Create a project in the Liveblocks Dashboard.
  2. Copy the Secret key into LIVEBLOCK_SK in .env.local.

5. Start the development server

npm run dev

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


🔑 Environment Variables

Create a .env.local file in the project root. Use .env.example as the template.

Variable Required Scope Description
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY ✅ Client Clerk publishable key
CLERK_SECRET_KEY ✅ Server Clerk secret key
NEXT_PUBLIC_CLERK_SIGN_IN_URL ✅ Client Sign-in route, for example /sign-in
NEXT_PUBLIC_CLERK_SIGN_UP_URL ✅ Client Sign-up route, for example /sign-up
NEXT_PUBLIC_FIREBASE_API_KEY ✅ Client Firebase web API key
NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN ➖ Client Firebase auth domain
NEXT_PUBLIC_FIREBASE_PROJECT_ID ➖ Client Firebase project id
NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET ➖ Client Firebase storage bucket
NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID ➖ Client Firebase messaging sender id
NEXT_PUBLIC_FIREBASE_APP_ID ➖ Client Firebase app id
NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID ➖ Client Google Analytics measurement id
FIREBASE_PROJECT_ID ✅ Server Service account project id
FIREBASE_CLIENT_EMAIL ✅ Server Service account client email
FIREBASE_PRIVATE_KEY ✅ Server Service account private key (`
`-escaped)
LIVEBLOCK_SK ✅ Server Liveblocks secret key

Caution

Never commit .env.local or any file that contains secret keys. All .env* files except .env.example are git-ignored.


🧭 Usage

  1. Sign up or sign in from the landing page.
  2. (Optional) Create or switch organization with the organization switcher to collaborate as a team.
  3. On the dashboard, click New Workspace. Pick a name, an emoji and a cover image.
  4. In the workspace, use + in the sidebar to add documents.
  5. Write in the editor. Press Tab or click + to insert blocks such as headings, lists, tables and code.
  6. Open the 💬 comments button to start a thread and @mention teammates.
  7. Check the 🔔 bell for your notifications.
  8. Use Share to copy a link to the document.

⌨️ Editor shortcuts

Shortcut Action
Ctrl/⌘ + Shift + L Insert list
Ctrl/⌘ + Shift + C Insert checklist
Ctrl/⌘ + Shift + P Insert code block
Ctrl/⌘ + Shift + A Insert alert

📁 Project Structure

Document-Planner/
├── app/
│   ├── (auth)/                         # Clerk sign-in & sign-up pages
│   ├── (routes)/
│   │   ├── createworkspace/            # Create a new workspace
│   │   ├── dashboard/                  # Workspace overview (grid / list views)
│   │   └── workspace/
│   │       ├── [workspaceid]/
│   │       │   ├── layout.jsx          # Workspace shell (sidebar + Liveblocks)
│   │       │   ├── page.jsx            # Opens the first document
│   │       │   └── [documentid]/       # Document editor page
│   │       └── _components/            # Sidebar, editor, comments, notifications…
│   ├── _components/                    # Landing page, logo, pickers, auth layout
│   ├── api/
│   │   ├── firebase-token/             # Mints Firebase custom tokens from Clerk sessions
│   │   ├── liveblocks-auth/            # Authorizes users for Liveblocks rooms
│   │   └── mention-suggestions/        # Workspace members for @mentions
│   ├── Room.jsx                        # Liveblocks client & room providers
│   ├── globals.css                     # Tailwind CSS 4 theme & global styles
│   └── layout.js                       # Root layout (Clerk, fonts, toaster, metadata)
├── components/
│   ├── FirebaseAuthGate.jsx            # Signs in to Firebase with the Clerk session
│   └── ui/                             # shadcn/ui primitives
├── config/firebaseConfig.js            # Firebase initialization
├── docs/screenshots/                   # README screenshots
├── lib/                                # Shared helpers (documents, block sync, utils)
│   └── server/                         # Server-only helpers (Firebase Admin, access checks)
├── public/Assets/                      # Logo, cover images & illustrations
├── scripts/migrate-org-ids.mjs         # One-time Firestore data migration
├── firestore.rules                     # Firestore security rules
├── proxy.js                            # Clerk route protection (Next.js proxy)
├── next.config.mjs                     # Next.js configuration
├── .env.example                        # Environment variable template
└── package.json

🗄️ Data Model

The app uses four Firestore collections:

erDiagram
    Workspace ||--o{ workspaceDocuments : contains
    workspaceDocuments ||--|| documentOutput : "has content"
    DocPlannerUsers ||--o{ Workspace : creates

    Workspace {
        string id PK
        string workspaceName
        string emoji
        string coverImage
        string createdBy
        string orgId "Clerk org id or user email"
    }
    workspaceDocuments {
        string id PK
        string workspaceId FK
        string documentName
        string emoji
        string coverImage
        string orgId "copied from workspace"
        string createdBy
    }
    documentOutput {
        string docId PK
        string orgId "copied from workspace"
        string output "Editor.js JSON"
        string editedBy
    }
    DocPlannerUsers {
        string email PK
        string name
        string avatar
    }
Loading

Each Liveblocks room id is the same as its document id, so every document has its own comments and presence.


📜 Available Scripts

Command Description
npm run dev Start the development server with hot reload
npm run build Create an optimized production build
npm run start Serve the production build
npm run migrate One-time data migration for Firestore rules (add -- --apply to write)

☁️ Deployment

Deploy to Vercel (recommended)

Deploy with Vercel

  1. Click the button above, or import the repository at vercel.com/new.
  2. Add all the required environment variables. Paste FIREBASE_PRIVATE_KEY exactly as it appears in the service account JSON.
  3. Deploy the Firestore rules and, for existing data, run the migration. See the Firebase setup steps above.
  4. Set Node.js 20.x or newer under Project Settings → General.
  5. Add your production domain in the Clerk Dashboard under Domains.
  6. Deploy. 🚀

Any platform that supports Next.js 16 on Node.js 20.9 or newer works as well (Netlify, Railway, Render, Docker and others).


🛡️ Security

  • ✅ 0 known vulnerabilities: all dependencies are on patched versions (npm audit).
  • ✅ Secrets stay server-side: CLERK_SECRET_KEY, FIREBASE_PRIVATE_KEY and LIVEBLOCK_SK are never sent to the browser.
  • ✅ Clerk ⇄ Firebase integration: users sign in to Firebase with a custom token minted from their Clerk session. The token carries their email and organization ids.
  • ✅ Firestore security rules (firestore.rules): users can only read and write workspaces, documents and content that belong to them or to their organizations. Ownership can't be changed or spoofed, and every other collection is closed. The rules are covered by tests run against the Firestore emulator.
  • ✅ Route protection: /dashboard, /workspace, /createworkspace and the /api/* routes require a signed-in user.
  • ✅ Scoped @mentions: suggestions only include members of the document's workspace organization (or just the owner for personal workspaces).
  • ✅ Room authorization: the Liveblocks auth endpoint validates the room id and checks that the user owns the workspace or belongs to its organization before it grants access.
  • ✅ No secrets in git: .env* files are ignored, and .env.example contains placeholders only.

Important

Remember to deploy firestore.rules to your Firebase project. Until the rules are deployed, Firestore uses whatever rules are currently set in the console.

Reporting a vulnerability: please don't open a public issue. Use GitHub private vulnerability reporting instead.


🗺️ Roadmap

  • Authentication & organizations
  • Workspaces with emoji & cover images
  • Rich block editor with autosave
  • Real-time sync between collaborators
  • Threaded comments, @mentions & notifications
  • Fully responsive UI
  • Clerk ⇄ Firebase Auth integration with strict Firestore rules
  • Workspace rename & delete
  • Workspace member management
  • Document search
  • Dark mode
  • Export to PDF / Markdown
  • Document version history

Have an idea? Open a feature request.


🤝 Contributing

Contributions make the open-source community great, and any contribution is appreciated.

  1. Fork the repository.
  2. Create a feature branch:
    git checkout -b feature/amazing-feature
  3. Commit your changes, following Conventional Commits:
    git commit -m "feat: add amazing feature"
  4. Push the branch:
    git push origin feature/amazing-feature
  5. Open a pull request.

Please make sure npm run build passes before you submit.


📄 License

Distributed under the MIT License. See LICENSE for details.


🙏 Acknowledgements


If you find this project useful, please consider giving it a ⭐ on GitHub!

Made with ❤️ by ethical0101

About

Real-time collaborative document workspace — rich block editor, workspaces, threaded comments, @mentions and notifications. Built with Next.js 16, React 19, Clerk, Firestore, Liveblocks and Tailwind CSS.

Topics

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages