Memoir Notes is a full-stack notes application for capturing ideas with minimal friction. Users sign up, sign in, and manage notes that belong only to them—each note supports a title, body, optional tags, and pinning for quick access. The app pairs a fast React SPA with a secure Express API backed by MongoDB, using JWT access tokens, httpOnly refresh cookies, and automatic token refresh when the access token expires.
- React – UI with function components and hooks.
- Vite – Dev server and production builds.
- TypeScript – Typed components and API layer.
- Tailwind CSS – Utility-first styling.
- React Router – Public vs protected routes, deep links to individual notes.
- Axios – HTTP client with
Authorizationheaders and refresh-retry logic. - Zod – Client-side validation aligned with API expectations.
- Sonner – Toast notifications.
- React Icons – Icon set.
- Node.js – Runtime.
- Express – REST API (
/api/auth,/api/user,/api/notes). - TypeScript – Typed controllers and middleware.
- Swagger/OpenAPI 3.0 – Interactive API documentation with swagger-jsdoc and swagger-ui-express.
- MongoDB + Mongoose – User and note persistence.
- JWT – Short-lived access tokens; refresh tokens stored server-side and in httpOnly cookies.
- bcrypt – Password hashing.
- Zod – Request validation on create/update flows.
- Upstash Redis – Sliding-window rate limits on auth endpoints via @upstash/ratelimit.
- cookie-parser & cors – Cookies and cross-origin configuration for the SPA.
- Authentication – Sign up and login with validated payloads; access token in memory (
localStorage); refresh token in an httpOnly cookie. - Session resilience – Axios interceptor calls
/auth/refreshon 401 and retries the original request when refresh succeeds. - Notes CRUD – List, create, read, update, and delete notes scoped to the logged-in user.
- Rich note metadata – Optional tags and pinned notes for organization.
- Protected experience – Landing, login, and signup are public; the home grid and single-note views require auth.
- Rate limiting – Auth routes are throttled to reduce brute-force and abuse (Upstash).
Interactive API documentation is available via Swagger UI when the backend is running:
- Development: http://localhost:5001/api-docs
- Production: https://memoir-notes-production.up.railway.app/api-docs
The documentation includes:
- Complete endpoint specifications (Auth, Users, Notes, Health)
- Request/response schemas with examples
- Interactive "Try it out" feature for testing endpoints
- JWT authentication integration
Tip: Use the "Authorize" button in Swagger UI to add your access token and test protected endpoints.
Note: Access tokens expire after 15 minutes. Use
/api/auth/refreshto get a new token or re-login.
You need Node.js (compatible with the versions pinned in each package) and a MongoDB deployment (local or Atlas). For rate limiting, create a free Upstash Redis database—the SDK reads credentials from environment variables.
git clone https://github.com/Pappyjay23/memoir-notes.gitcd memoir-notescd backend
npm installCreate backend/.env:
# Server
PORT=5001
# CORS – set to your frontend origin (Vite default shown)
CLIENT_URL=http://localhost:5173
# Database
MONGODB_URI=mongodb://localhost:27017/memoir-notes
# or your MongoDB Atlas connection string
# JWT – use long random strings in production
JWT_ACCESS_SECRET=your_access_secret
JWT_REFRESH_SECRET=your_refresh_secret
# Optional overrides (defaults: 15m access, 7d refresh)
# JWT_ACCESS_TOKEN_EXPIRES_IN=15m
# JWT_REFRESH_TOKEN_EXPIRES_IN=7d
# Upstash Redis (from Upstash dashboard – required for auth rate limiting)
UPSTASH_REDIS_REST_URL=https://YOUR_INSTANCE.upstash.io
UPSTASH_REDIS_REST_TOKEN=your_tokenStart the API:
npm run devThe server listens on http://localhost:5001 by default (GET / responds with a simple health JSON).
Production build:
npm run build
npm startOpen a second terminal:
cd frontend
npm installCreate frontend/.env:
# Must match the API mount path (see server.ts: /api/auth, /api/notes, …)
VITE_MEMOIR_API_URL=http://localhost:5001/apiStart the Vite dev server:
npm run devOpen http://localhost:5173 (or the URL Vite prints). Ensure the backend is running so login and notes requests succeed.
Production build:
npm run build
npm run preview| Path | Role |
|---|---|
frontend/ |
React + Vite SPA |
backend/ |
Express API, MongoDB, auth & rate limits |
There is no root-level package.json; install and run each package separately.
Implementation by Peace Jinadu-Paul