Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

10 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ThinkBoard

Don't just think it. Note it.

A minimal, fast note-taking application built on the MERN stack. ThinkBoard provides a clean interface for creating, editing, and organising short notes, backed by a REST API with distributed rate limiting.

Live at: https://thinkboardpro.onrender.com/

React Node.js Express MongoDB Vite


Table of Contents


Live Demo

A hosted instance is available at https://thinkboardpro.onrender.com/.

The demo runs on Render's free tier, so the first request after a period of inactivity may take a few seconds while the service wakes up. Notes created there are public — see Security Considerations.


Features

  • Full CRUD for notes — create, read, update, and delete notes through a REST API.
  • Responsive UI — built with React 19, Tailwind CSS v4, and daisyUI; adapts from mobile to widescreen.
  • Distributed rate limiting — Upstash Redis sliding-window limiter protects the API from request floods.
  • Graceful degradation — dedicated UI states for loading, empty results, and rate-limited responses.
  • Toast notifications — immediate feedback on every mutation via react-hot-toast.
  • Single-service deployment — in production the Express server also serves the compiled frontend, so the whole app runs as one process.

Tech Stack

Layer Technology
Frontend React 19, React Router 8, Vite 8, Tailwind CSS v4, daisyUI, Axios, Lucide icons
Backend Node.js, Express 4, Mongoose 7
Database MongoDB (MongoDB Atlas recommended)
Rate limiting Upstash Redis + @upstash/ratelimit
Tooling ESLint 10, nodemon

Project Structure

thinkboard/
├── backend/
│   └── src/
│       ├── config/
│       │   ├── db.js               # Mongoose connection bootstrap
│       │   └── upstash.js          # Upstash Redis rate-limiter instance
│       ├── controllers/
│       │   └── notesController.js  # Request handlers for note CRUD
│       ├── middleware/
│       │   └── rateLimiter.js      # Express rate-limiting middleware
│       ├── models/
│       │   └── notes.js            # Mongoose note schema
│       ├── routes/
│       │   └── notesRoutes.js      # /api/notes router
│       └── server.js               # App entry point
├── frontend/
│   ├── public/                     # Static assets
│   └── src/
│       ├── components/             # Navbar, NoteCard, loading & empty states
│       ├── lib/                    # Axios instance, date helpers
│       ├── pages/                  # Home, Create, Note detail
│       ├── App.jsx                 # Route definitions
│       └── main.jsx                # React entry point
└── package.json                    # Root build/start scripts

Prerequisites

  • Node.js 18 or later and npm
  • A MongoDB connection string (local instance or MongoDB Atlas)
  • An Upstash Redis database (REST URL and token) — required, as the rate limiter runs on every request

Getting Started

1. Clone the repository

git clone https://github.com/Alphax978/thinkboardv3.git
cd thinkboardv3

2. Configure environment variables

Create backend/.env using the template in Environment Variables. This file is git-ignored and must never be committed.

3. Install dependencies

npm install --prefix backend
npm install --prefix frontend

4. Run in development

Start the API server (defaults to port 5001):

npm run dev --prefix backend

In a second terminal, start the Vite dev server (defaults to port 5173):

npm run dev --prefix frontend

Open http://localhost:5173. In development the frontend targets http://localhost:5001/api, and the backend enables CORS for the Vite origin only.


Environment Variables

All backend configuration lives in backend/.env:

# MongoDB connection string
MONGO_URI=mongodb+srv://<user>:<password>@<cluster>/<database>

# Port for the Express server (optional, defaults to 5001)
PORT=5001

# Upstash Redis REST credentials for rate limiting
UPSTASH_REDIS_REST_URL=https://<your-database>.upstash.io
UPSTASH_REDIS_REST_TOKEN=<your-token>

# "development" or "production"
NODE_ENV=development
Variable Required Description
MONGO_URI Yes MongoDB connection string. The process exits on connection failure.
PORT No HTTP port for the API server. Defaults to 5001.
UPSTASH_REDIS_REST_URL Yes Upstash Redis REST endpoint used by the rate limiter.
UPSTASH_REDIS_REST_TOKEN Yes Upstash Redis REST token. Treat as a secret.
NODE_ENV Yes Controls CORS and static-file serving. Set to production when deploying.

The frontend requires no environment variables; it resolves its API base URL from Vite's build mode.


API Reference

Base path: /api/notes

Method Endpoint Description Request body
GET /api/notes List all notes, newest first
GET /api/notes/:id Fetch a single note by id
POST /api/notes Create a note { "title": string, "content": string }
PUT /api/notes/:id Update a note { "title": string, "content": string }
DELETE /api/notes/:id Delete a note

Note object

{
  "_id": "6532f1c8a4d3b2001f8e4a91",
  "title": "Meeting notes",
  "content": "Ship the release on Friday.",
  "createdAt": "2026-01-14T09:12:04.512Z",
  "updatedAt": "2026-01-14T09:12:04.512Z"
}

Status codes

Code Meaning
200 Request succeeded
201 Note created
404 Note not found
429 Rate limit exceeded — { "message": "Too many requests, try again later" }
500 Internal server error

Rate limiting

A sliding-window limiter allows 100 requests per 60 seconds and applies to every route. Exceeding it returns 429; the frontend surfaces this with a dedicated banner rather than a generic error.


Production Build

From the repository root:

npm run build   # installs backend + frontend deps, then builds the frontend
npm start       # starts the Express server

With NODE_ENV=production, the server serves frontend/dist as static files and falls back to index.html for client-side routes, so the API and the SPA are hosted on the same origin. The static path is resolved relative to the backend working directory — start the server with npm start from the repository root (or from backend/) so the path resolves correctly.


Security Considerations

This project is a learning-oriented reference implementation. Review the following before exposing it publicly:

  • No authentication or authorisation. Every note is globally readable and writable — anyone who can reach the API can read, edit, or delete any note. Add an auth layer and per-user ownership checks before hosting real data.
  • Rate limiting is global, not per-client. The limiter uses a single fixed key, so all traffic shares one 100 req/min budget. A single client can exhaust the quota for everyone. Key the limiter on client IP or authenticated user identity to fix this.
  • No server-side input validation. Length caps on title and content are enforced only in the browser and can be bypassed by calling the API directly. Add schema-level maxlength and request validation.
  • Dependencies need updating. npm audit currently reports known advisories in both workspaces, including a critical prototype-pollution issue in Mongoose 7.0.3 and multiple high-severity advisories in the Express 4.18.2 dependency tree. Run npm audit fix in backend/ and frontend/ and re-test.
  • Secrets stay out of version control. .env is git-ignored at every level. Rotate MONGO_URI and UPSTASH_REDIS_REST_TOKEN immediately if either is ever committed or shared.
  • Consider hardening headers. The server sets no security headers; adding helmet and enforcing HTTPS is recommended for any public deployment.

Roadmap

  • User accounts with per-user note ownership
  • Per-IP / per-user rate limiting
  • Server-side request validation
  • Search and tagging
  • Automated test suite and CI

Contributing

Contributions are welcome.

  1. Fork the repository and create a feature branch: git checkout -b feature/my-change
  2. Make your changes and run the linter: npm run lint --prefix frontend
  3. Commit with a descriptive message and open a pull request against main

License

Released under the ISC License.

About

One site to store all your thoughts and to-do's for the day

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages