Skip to main content
Get your Portfolio Hub API up and running, create your first user account, and make authenticated API requests.

Prerequisites

Before you begin, ensure you have the following installed on your system:

Java 21 (JDK)

Required to run the Spring Boot application

Maven 3.9+

Build tool for managing dependencies

MySQL 8.0+

Database for storing portfolio data

Git

Version control for cloning the repository
You can verify your installations by running:
java -version
mvn -version
mysql --version

Step 1: Clone and Setup

1

Clone the repository

Clone the Portfolio Hub API repository to your local machine:
git clone https://github.com/LavenderEdit/Portfolio.git
cd Portfolio
2

Create MySQL database

Create a new MySQL database for the application:
mysql -u root -p
CREATE DATABASE studiostkoh.portafolio;
EXIT;
Flyway will automatically create all required tables when you first run the application.
3

Configure environment variables

Set up the required environment variables. Create a .env file or export them directly:
# Database Configuration
export MYSQL_HOST=localhost
export MYSQL_PORT=3306
export MYSQL_DATABASE=studiostkoh.portafolio
export MYSQL_USER=your_username
export MYSQL_PASSWORD=your_password

# JWT Configuration
export JWT_TOKEN=your_secret_key_at_least_256_bits_long_for_security
export JWT_EXPIRATION_TIME=60

# CORS Configuration
export CORS_ALLOWED_ORIGINS=http://localhost:3000
The JWT_TOKEN must be a strong, random string. Never use a simple password or commit this value to version control.

Step 2: Run the Application

Start the Portfolio Hub API server:
./mvnw spring-boot:run
You should see output similar to:
Started PortfolioApplication in 5.432 seconds (process running for 5.891)
The API is now running at http://localhost:8080
Access the interactive API documentation at: http://localhost:8080/swagger-ui/index.html

Step 3: Register Your First User

Create a new user account using the /api/auth/register endpoint:
curl -X POST http://localhost:8080/api/auth/register \
  -H "Content-Type: application/json" \
  -d '{
    "fullName": "John Doe",
    "email": "[email protected]",
    "password": "securePassword123"
  }'

Request Requirements

The RegisterRequest accepts the following fields:
FieldTypeValidationDescription
fullNamestring3-120 characters, requiredUser’s full name
emailstringValid email, max 150 characters, requiredUser’s email address
passwordstringMin 8 characters, max 100, requiredAccount password

Successful Response

{
  "success": true,
  "message": "Usuario registrado exitosamente",
  "data": {
    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
  },
  "timestamp": "2026-03-09T10:15:30.123Z"
}
The API automatically creates a profile for each new user and returns a JWT token that you can use immediately.

Step 4: Login to Your Account

Authenticate with your credentials to obtain a JWT token:
curl -X POST http://localhost:8080/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{
    "email": "[email protected]",
    "password": "securePassword123"
  }'

Successful Response

{
  "success": true,
  "message": "Login exitoso",
  "data": {
    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
  },
  "timestamp": "2026-03-09T10:20:45.456Z"
}
Store the JWT token securely. You’ll need to include it in the Authorization header for all authenticated requests.

Step 5: Make Your First Authenticated Request

Use the JWT token to access protected endpoints. Let’s fetch your profile:
curl -X GET http://localhost:8080/api/me/profile \
  -H "Authorization: Bearer YOUR_JWT_TOKEN_HERE"

Successful Response

{
  "success": true,
  "message": "Perfil obtenido exitosamente",
  "data": {
    "id": 1,
    "fullName": "John Doe",
    "slug": "john-doe",
    "tagline": null,
    "bio": null,
    "avatarUrl": null,
    "resumeUrl": null,
    "contactEmail": null
  },
  "timestamp": "2026-03-09T10:25:30.789Z"
}

Step 6: Update Your Profile

Now let’s update your profile with additional information:
curl -X PUT http://localhost:8080/api/me/profile \
  -H "Authorization: Bearer YOUR_JWT_TOKEN_HERE" \
  -H "Content-Type: application/json" \
  -d '{
    "tagline": "Full Stack Developer",
    "bio": "Passionate software engineer with 5+ years of experience",
    "location": "San Francisco, CA"
  }'

Successful Response

{
  "success": true,
  "message": "Perfil actualizado exitosamente",
  "data": {
    "id": 1,
    "fullName": "John Doe",
    "slug": "john-doe",
    "tagline": "Full Stack Developer",
    "bio": "Passionate software engineer with 5+ years of experience",
    "location": "San Francisco, CA",
    "avatarUrl": null,
    "resumeUrl": null,
    "contactEmail": null
  },
  "timestamp": "2026-03-09T10:30:15.234Z"
}

Next Steps

Congratulations! You’ve successfully set up Portfolio Hub API and made your first authenticated requests. Here’s what you can explore next:

Authentication

Learn about JWT tokens, security, and session management

API Reference

Explore all available endpoints and their usage

Managing Portfolios

Add projects, experiences, education, and skills

File Uploads

Upload avatars, resumes, and project images to Google Drive

Common Issues

Ensure MySQL is running and accessible on the configured host and port:
mysql -h localhost -u your_username -p
Check that the MYSQL_HOST, MYSQL_PORT, MYSQL_USER, and MYSQL_PASSWORD environment variables are correctly set.
JWT tokens expire based on the JWT_EXPIRATION_TIME setting (default: 60 minutes). If you receive a 401 Unauthorized error, login again to get a fresh token.
If you encounter Flyway migration issues, ensure your database schema is empty on first run. Flyway will create all necessary tables automatically.To reset the database:
DROP DATABASE studiostkoh.portafolio;
CREATE DATABASE studiostkoh.portafolio;
If port 8080 is already in use, you can change the server port by adding:
export SERVER_PORT=8081
Or add to application.properties:
server.port=8081

API Response Structure

All Portfolio Hub API endpoints return responses in a consistent format:
{
  success: boolean;      // Indicates if the request was successful
  message: string;       // Human-readable message
  data: T | null;        // Response data (type varies by endpoint)
  timestamp: string;     // ISO 8601 timestamp
}

Success Response Example

{
  "success": true,
  "message": "Perfil obtenido exitosamente",
  "data": { /* ... */ },
  "timestamp": "2026-03-09T10:15:30.123Z"
}

Error Response Example

{
  "success": false,
  "message": "Email already in use",
  "data": null,
  "timestamp": "2026-03-09T10:15:30.123Z"
}
Always check the success field before processing the data to ensure your request completed successfully.

Build docs developers (and LLMs) love