Live API: my-blog-travel-app-backend.vercel.app
This is the REST API backend powering the Travel Blog App β a platform for sharing travel stories and experiences. It handles authentication, blog post management, and data persistence.
- From: Mallorca,Spain
- Hobbies: Traveling
A RESTful API that serves the Travel Blog App frontend. It manages users, posts, and media, providing secure endpoints for all core app features.
Built with [Node.js + Express], the backend exposes JSON endpoints consumed by the frontend. It connects to a MongoDB database and handles authentication via JWT tokens.
I wanted hands-on experience building a production-grade API from scratch β including auth, data modeling, error handling, and cloud deployment β to complement my frontend skills.
| Layer | Technology |
|---|---|
| Runtime | Node.js |
| Framework | Express |
| Database | MongoDB |
| Auth | JWT + bcrypt |
| Deployment | Vercel |
- Node.js
>= 18.x - npm
- A MongoDB (local or cloud)
# Clone the repository
git clone https://github.com/FD94/backend-BlogTravelApp
cd blog-travel-app-backend
# Install dependencies
npm install
# Set up environment variables
cp .env.example .env
# Edit .env with your values (see Environment Variables below)npm run devAPI will be available at http://localhost:5000
| Variable | Description |
|---|---|
DATABASE_URL |
MongoDB connection string or PostgreSQL URL |
JWT_SECRET |
Secret key for signing JWT tokens |
PORT |
Port to run the server |
FRONTEND_URL |
Allowed origin for CORS (e.g., https://blog-travel-app.vercel.app) |
π Routes marked as Protected require a valid JWT token in the
Authorizationheader:Authorization: Bearer <your_token>
| Method | Endpoint | Auth | Description |
|---|---|---|---|
POST |
/auth/signup |
Public | Register a new user |
POST |
/auth/login |
Public | Login and receive a JWT |
GET |
/auth/verify |
π Protected | Verify a JWT and return user payload |
Creates a new user account. Returns the user object and a signed JWT
Request body:
{
"name": "Jane Doe",
"email": "jane@example.com",
"password": "Secret123"
}Response 201:
{
"user": { "_id": "...", "email": "jane@example.com", "name": "Jane Doe" },
"authToken": "<jwt>"
}Authenticates an existing user. Returns a signed JWT
Request body:
{
"email": "jane@example.com",
"password": "Secret123"
}Response 200:
{
"authToken": "<jwt>"
}Verifies the JWT sent in the Authorization header and returns the decoded user payload.
Response 200:
{
"_id": "...",
"email": "jane@example.com",
"name": "Jane Doe"
}| Method | Endpoint | Auth | Description |
|---|---|---|---|
GET |
/posts |
Public | Get all posts |
GET |
/posts/:postId |
π Protected | Get a single post by ID |
POST |
/posts |
π Protected | Create a new post |
PUT |
/posts/:postId |
π Protected | Update a post by ID |
DELETE |
/posts/:postId |
π Protected | Delete a post by ID |
Returns a list of all blog posts.
Response 200:
[
{
"_id": "...",
"title": "My trip to Japan",
"description": "It was amazing...",
"image": "https://...",
"author": "..."
}
]Returns a single post by its ID.
Response 200:
{
"_id": "...",
"title": "My trip to Japan",
"description": "It was amazing...",
"image": "https://...",
"author": "..."
}Creates a new post. The author is automatically set from the JWT payload.
Request body:
{
"title": "My trip to Japan",
"description": "It was amazing...",
"image": "https://..."
}Response 201:
{
"_id": "...",
"title": "My trip to Japan",
"description": "It was amazing...",
"image": "https://...",
"author": "..."
}Updates an existing post by its ID. Returns the updated document.
Request body (any updatable fields):
{
"title": "Updated title",
"description": "Updated description"
}Response 200: Returns the updated post object.
Deletes a post by its ID. Returns the deleted document.
Response 200: Returns the deleted post object.
| Method | Endpoint | Auth | Description |
|---|---|---|---|
POST |
/comments |
π Protected | Add a comment to a post |
GET |
/comments/:postId |
Public | Get all comments for a post |
DELETE |
/comments/:commentId |
π Protected | Delete a comment (owner only) |
Creates a new comment on a post. The author is automatically set from the JWT payload.
Request body:
{
"text": "Great post!",
"post": "<postId>"
}Response 201: Returns the new comment populated with post and author data.
Returns all comments for a given post, with author and post populated.
Response 200:
[
{
"_id": "...",
"text": "Great post!",
"author": { "_id": "...", "name": "Jane Doe" },
"post": { "_id": "...", "title": "My trip to Japan" }
}
]Deletes a comment by its ID. Only the comment's author can delete it.
Response 200:
{ "message": "Comentario eliminado" }Response 403 if the requesting user is not the comment's author.
| Resource | URL |
|---|---|
| π Live API | my-blog-travel-app-backend.vercel.app |
| π Frontend App | blog-travel-app.vercel.app |
| π Frontend Repo | github.com/your-username/blog-travel-app |
Thank You for visiting!