Write once, publish everywhere. A modern full-stack application for syndicating blog posts across Medium, DEV.to, and WordPress.
- Multi-Platform Publishing: Publish to Medium, DEV.to, and WordPress from a single interface
- Rich Text Editor: Built-in TipTap editor with Markdown support and live preview
- User Authentication: Secure JWT-based authentication with role management
- Platform Credentials Management: Encrypted storage of API keys
- Tag Management: SEO-friendly tagging system for better discoverability
- Cover Images & Canonical URLs: Professional post metadata support
- MDX Export: Export posts as MDX files for static site generators
- Dark Mode: Built-in theme support with persistent preferences
- Real-time Updates: Live post status across all platforms
- Performance Optimized: Caching, memoization, and code splitting
- Responsive Design: Mobile-first UI with Tailwind CSS
Frontend:
- React 18 with Vite
- TypeScript support (strict mode, gradual migration; see
client/src/types/anddocs/ARCHITECTURE.md) - React Router v6 for routing
- Axios for API calls
- Tailwind CSS for styling
- TipTap for rich text editing
- React Markdown for preview
- React Icons (Feather Icons)
Backend:
- Node.js with Express
- TypeScript support (type-check only; see
server/src/types/anddocs/ARCHITECTURE.md). Full migration plan:docs/TS_MIGRATION_AND_CLEANUP_ROADMAP.md - MongoDB with Mongoose ODM
- JWT for authentication
- Joi for validation
- Bcrypt for password hashing
- Axios for external API calls
Infrastructure:
- MongoDB Atlas (database)
- Vercel/Railway (deployment options)
- GitHub (version control)
This project consists of two separate applications that can be developed, deployed, and run independently:
SyncApp/
βββ client/ # React frontend application (STANDALONE)
β βββ src/ # Frontend source code
β βββ README.md # Frontend setup guide
β βββ .env.example # Frontend environment template
β βββ package.json # Frontend dependencies
β βββ vite.config.js # Vite configuration
β
βββ server/ # Express backend API (STANDALONE)
β βββ src/ # Backend source code
β βββ README.md # Backend setup guide
β βββ env.example # Backend environment template
β βββ package.json # Backend dependencies
β
βββ scripts/ # Shared utility scripts
β βββ generate-keys.js # Generate encryption keys
β
βββ DEPLOYMENT.md # Deployment guide
βββ OPTIMIZATION.md # Performance optimization docs
βββ AUTHENTICATION.md # Authentication documentation
βββ WORDPRESS_INTEGRATION.md # WordPress setup guide
βββ API.md # API documentation
βββ CHANGELOG.md # Version history
βββ LICENSE # MIT License
βββ package.json # Root package (helper scripts only)
βββ README.md # This file
Note: The frontend and backend are independent applications. Each has its own:
package.jsonwith its own dependenciesREADME.mdwith setup instructions- Environment configuration files
- Can be deployed separately
- Can be developed independently
SyncApp consists of two separate applications that communicate via REST API:
- Frontend (Client) - React application
- Backend (Server) - Express API server
- Node.js: v22.0.0 or higher
- MongoDB: MongoDB Atlas account (or local MongoDB)
- Git: For version control
- API Keys (optional for publishing):
- Medium Integration Token
- DEV.to API Key
- WordPress Application Password
-
Clone the repository:
git clone https://github.com/FarukhSaifi/SyncApp.git cd SyncApp -
Install all dependencies:
npm run install:all
Or install separately:
cd client && npm install cd ../server && npm install
Frontend only:
cd client
npm installBackend only:
cd server
npm installSee server/README.md for detailed backend setup:
cd server
# Copy environment template
cp env.example .env
# Generate encryption keys (from root)
node ../scripts/generate-keys.js
# Edit .env with your MongoDB URI, JWT secret, and encryption keys
# Then setup database
npm run db:setup
# Start backend
npm run devBackend runs on: http://localhost:9000
See client/README.md for detailed frontend setup:
cd client
# Copy environment template
cp .env.example .env.local
# Edit .env.local with backend API URL (optional in dev, uses proxy)
# VITE_API_BACKEND_URL=http://localhost:9000/api
# Start frontend
npm run devFrontend runs on: http://localhost:3000
After installing both:
# Terminal 1: Start backend
cd server && npm run dev
# Terminal 2: Start frontend
cd client && npm run dev- Frontend: http://localhost:3000
- Backend API: http://localhost:9000
- Health Check: http://localhost:9000/health
Helper scripts for convenience:
npm run install:all- Install dependencies for both client and servernpm run install:client- Install client dependencies onlynpm run install:server- Install server dependencies only
npm start- Start server in production modenpm run dev- Start server with nodemon (auto-reload)npm run db:setup- Initialize database schemanpm run typecheck- Run TypeScript type-check (no emit)
See server/README.md for more details.
npm run dev- Start Vite dev server (port 3000)npm run build- Build for productionnpm run preview- Preview production buildnpm run lint- Run ESLintnpm run typecheck- Run TypeScript type-check (no emit)
See client/README.md for more details.
SyncApp includes a complete authentication system:
- User Registration: Create account with username, email, password
- User Login: JWT-based authentication
- Protected Routes: Routes require authentication
- Profile Management: Update user info, change password
- Session Management: Token stored in localStorage
- Role-Based Access: User/Admin roles (extensible)
See AUTHENTICATION.md for detailed documentation.
- Write posts in rich text or Markdown
- Add tags for better discoverability
- Upload cover images
- Set canonical URLs for SEO
- View all posts with filtering (all, published, drafts)
- Edit existing posts
- Delete posts
- Track publishing status across platforms
Medium:
- One-click publish to Medium
- Automatic author ID detection
- Track published URL and status
DEV.to:
- Publish with tags and cover images
- Support for canonical URLs
- Community engagement tracking
WordPress:
- Direct publication to WordPress sites
- Category assignment
- Custom post metadata
Multi-Platform:
- Publish to all platforms simultaneously
- Individual platform status tracking
- Error handling per platform
- Securely store API credentials (encrypted)
- Manage credentials for each platform
- Toggle platform activation
- Test connections
- Export posts as MDX files
- Frontmatter with metadata
- Compatible with static site generators
POST /api/auth/register- Create new accountPOST /api/auth/login- User loginGET /api/auth/me- Get current userPUT /api/auth/me- Update profilePUT /api/auth/change-password- Change password
GET /api/posts- List posts (paginated)GET /api/posts/:id- Get specific postGET /api/posts/slug/:slug- Get post by slugPOST /api/posts- Create post (auth required)PUT /api/posts/:id- Update post (auth required)DELETE /api/posts/:id- Delete post (auth required)
GET /api/credentials- List all credentialsGET /api/credentials/:platform- Get platform credentialsPUT /api/credentials/:platform- Save/update credentialsDELETE /api/credentials/:platform- Delete credentials
POST /api/publish/medium- Publish to MediumPOST /api/publish/devto- Publish to DEV.toPOST /api/publish/wordpress- Publish to WordPressPOST /api/publish/all- Publish to all platformsGET /api/publish/medium/status/:postId- Get status
GET /api/mdx/:id- Export post as MDX
GET /health- Health check with system info
See API.md for complete API documentation with examples.
SyncApp is optimized for performance with:
- Backend Caching: In-memory cache with TTL for frequently accessed data
- Database Optimization: Lean queries, proper indexing, field projection
- Frontend Memoization: React.memo for expensive components
- Code Splitting: Lazy loading for all routes
- Debouncing: Search and filter optimization
- Error Handling: Comprehensive error handling with custom error types
- Request Validation: Joi schemas for all inputs
- Logging: Structured logging with performance tracking
Performance Metrics:
- API Response Time: ~90ms (40% improvement)
- Dashboard Render: ~45ms (44% improvement)
- Bundle Size: ~280KB (38% reduction)
- Memory Usage: ~85MB (29% reduction)
See OPTIMIZATION.md for detailed information.
- Password Hashing: bcrypt with salt rounds
- JWT Tokens: Secure authentication with expiration
- API Key Encryption: AES-256-CBC encryption for stored credentials
- CORS Protection: Configurable origin restrictions
- Rate Limiting: Prevent abuse (100 requests per 15 minutes)
- Helmet.js: Security headers
- Input Validation: Joi schemas prevent injection attacks
- Environment Variables: Sensitive data in .env files
- Modern Design: Clean, professional interface with shadcn/ui components
- Dark Mode: Persistent theme switching
- Responsive: Mobile-first design works on all devices
- Toast Notifications: Real-time feedback for all actions
- Loading States: Clear feedback during operations
- Error Handling: User-friendly error messages
- Accessibility: ARIA labels and keyboard navigation
- API.md - Complete API reference
- DEPLOYMENT.md - Deployment guides for Vercel, Railway, etc.
- AUTHENTICATION.md - Authentication system documentation
- OPTIMIZATION.md - Performance optimization details
- WORDPRESS_INTEGRATION.md - WordPress setup guide
- CHANGELOG.md - Version history
Required variables in server/.env:
# Server
NODE_ENV=development
PORT=9000
# Database (Required)
MONGODB_URI=mongodb+srv://user:pass@cluster.mongodb.net/syncapp
# Authentication (Required)
JWT_SECRET=your_random_secure_string_min_32_chars
# Encryption (Required - generate with scripts/generate-keys.js)
ENCRYPTION_KEY=your_32_byte_hex_string
ENCRYPTION_IV=your_16_byte_hex_string
# CORS (Optional - defaults to localhost:3000)
CORS_ORIGIN=http://localhost:3000
# Rate Limiting (Optional)
RATE_LIMIT_WINDOW_MS=900000
RATE_LIMIT_MAX_REQUESTS=100
# Google Vertex AI (Optional for AI workflows)
# Local development: specify a file path
GOOGLE_APPLICATION_CREDENTIALS=./server/google-credentials.json
# Vercel deployment: paste exact JSON string contents to avoid uploading physical keys
GOOGLE_CREDENTIALS_JSON='{"type": "service_account", "project_id": "..."}'
# The default model is gemini-3-flash-preview. To override:
GOOGLE_AI_MODEL=gemini-3-flash-previewSee client/.env.example or client/README.md:
# API URL (optional - uses proxy in development)
VITE_API_BACKEND_URL=http://localhost:9000/api
# App Configuration (optional)
VITE_APP_NAME=SyncApp
VITE_APP_VERSION=2.0.0-
Server Health:
curl http://localhost:9000/health
-
Register User:
curl -X POST http://localhost:9000/api/auth/register \ -H "Content-Type: application/json" \ -d '{"username":"testuser","email":"test@example.com","password":"test123","firstName":"Test","lastName":"User"}'
-
Create Post:
- Login to app at http://localhost:3000
- Navigate to "New Post"
- Fill in title and content
- Save draft or publish
The frontend and backend are separate applications and should be deployed independently:
Option 1: Vercel (Recommended)
- See client/README.md for details
- Framework: Vite
- Build Command:
npm run build - Output Directory:
dist
Option 2: Netlify, Cloudflare Pages, or any static hosting
- Build with
npm run buildin theclient/directory - Deploy the
dist/folder
Option 1: Railway/Render
- See server/README.md for details
- Root Directory:
server - Build Command:
npm ci - Start Command:
npm start
Option 2: Heroku, AWS, or any Node.js hosting
- Deploy from the
server/directory - Set all environment variables
- Frontend requires
VITE_API_BACKEND_URLpointing to your deployed backend - Backend requires proper CORS configuration for your frontend URL
- Both can be deployed to different platforms/services
See DEPLOYMENT.md for detailed deployment instructions.
- Go to https://medium.com/me/settings
- Scroll to "Integration tokens"
- Generate token
- Add to SyncApp Settings
- Go to https://dev.to/settings/account
- Scroll to "API Keys"
- Generate API key
- Add to SyncApp Settings with your username
- Install JWT Authentication plugin
- Generate Application Password
- Add site URL and password to SyncApp Settings
See WORDPRESS_INTEGRATION.md for WordPress setup.
Contributions are welcome! Please follow these steps:
- Fork the repository
- Create a feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
- Follow the existing code style
- Add JSDoc comments for functions
- Write meaningful commit messages
- Test thoroughly before submitting
- Update documentation if needed
Server won't start:
- Check MongoDB connection string
- Ensure all environment variables are set
- Verify port 9000 is available
CORS errors:
- Update
CORS_ORIGINin server/.env - Ensure client and server ports match configuration
API calls fail:
- Verify Vite proxy is configured (development)
- Check server is running on port 9000
- Check browser console for detailed errors
Authentication issues:
- Clear localStorage and try again
- Check JWT_SECRET is set
- Verify token hasn't expired
Enable detailed logging:
Backend:
NODE_ENV=development npm run dev:serverFrontend: Open browser DevTools β Console for detailed API logs
GET http://localhost:9000/healthReturns:
{
"status": "OK",
"timestamp": "2025-01-01T00:00:00.000Z",
"uptime": 3600.5,
"environment": "development",
"database": {
"status": "connected",
"host": "cluster0.mongodb.net",
"name": "syncapp"
},
"services": {
"mongodb": "healthy",
"server": "healthy"
}
}- Image upload and management
- Post scheduling
- Draft autosave
- Collaborative editing
- Analytics dashboard
- Hashnode integration
- Ghost CMS support
- Social media sharing
- Email newsletter integration
- Advanced SEO tools
- Team collaboration
- Content calendar
- AI-powered writing assistance
- Multi-language support
- Mobile app
This project is licensed under the MIT License - see the LICENSE file for details.
- React - Frontend framework
- Express - Backend framework
- MongoDB - Database
- Tailwind CSS - CSS framework
- shadcn/ui - UI component inspiration
- Vite - Build tool
- Issues: GitHub Issues
- Discussions: GitHub Discussions
- Email: support@syncapp.com (if applicable)
Farukh Saifi
- GitHub: @FarukhSaifi
Made with β€οΈ for the developer community
SyncApp - Write once, publish everywhere π