A production-ready MERN stack blog platform for software engineers and AI practitioners. Dark-first editorial design, AI-assisted authoring, full SEO optimization, and JWT-secured admin dashboard.
πΈ Add screenshots or a live demo link here once deployed.
Suggested screenshots:
- Homepage hero section
- Blog listing page with filters
- Individual post with TL;DR, code highlighting, comments
- Dashboard new-post editor with AI assist panel
- Mobile responsive views
| Layer | Technology |
|---|---|
| Frontend | React 18, Vite, Tailwind CSS, React Router v6 |
| Data Layer | TanStack React Query v5 |
| Rich Text Editor | TipTap (with code block syntax highlighting) |
| SEO | React Helmet Async, JSON-LD, Open Graph |
| Backend | Node.js, Express.js |
| Database | MongoDB Atlas (Mongoose ODM) |
| Auth | JWT (access + refresh token rotation) |
| AI | OpenAI API (gpt-4o-mini) |
| Rate Limiting | express-rate-limit |
| Validation | Joi |
| Deployment | Frontend β Vercel, Backend β Render/Railway |
blogapp/
βββ frontend/ # React + Vite app
β βββ src/
β β βββ pages/ # Route-level page components
β β β βββ dashboard/ # Admin dashboard pages
β β βββ components/
β β β βββ ui/ # Layout, Navbar, Footer, ProtectedRoute, SEOHead
β β β βββ blog/ # PostCard, NewsletterSignup
β β βββ hooks/ # useAuth (auth context)
β β βββ services/ # api.js (axios + all service functions)
β β βββ utils/ # formatDate
β βββ vercel.json # SPA fallback config
β βββ .env.example
β
βββ backend/ # Express.js REST API
βββ src/
β βββ config/ # db.js (MongoDB connection)
β βββ models/ # Mongoose models
β βββ controllers/ # Route handlers
β βββ routes/ # Express routers
β βββ middleware/ # auth, admin, errorHandler, rateLimiter
β βββ services/ # aiService.js (OpenAI)
β βββ validators/ # Joi schemas
β βββ utils/ # slugify, readTime
βββ db/
β βββ seed.js # Database seeder (3 sample posts)
βββ server.js
βββ .env.example
git clone https://github.com/AbhisharSingh/blogapp.git
cd blogapp
# Install backend deps
cd backend && npm install
# Install frontend deps
cd ../frontend && npm install
Backend β copy and edit:
cd backend
cp .env.example .env
# Edit .env with your values
Frontend β copy and edit:
cd frontend
cp .env.example .env
# Edit .env with your backend URL
cd backend
SEED_ADMIN_PASSWORD=YourSecurePassword123! npm run seed
This creates:
admin@blogapp.dev, password: value of SEED_ADMIN_PASSWORD# Terminal 1 β Backend
cd backend
npm run dev # starts on http://localhost:5000
# Terminal 2 β Frontend
cd frontend
npm run dev # starts on http://localhost:5173
Open http://localhost:5173 in your browser.
backend/.env)| Variable | Description | Required |
|---|---|---|
PORT | Server port (default: 5000) | No |
MONGO_URI | MongoDB connection string | Yes |
JWT_SECRET | Secret for access tokens | Yes |
JWT_REFRESH_SECRET | Secret for refresh tokens | Yes |
JWT_EXPIRE | Access token TTL (default: 15m) | No |
JWT_REFRESH_EXPIRE | Refresh token TTL (default: 7d) | No |
OPENAI_API_KEY | OpenAI API key for AI features | No |
FRONTEND_URL | Allowed CORS origin(s), comma-separated | No |
NODE_ENV | development or production | No |
CLOUDINARY_CLOUD_NAME | Cloudinary cloud name | No |
CLOUDINARY_API_KEY | Cloudinary API key | No |
CLOUDINARY_API_SECRET | Cloudinary API secret | No |
frontend/.env)| Variable | Description | Required |
|---|---|---|
VITE_API_URL | Backend API base URL | Yes |
Base URL: http://localhost:5000/api
All error responses follow: { "success": false, "message": "..." }
| Method | Endpoint | Description |
|---|---|---|
| GET | /health | Health check |
| Method | Endpoint | Body | Auth |
|---|---|---|---|
| POST | /auth/register | { name, email, password } | β |
| POST | /auth/login | { email, password } | β |
| POST | /auth/refresh | { refreshToken } | β |
| POST | /auth/logout | { refreshToken } | β |
| Method | Endpoint | Query Params | Auth |
|---|---|---|---|
| GET | /posts | page, limit, category, tag, status | β |
| GET | /posts/search | q (search query) | β |
| GET | /posts/:slug | β | β |
| POST | /posts | β | Admin |
| PUT | /posts/:id | β | Admin |
| DELETE | /posts/:id | β | Admin |
Create/Update Post body:
{
"title": "string",
"excerpt": "string (max 300)",
"content": "HTML string",
"category": "string",
"tags": ["tag1", "tag2"],
"status": "draft|published",
"coverImage": { "url": "string", "alt": "string" },
"metaTitle": "string (max 60)",
"metaDescription": "string (max 160)",
"keywords": ["kw1", "kw2"],
"tldr": ["point 1", "point 2", "point 3"]
}
| Method | Endpoint | Description |
|---|---|---|
| GET | /categories | Get all categories |
| GET | /tags | Get all tags with counts |
| Method | Endpoint | Body | Auth |
|---|---|---|---|
| GET | /posts/:id/comments | β | β |
| POST | /posts/:id/comments | { authorName, email, content } | β |
| DELETE | /comments/:id | β | Admin |
| Method | Endpoint | Body |
|---|---|---|
| POST | /newsletter/subscribe | { email } |
| Method | Endpoint | Body | Description |
|---|---|---|---|
| POST | /ai/generate | { topic, tone } | Generate full draft |
| POST | /ai/improve | { paragraph, instruction? } | Rewrite paragraph |
| POST | /ai/seo | { content, title } | Generate SEO meta |
| POST | /ai/tags | { content, title } | Suggest tags |
| POST | /ai/summary | { content } | Generate TL;DR |
readWrite role0.0.0.0/0 (or your Render/Railway IP)MONGO_URIbackendnpm installnode server.jsbackend/.env.example/api/healthbackendPORT variable (Railway auto-detects)frontendVITE_API_URL=https://your-backend.onrender.com/apivercel.json handles SPA routing fallback automatically.env.example for both frontend and backend9 commits
2 commits
JavaScript
95.0%
CSS
4.6%
A production-ready MERN stack blog platform for software engineers and AI practitioners. Dark-first editorial design, AI-assisted authoring, full SEO optimization, and JWT-secured admin dashboard.
πΈ Add screenshots or a live demo link here once deployed.
Suggested screenshots:
- Homepage hero section
- Blog listing page with filters
- Individual post with TL;DR, code highlighting, comments
- Dashboard new-post editor with AI assist panel
- Mobile responsive views
| Layer | Technology |
|---|---|
| Frontend | React 18, Vite, Tailwind CSS, React Router v6 |
| Data Layer | TanStack React Query v5 |
| Rich Text Editor | TipTap (with code block syntax highlighting) |
| SEO | React Helmet Async, JSON-LD, Open Graph |
| Backend | Node.js, Express.js |
| Database | MongoDB Atlas (Mongoose ODM) |
| Auth | JWT (access + refresh token rotation) |
| AI | OpenAI API (gpt-4o-mini) |
| Rate Limiting | express-rate-limit |
| Validation | Joi |
| Deployment | Frontend β Vercel, Backend β Render/Railway |
blogapp/
βββ frontend/ # React + Vite app
β βββ src/
β β βββ pages/ # Route-level page components
β β β βββ dashboard/ # Admin dashboard pages
β β βββ components/
β β β βββ ui/ # Layout, Navbar, Footer, ProtectedRoute, SEOHead
β β β βββ blog/ # PostCard, NewsletterSignup
β β βββ hooks/ # useAuth (auth context)
β β βββ services/ # api.js (axios + all service functions)
β β βββ utils/ # formatDate
β βββ vercel.json # SPA fallback config
β βββ .env.example
β
βββ backend/ # Express.js REST API
βββ src/
β βββ config/ # db.js (MongoDB connection)
β βββ models/ # Mongoose models
β βββ controllers/ # Route handlers
β βββ routes/ # Express routers
β βββ middleware/ # auth, admin, errorHandler, rateLimiter
β βββ services/ # aiService.js (OpenAI)
β βββ validators/ # Joi schemas
β βββ utils/ # slugify, readTime
βββ db/
β βββ seed.js # Database seeder (3 sample posts)
βββ server.js
βββ .env.example
git clone https://github.com/AbhisharSingh/blogapp.git
cd blogapp
# Install backend deps
cd backend && npm install
# Install frontend deps
cd ../frontend && npm install
Backend β copy and edit:
cd backend
cp .env.example .env
# Edit .env with your values
Frontend β copy and edit:
cd frontend
cp .env.example .env
# Edit .env with your backend URL
cd backend
SEED_ADMIN_PASSWORD=YourSecurePassword123! npm run seed
This creates:
admin@blogapp.dev, password: value of SEED_ADMIN_PASSWORD# Terminal 1 β Backend
cd backend
npm run dev # starts on http://localhost:5000
# Terminal 2 β Frontend
cd frontend
npm run dev # starts on http://localhost:5173
Open http://localhost:5173 in your browser.
backend/.env)| Variable | Description | Required |
|---|---|---|
PORT | Server port (default: 5000) | No |
MONGO_URI | MongoDB connection string | Yes |
JWT_SECRET | Secret for access tokens | Yes |
JWT_REFRESH_SECRET | Secret for refresh tokens | Yes |
JWT_EXPIRE | Access token TTL (default: 15m) | No |
JWT_REFRESH_EXPIRE | Refresh token TTL (default: 7d) | No |
OPENAI_API_KEY | OpenAI API key for AI features | No |
FRONTEND_URL | Allowed CORS origin(s), comma-separated | No |
NODE_ENV | development or production | No |
CLOUDINARY_CLOUD_NAME | Cloudinary cloud name | No |
CLOUDINARY_API_KEY | Cloudinary API key | No |
CLOUDINARY_API_SECRET | Cloudinary API secret | No |
frontend/.env)| Variable | Description | Required |
|---|---|---|
VITE_API_URL | Backend API base URL | Yes |
Base URL: http://localhost:5000/api
All error responses follow: { "success": false, "message": "..." }
| Method | Endpoint | Description |
|---|---|---|
| GET | /health | Health check |
| Method | Endpoint | Body | Auth |
|---|---|---|---|
| POST | /auth/register | { name, email, password } | β |
| POST | /auth/login | { email, password } | β |
| POST | /auth/refresh | { refreshToken } | β |
| POST | /auth/logout | { refreshToken } | β |
| Method | Endpoint | Query Params | Auth |
|---|---|---|---|
| GET | /posts | page, limit, category, tag, status | β |
| GET | /posts/search | q (search query) | β |
| GET | /posts/:slug | β | β |
| POST | /posts | β | Admin |
| PUT | /posts/:id | β | Admin |
| DELETE | /posts/:id | β | Admin |
Create/Update Post body:
{
"title": "string",
"excerpt": "string (max 300)",
"content": "HTML string",
"category": "string",
"tags": ["tag1", "tag2"],
"status": "draft|published",
"coverImage": { "url": "string", "alt": "string" },
"metaTitle": "string (max 60)",
"metaDescription": "string (max 160)",
"keywords": ["kw1", "kw2"],
"tldr": ["point 1", "point 2", "point 3"]
}
| Method | Endpoint | Description |
|---|---|---|
| GET | /categories | Get all categories |
| GET | /tags | Get all tags with counts |
| Method | Endpoint | Body | Auth |
|---|---|---|---|
| GET | /posts/:id/comments | β | β |
| POST | /posts/:id/comments | { authorName, email, content } | β |
| DELETE | /comments/:id | β | Admin |
| Method | Endpoint | Body |
|---|---|---|
| POST | /newsletter/subscribe | { email } |
| Method | Endpoint | Body | Description |
|---|---|---|---|
| POST | /ai/generate | { topic, tone } | Generate full draft |
| POST | /ai/improve | { paragraph, instruction? } | Rewrite paragraph |
| POST | /ai/seo | { content, title } | Generate SEO meta |
| POST | /ai/tags | { content, title } | Suggest tags |
| POST | /ai/summary | { content } | Generate TL;DR |
readWrite role0.0.0.0/0 (or your Render/Railway IP)MONGO_URIbackendnpm installnode server.jsbackend/.env.example/api/healthbackendPORT variable (Railway auto-detects)frontendVITE_API_URL=https://your-backend.onrender.com/apivercel.json handles SPA routing fallback automatically.env.example for both frontend and backend9 commits
2 commits
JavaScript
95.0%
CSS
4.6%