MERN Stack Blog Platform
overview
A full stack blog platform using the MERN stack with Next.js replacing Create React App for server-side rendering and improved SEO. Authors can write in Markdown with a live split-pane preview the left pane shows raw Markdown, the right renders the output in real time via a debounced event listener.
The backend is an Express.js REST API with Mongoose ODM providing schema validation and typed document models. Posts, authors, tags, and comments are modelled as separate collections with references rather than embedded documents this keeps individual documents small and makes tag/author queries efficient. JWT authentication is issued on login and validated as Bearer tokens on protected endpoints.
Next.js provides server-side rendering for published posts, which means post content is in the HTML at request time for search engine indexing. The editor interface is a pure client-side SPA for fast interactive feedback. Static generation is used for the homepage and tag listing pages.
architecture
Next.js Frontend
├── SSR: /posts/[slug] (published post pages)
├── SSG: / (homepage, tag pages)
└── SPA: /editor (Markdown editor, real-time preview)
│
▼
Express.js REST API
├── POST /auth/login (JWT issue)
├── GET /posts (list, filter by tag)
├── GET /posts/:slug (single post)
├── POST /posts (create auth required)
└── PUT /posts/:slug (update auth required)
│
▼
Mongoose ODM
│
▼
MongoDB
├── posts { title, slug, content, tags[], authorId }
├── authors { name, bio, avatarUrl }
└── tags { name, slug, count }technical.decisions
Blog post content needs to be in the HTML at request time for search engine indexing. Create React App renders on the client, meaning crawlers see an empty shell. Next.js getServerSideProps fetches the post and embeds it in the HTML published posts are fully indexable without a separate SSR server.
Embedding all post data in a single MongoDB document (including comments, tags, author) would grow documents unboundedly and make cross-collection queries expensive. Separate collections with ObjectId references keeps document sizes predictable and allows efficient tag and author queries with populate().
Parsing Markdown on every keypress is CPU-intensive for long documents. A 150ms debounce on the input event balances responsiveness with performance the preview updates fast enough to feel real-time while avoiding parser invocations on every keystroke.
outcomes
- Published posts fully server-side rendered for SEO
- Real-time Markdown preview with 150ms debounce
- Reference-based schema keeps document sizes predictable
- JWT auth with Bearer token pattern for protected endpoints