A full-stack newsletter and subscription management system built with React and Node.js.

- 📧 Newsletter Subscription: Easy email subscription with validation
- 📰 Newsletter Archive: Browse and read published newsletters
- 🔐 Admin Dashboard: Secure admin interface for content management
- ✏️ Rich Content Editor: Support for both rich text (WYSIWYG) and Markdown editing
- 📱 Responsive Design: Works seamlessly on desktop and mobile
- 🚀 Modern Tech Stack: React, Node.js, MongoDB/PostgreSQL, Tailwind CSS
- 🔒 Security: JWT authentication, input validation, rate limiting
- 🗄️ Database Choice: Support for both MongoDB and PostgreSQL
- 🎨 Content Flexibility: Create newsletters with rich formatting, images, links, and more
- React 18 - Modern React with hooks
- React Router - Client-side routing
- React Query - Data fetching and caching
- React Hook Form - Form management
- Tailwind CSS - Utility-first CSS framework
- Lucide React - Beautiful icons
- React Hot Toast - Toast notifications
- ReactQuill - Rich text editor
- Marked - Markdown parsing (optional)
- React Markdown - Markdown rendering (optional)
- Remark GFM - GitHub Flavored Markdown support (optional)
- Rehype Raw & Sanitize - HTML processing and sanitization (optional)
- @hcaptcha/react-hcaptcha - hCaptcha integration for spam protection
- Node.js & Express - Server framework
- MongoDB & Mongoose - NoSQL database and ODM
- PostgreSQL & Sequelize - SQL database and ORM
- JWT - Authentication tokens
- bcryptjs - Password hashing
- Nodemailer - Email sending
- Helmet - Security middleware
- CORS - Cross-origin resource sharing
- Sanitize HTML - HTML content sanitization
- HTML-to-Text - Convert HTML to plain text for emails
- axios - Promise-based HTTP client for the browser and Node.js
newsletter/
├── package.json # Root package.json with dev scripts
├── package-lock.json # Root dependency lock file
├── backend/ # Node.js API server
│ ├── package.json # Backend dependencies
│ ├── package-lock.json # Backend dependency lock file
│ ├── config/ # Database configuration
│ ├── middleware/ # Auth and admin middleware
│ ├── models/ # Database models (MongoDB/PostgreSQL)
│ ├── routes/ # API routes
│ └── server.js # Express server entry point
├── frontend/ # React web application
│ ├── package.json # Frontend dependencies (includes optional markdown packages)
│ ├── package-lock.json # Frontend dependency lock file
│ ├── public/ # Static assets
│ └── src/
│ ├── components/ # Reusable React components
│ ├── pages/ # Page components (Admin.js contains editor)
│ ├── hooks/ # Custom React hooks
│ ├── utils/ # Utilities and API functions
│ └── styles/ # CSS and styling
└── shared/ # Shared utilities
Key Dependencies by Directory:
- Root: Development tools (concurrently for running both servers)
- Backend: Express, database ORMs, authentication, email sending
- Frontend: React, UI components, form handling, content editing (Rich Text + Markdown)
Important Files for CI/CD:
- package-lock.json files: Lock dependency versions for consistent builds
- Root package-lock.json: Controls development workflow dependencies
- Backend package-lock.json: Ensures consistent server-side dependencies
- Frontend package-lock.json: Locks client-side dependencies and build tools │ ├── hooks/ # Custom React hooks │ ├── utils/ # Utilities and API functions │ └── styles/ # CSS and styling └── shared/ # Shared utilities
## Getting Started
### Prerequisites
- Node.js (v16 or higher)
- Database: **MongoDB** (local installation or MongoDB Atlas) **OR** **PostgreSQL** (local installation or cloud service)
- npm or yarn package manager
### Installation
1. **Clone the repository**
```bash
git clone <repository-url>
cd newsletter
-
Install dependencies
# Install root dependencies (creates package-lock.json) npm install # Install backend dependencies (creates backend/package-lock.json) cd backend npm install # Install frontend dependencies (creates frontend/package-lock.json) cd ../frontend npm install # For markdown support (optional - if you want markdown editing capabilities) # These packages enable dual Rich Text / Markdown editor modes cd ../frontend npm install marked react-markdown remark-gfm rehype-raw rehype-sanitize npm install sanitize-html
Package Notes:
marked- Fast markdown parser and compilerreact-markdown- React component for rendering markdownremark-gfm- GitHub Flavored Markdown support (tables, task lists, etc.)rehype-raw- Allows raw HTML in markdownrehype-sanitize- Sanitizes HTML for security
Workflow Best Practices:
- Commit all
package-lock.jsonfiles to version control - Use
npm ciin production/CI environments for faster, reliable installs - Never manually edit
package-lock.jsonfiles
-
Environment Setup
Create a
.envfile in thebackenddirectory:PORT=5050 NODE_ENV=development CLIENT_URL=http://localhost:3030 # Database Configuration # Choose: 'mongodb' or 'postgresql' DATABASE_TYPE=mongodb # MongoDB Configuration (if using MongoDB) MONGODB_URI=mongodb://localhost:27017/newsletter # PostgreSQL Configuration (if using PostgreSQL) POSTGRES_HOST=localhost POSTGRES_PORT=5432 POSTGRES_DB=newsletter POSTGRES_USER=newsletter_user POSTGRES_PASSWORD=newsletter_password JWT_SECRET=your-super-secret-jwt-key # Email configuration (optional) SMTP_HOST=smtp.gmail.com SMTP_PORT=587 SMTP_USER=your-email@gmail.com SMTP_PASS=your-app-password FROM_EMAIL=your-email@gmail.com # hCaptcha configuration HCAPTCHA_SECRET=your-hcaptcha-secret-key
-
Database Setup
The application supports both MongoDB and PostgreSQL. Choose your preferred database:
For MongoDB:
- Set
DATABASE_TYPE=mongodbin your.envfile - Install MongoDB locally or use MongoDB Atlas (cloud)
For PostgreSQL:
- Set
DATABASE_TYPE=postgresqlin your.envfile - Install PostgreSQL locally or use a cloud service
See
MONGODB_SETUP.mdfor detailed database installation instructions. - Set
-
Start the Application
From the root directory:
# Start both frontend and backend concurrently npm run dev # Or start them separately: # Backend (from backend directory) npm run dev # Frontend (from frontend directory) npm start
-
Access the Application
- Frontend: http://localhost:3030
- Backend API: http://localhost:5050
GET /api/newsletters- Get all published newslettersGET /api/newsletters/:id- Get newsletter by IDPOST /api/subscriptions/subscribe- Subscribe to newsletterPOST /api/subscriptions/unsubscribe- Unsubscribe from newsletterGET /api/subscriptions/status/:email- Check subscription status
POST /api/auth/login- Admin loginPOST /api/auth/register- Admin registrationGET /api/newsletters/admin/all- Get all newsletters (including drafts)POST /api/newsletters- Create new newsletterPUT /api/newsletters/:id- Update newsletterDELETE /api/newsletters/:id- Delete newsletterGET /api/subscriptions/admin/all- Get all subscriptions
- Visit the homepage to browse newsletters
- Click on any newsletter to read the full content
- Use the subscribe page to join the mailing list
- Manage subscription status (subscribe/unsubscribe)
- Access the admin panel at
/admin - Login with admin credentials
- Manage newsletters (create, edit, delete, publish)
- Rich Text Mode: Use the WYSIWYG editor with formatting toolbar
- Markdown Mode: Write content in Markdown for faster, cleaner editing
- Preview: Real-time preview of your newsletter content
- View subscriber statistics
- Send newsletters to subscribers
- Dual Editor Modes: Switch between rich text and Markdown editing
- Live Preview: See how your newsletter will look before publishing
- Excerpt Support: Add brief descriptions for each newsletter
- Content Formatting: Headers, lists, links, images, code blocks, and more
- Email Optimization: Content is automatically optimized for email delivery
Root directory:
npm run dev- Start both frontend and backendnpm run server- Start backend onlynpm run client- Start frontend onlynpm run build- Build frontend for productionnpm run install-all- Install all dependenciesnpm ci- Clean install from package-lock.json (recommended for CI/CD)
Backend directory:
npm start- Start production servernpm run dev- Start development server with nodemonnpm ci- Clean install from package-lock.json
Frontend directory:
npm start- Start development servernpm run build- Build for productionnpm test- Run testsnpm ci- Clean install from package-lock.json
Backend environment variables (.env):
PORT- Server port (default: 5050)NODE_ENV- Environment (development/production)CLIENT_URL- Frontend URL for CORSDATABASE_TYPE- Database type ('mongodb' or 'postgresql')MONGODB_URI- MongoDB connection string (if using MongoDB)POSTGRES_*- PostgreSQL connection details (if using PostgreSQL)JWT_SECRET- Secret for JWT tokensSMTP_*- Email server configurationHCAPTCHA_SECRET- hCaptcha secret key for backend verification
Package Lock Files:
Each directory contains a package-lock.json file that locks exact dependency versions:
./package-lock.json- Development tools (concurrently, etc.)./backend/package-lock.json- Server dependencies./frontend/package-lock.json- React app and build dependencies
Production Deployment:
# Use npm ci for faster, reliable installs in production
npm ci # Install root dependencies
cd backend && npm ci # Install backend dependencies
cd ../frontend && npm ci # Install frontend dependencies
npm run build # Build frontend for productionDocker Considerations:
- Copy
package*.jsonfiles beforenpm cifor better layer caching - Use multi-stage builds to reduce final image size
- Set
NODE_ENV=productionfor optimized builds
- JWT-based authentication
- Password hashing with bcrypt
- Input validation and sanitization
- Rate limiting to prevent abuse
- CORS configuration
- Helmet for security headers
- Environment variable protection
Package Lock File Conflicts If you encounter dependency conflicts or inconsistent installs:
# Clean install from lock files (recommended)
npm ci
# Or if you need to regenerate lock files:
rm -rf node_modules package-lock.json
npm install
# For specific directories:
cd backend
rm -rf node_modules package-lock.json
npm install
cd ../frontend
rm -rf node_modules package-lock.json
npm installMarkdown Dependencies (Optional) If you encounter issues with markdown packages:
# Clear npm cache and reinstall
npm cache clean --force
cd frontend
rm -rf node_modules package-lock.json
npm install
npm install marked react-markdown remark-gfm rehype-raw rehype-sanitizeNode Version Compatibility
- Ensure Node.js v16 or higher is installed
- Check
.nvmrcfile if present for recommended Node version - Use
npm listto check for dependency conflicts
Database Connection Issues
- Ensure your database server is running
- Check connection string in
.envfile - For PostgreSQL, ensure the database and user exist
- For MongoDB, ensure MongoDB service is started
Port Conflicts If ports 3030 or 5050 are in use:
- Change
PORT=5050in backend.envfile - Update
REACT_APP_API_URLin frontend if needed
SMTP Email Issues
- Use app-specific passwords for Gmail
- Check firewall settings for SMTP ports
- Test SMTP settings with a simple email client first
hCaptcha Issues
- Ensure
HCAPTCHA_SECRETis set inbackend/.env - Verify hCaptcha site key is correctly used in the frontend
- Check network requests to hCaptcha for any errors
- Fork the repository
- Create a feature branch
- Make your changes
- Important: Commit package-lock.json files if dependencies changed
- Test your changes locally
- Submit a pull request
Always Commit These Files:
package.json(all directories)package-lock.json(all directories).env.example(environment template)
Never Commit These Files:
node_modules/(excluded by .gitignore).env(contains secrets)- Build artifacts (
frontend/build/)
Dependency Management:
- Use
npm install <package>to add new dependencies - Use
npm ciin CI/CD pipelines for consistent builds - Update
package-lock.jsonwhen changing dependencies - Document any new optional dependencies in README
This project is licensed under the MIT License.
For support or questions, please open an issue in the repository.
This project uses OpenCaptcha to prevent spam subscriptions.
Frontend & Backend:
cd frontend
C:\Users\marood\Documents\workspace\node-v22.18.0-win-x64\npm.cmd install axios
cd ../backend
C:\Users\marood\Documents\workspace\node-v22.18.0-win-x64\npm.cmd install axios- The subscription form in the frontend displays an OpenCaptcha image and input field.
- The backend verifies the OpenCaptcha solution before accepting subscriptions.
- CAPTCHA is always required for subscriptions (controlled by frontend display).
To control whether CAPTCHA is shown on the subscription form, set the following in frontend/.env:
REACT_APP_ENABLE_CAPTCHA=true # Show CAPTCHA (recommended)
REACT_APP_ENABLE_CAPTCHA=false # Hide CAPTCHA (not recommended for production)
The backend always requires CAPTCHA verification for subscriptions. The frontend controls whether the CAPTCHA widget is displayed to users.