A modern, full-stack, secure note-taking application built with the MERN stack (MongoDB, Express 5, React 19, Node.js), featuring Google OAuth 2.0 Single Sign-On, Guest Account Mode, Automatic Guest-to-Google Note Migration, and Strict Per-User Note Isolation.
1. Live Demo (Hosted on Vercel)
2. Live Demo (Hosted on Render)
- π Google OAuth 2.0 & Guest Authentication:
- Sign in seamlessly using Google OAuth 2.0 with a modern, customized Google Sign-In interface.
- Guest Mode: Instant trial mode allowing users to create and test notes without creating an account or providing email details.
- π Automatic Note Migration:
- Transfer and merge all temporary guest notes into a permanent Google account upon Google Sign-In.
- π‘οΈ Per-User Data Isolation & Security:
- Notes are strictly isolated per user in MongoDB.
- Protected API endpoints enforced with JSON Web Tokens (JWT) middleware to ensure users can only view, edit, and delete their own private notes.
- π¨ Modern Aesthetic & Mobile Responsive:
- Vibrant dark-mode glassmorphism interface built with React 19, Tailwind CSS, DaisyUI, and Lucide React icons.
- Minimalist Navbar with an animated profile avatar dropdown displaying full user details and single-click logout.
- Fully responsive design tailored for mobile viewports (320px+), tablets, and desktop displays.
- Graceful avatar fallback β automatically displays user initials when profile images fail to load or are rate-limited.
- β‘ Fail-Open Rate Limiting:
- Integrated API rate limiting using Upstash Redis with fail-open fallback handling to protect endpoints against abuse without compromising service availability.
- Framework: React 19 + Vite 8
- Authentication:
@react-oauth/google - Styling: Tailwind CSS (v3) + DaisyUI
- Icons: Lucide React
- Routing: React Router v8
- HTTP Client: Axios (with automatic JWT Authorization request interceptors)
- Notifications: React Hot Toast
- Runtime: Node.js (v18+)
- Framework: Express.js (v5)
- Database: MongoDB (via Mongoose 9 ORM)
- Tokens & Auth: JSON Web Tokens (
jsonwebtoken),google-auth-library - Rate Limiting: Upstash Redis (
@upstash/ratelimit,@upstash/redis)
mern-thinkboard/
βββ backend/ # Express API Server (Vercel Serverless Function)
β βββ src/
β β βββ config/ # MongoDB (db.js) & Upstash Redis (upstash.js) config
β β βββ controllers/ # authController.js & notesController.js
β β βββ middleware/ # authMiddleware.js & rateLimiter.js
β β βββ models/ # User.js & Note.js Mongoose schemas
β β βββ routes/ # authRoutes.js & notesRoutes.js
β β βββ server.js # Express server entry point
β βββ vercel.json # Vercel backend routing & @vercel/node builder config
β βββ .env # Backend environment configuration
β βββ package.json
βββ frontend/ # React SPA Frontend (Vercel Static Deployment)
β βββ src/
β β βββ assets/ # Application assets & thumbnails
β β βββ components/ # ConfirmDialog, Navbar, NoteCard, NoteEditor, NotesNotFound, ProtectedRoute, RateLimitedUI
β β βββ context/ # AuthContext (JWT & OAuth session management)
β β βββ lib/ # Axios instance configuration (axios.js)
β β βββ pages/ # LoginPage, HomePage, CreatePage, NoteDetailPage
β β βββ App.jsx # Application routing layout
β β βββ main.jsx # React DOM entry with Google OAuth Provider
β βββ vercel.json # Vercel frontend SPA rewrite & COOP headers config
β βββ .env # Frontend environment configuration
β βββ package.json
βββ some-notes.txt # Local reference notes
βββ package.json # Root package for production builds & deployment
βββ README.md # Project documentation
- Node.js: v18.0.0 or higher
- MongoDB: Local MongoDB instance or MongoDB Atlas Cluster connection string
- Google Cloud Console Account: OAuth 2.0 Client ID setup
Create a .env file in the backend/ directory:
PORT=5001
MONGO_URI=mongodb+srv://<username>:<password>@cluster.mongodb.net/thinkboard?retryWrites=true&w=majority
JWT_SECRET=your_super_secret_jwt_key_here
GOOGLE_CLIENT_ID=your_google_client_id.apps.googleusercontent.com
# Optional: Upstash Redis Rate Limiting Configuration
UPSTASH_REDIS_REST_URL=https://your-redis-url.upstash.io
UPSTASH_REDIS_REST_TOKEN=your_upstash_redis_token
NODE_ENV=developmentCreate a .env file in the frontend/ directory:
VITE_GOOGLE_CLIENT_ID=your_google_client_id.apps.googleusercontent.com
VITE_API_URL=http://localhost:5001/api-
Clone the Repository
git clone https://github.com/taher-dev/thinkboard-mern.git cd mern-thinkboard -
Install Dependencies Run from the root directory to install dependencies for both frontend and backend:
npm run build
Or install individually:
npm install --prefix backend npm install --prefix frontend
-
Start Development Servers Open two terminal windows to run both servers concurrently:
Terminal 1 (Backend Server):
cd backend npm run devTerminal 2 (Frontend Server):
cd frontend npm run dev- Frontend App:
http://localhost:5173 - Backend API:
http://localhost:5001/api
- Frontend App:
- Navigate to the Google Cloud Console Credentials Page.
- Create an OAuth 2.0 Client ID (Application type: Web application).
- Add Authorized JavaScript Origins:
http://localhost:5173<your-frontend-url>
- Add Authorized Redirect URIs:
http://localhost:5173<your-frontend-url>
- Set your Client ID in
frontend/.env(VITE_GOOGLE_CLIENT_ID) andbackend/.env(GOOGLE_CLIENT_ID).
| Method | Endpoint | Access | Description |
|---|---|---|---|
POST |
/api/auth/guest |
Public | Initializes a temporary guest account |
POST |
/api/auth/google |
Public | Authenticates Google user & merges existing guest notes |
GET |
/api/auth/me |
Protected | Fetches currently logged-in user details |
| Method | Endpoint | Access | Description |
|---|---|---|---|
GET |
/api/notes |
Protected | Fetches all notes belonging to the logged-in user |
GET |
/api/notes/:id |
Protected | Fetches a specific note by ID (user ownership enforced) |
POST |
/api/notes |
Protected | Creates a new note for the logged-in user |
PUT |
/api/notes/:id |
Protected | Updates an existing note (user ownership enforced) |
DELETE |
/api/notes/:id |
Protected | Deletes a note (user ownership enforced) |
The project includes pre-configured vercel.json files for both frontend and backend deployments on Vercel.
- Import your project repository into Vercel as a new project.
- Set Root Directory to
backend. - Framework Preset: Other / Node.js.
- Configure Environment Variables in Vercel Project Settings:
MONGO_URIPORT=5001JWT_SECRETGOOGLE_CLIENT_IDUPSTASH_REDIS_REST_URLUPSTASH_REDIS_REST_TOKENNODE_ENV=productionCLIENT_URL=<your-frontend-url>
- Deploy backend app and copy the backend URL.
- Import your project repository into Vercel as a second project (or separate app).
- Set Root Directory to
frontend. - Framework Preset: Vite.
- Configure Build Command:
npm run buildand Output Directory:dist. - Configure Environment Variables in Vercel Project Settings:
VITE_GOOGLE_CLIENT_IDVITE_API_URL=<your-backend-url>
- Deploy frontend app and copy the frontend URL.
- Paste the frontend URL in the
CLIENT_URLenvironment variable of the backend app.
- Create a new Web Service on Render linked to your GitHub repository.
- Configure build settings:
- Build Command:
npm run build - Start Command:
npm start
- Build Command:
- Add Environment Variables in the Render Dashboard:
MONGO_URIJWT_SECRETGOOGLE_CLIENT_IDVITE_GOOGLE_CLIENT_IDNODE_ENV=productionUPSTASH_REDIS_REST_URLUPSTASH_REDIS_REST_TOKEN
This project is open source and available under the MIT License.