6.4 KiB
6.4 KiB
Blog Editor - Full Stack Application
A full-stack blog editor built with TipTap, React, Node.js, PostgreSQL, and AWS S3.
Features
- ✨ Rich text editor with TipTap
- 📝 Auto-save drafts every 10 seconds
- 🖼️ Image upload to AWS S3 with presigned URLs
- 🔐 Phone/OTP authentication (integrated with existing auth service)
- 📱 Mobile responsive UI
- 🎨 Rich formatting options (Bold, Italic, Underline, Headings, Lists, Quotes, Code blocks, Colors, Font sizes)
- 📄 Public blog pages
- 🎯 Dashboard for managing posts
Tech Stack
Frontend
- React 18
- Vite
- TipTap Editor
- Tailwind CSS
- React Router
- Axios
Backend
- Node.js
- Express
- PostgreSQL
- JWT + bcrypt
- AWS S3 SDK
Project Structure
blog-editor/
├── frontend/ # React + Vite application
│ ├── src/
│ │ ├── components/ # React components
│ │ ├── pages/ # Page components
│ │ ├── contexts/ # React contexts
│ │ ├── utils/ # Utility functions
│ │ └── extensions/ # TipTap extensions
│ └── package.json
├── backend/ # Express API
│ ├── config/ # Database and S3 config
│ ├── routes/ # API routes
│ ├── middleware/ # Auth middleware
│ ├── migrations/ # Database migrations
│ └── package.json
└── README.md
Setup Instructions
Prerequisites
- Node.js 18+
- PostgreSQL 12+
- AWS Account with S3 bucket
- AWS Access Key and Secret Key
Backend Setup
- Navigate to backend directory:
cd backend
- Install dependencies:
npm install
- Create
.envfile:
PORT=5000
DB_HOST=localhost
DB_PORT=5432
DB_NAME=blog_editor
DB_USER=postgres
DB_PASSWORD=your_password
AUTH_SERVICE_URL=http://localhost:3000
AWS_REGION=us-east-1
AWS_ACCESS_KEY_ID=your_access_key
AWS_SECRET_ACCESS_KEY=your_secret_key
S3_BUCKET_NAME=blog-editor-images
CORS_ORIGIN=http://localhost:4000
Note: The blog editor uses the existing auth service at G:\LivingAi\GITTEA_RPO\auth. Make sure:
- The auth service is running on port 3000 (or update
AUTH_SERVICE_URL) - Auth service uses its own separate database (not Supabase)
- Blog editor uses Supabase for storing posts
-
Configure Supabase database:
- Add your Supabase connection string to
.envasDATABASE_URL - Format:
postgresql://postgres.ekqfmpvebntssdgwtioj:[YOUR-PASSWORD]@aws-1-ap-south-1.pooler.supabase.com:5432/postgres - Replace
[YOUR-PASSWORD]with your actual Supabase password
- Add your Supabase connection string to
-
Run migrations:
npm run migrate
- Start the server:
npm run dev
The backend will run on http://localhost:5001
Frontend Setup
- Navigate to frontend directory:
cd frontend
- Install dependencies:
npm install
- Create
.envfile:
cp .env.example .env
- Update
.env:
VITE_API_URL=http://localhost:5001
VITE_AUTH_API_URL=http://localhost:3000
Note: VITE_AUTH_API_URL should point to your existing auth service.
- Start the development server:
npm run dev
The frontend will run on http://localhost:4000
AWS S3 Setup
- Create an S3 bucket in your AWS account
- Configure CORS for the bucket:
[
{
"AllowedHeaders": ["*"],
"AllowedMethods": ["PUT", "POST", "GET"],
"AllowedOrigins": ["http://localhost:4000"],
"ExposeHeaders": []
}
]
-
Create an IAM user with S3 permissions:
s3:PutObjecton your buckets3:GetObjecton your bucket
-
Add the Access Key ID and Secret Access Key to your backend
.envfile
Database Schema
Note: Users are managed by the auth service in a separate database. The blog editor only stores user_id references.
Posts Table
id(UUID, Primary Key)user_id(UUID) - References user ID from auth service (no foreign key constraint)title(VARCHAR)content_json(JSONB) - TipTap editor content stored as JSONslug(VARCHAR, Unique) - URL-friendly post identifierstatus(VARCHAR: 'draft' or 'published')created_at(TIMESTAMP)updated_at(TIMESTAMP) - Auto-updated via trigger
API Endpoints
Authentication (Handled by Existing Auth Service)
The blog editor uses the existing auth service at G:\LivingAi\GITTEA_RPO\auth:
POST /auth/request-otp- Request OTP for phone numberPOST /auth/verify-otp- Verify OTP and get tokensPOST /auth/refresh- Refresh access tokenPOST /auth/logout- Logout userPOST /auth/validate-token- Validate JWT token (used by blog editor backend)
Posts
GET /api/posts- Get all posts for current user (protected)GET /api/posts/:id- Get single post (protected)GET /api/posts/slug/:slug- Get post by slug (public)POST /api/posts- Create new post (protected)PUT /api/posts/:id- Update post (protected)DELETE /api/posts/:id- Delete post (protected)
Upload
POST /api/upload/presigned-url- Get presigned URL for image upload (protected)
Pages
/login- Login page (Phone/OTP authentication)/dashboard- User dashboard (protected)/editor- Create new post (protected)/editor/:id- Edit existing post (protected)/blog/:slug- Public blog post view
Deployment
Backend (AWS EC2)
- Set up EC2 instance
- Install Node.js and PostgreSQL
- Clone repository
- Set environment variables
- Run migrations
- Use PM2 or similar to run the server:
pm2 start server.js --name blog-editor-api
Frontend (AWS Amplify or Vercel)
AWS Amplify:
- Connect your repository
- Set build settings:
- Build command:
npm run build - Output directory:
dist
- Build command:
- Add environment variable:
VITE_API_URL
Vercel:
- Import your repository
- Set build command:
npm run build - Add environment variable:
VITE_API_URL
Environment Variables
Backend
PORT- Server port (default: 5000)DB_HOST- PostgreSQL hostDB_PORT- PostgreSQL portDB_NAME- Database nameDB_USER- Database userDB_PASSWORD- Database passwordAUTH_SERVICE_URL- URL of existing auth service (default: http://localhost:3000)AWS_REGION- AWS regionAWS_ACCESS_KEY_ID- AWS access keyAWS_SECRET_ACCESS_KEY- AWS secret keyS3_BUCKET_NAME- S3 bucket nameCORS_ORIGIN- CORS allowed origin
Frontend
VITE_API_URL- Blog editor backend API URLVITE_AUTH_API_URL- Auth service API URL (default: http://localhost:3000)
License
MIT