This project serves as the robust Fullstack for the Legend4Tech personal portfolio, built with TypeScript, Next.js API Routes, and Server Actions. It manages dynamic content such as projects, certificates, tech stack items, and user comments, offering secure administrative functionalities and integration with external services like AWS S3 for file storage and Resend for email communications.
- Project Management: CRUD operations for portfolio projects, including details, technologies, features, and links.
- Certificate Management: CRUD operations for professional certifications, including images and external verification links.
- Tech Stack Management: CRUD operations for displaying technical skills, categorized and ordered for presentation.
- User Comments: Public comment submission and retrieval for portfolio engagement.
- Admin Authentication: Secure login and session management for administrators using Next-Auth (Auth.js v5) with credentials and Google OAuth.
- File Uploads: Direct image upload capabilities to AWS S3 for projects, certificates, and user avatars.
- Contact Form: Email handling via Resend for direct inquiries from the portfolio.
- GitHub Integration: Fetches merged pull requests from a specified GitHub username to showcase open-source contributions.
- First-Time Setup: Guided setup process to create the initial admin account securely.
To set up the project locally, follow these steps:
# Clone the repository
git clone https://github.com/legend4tech/portfolio-v1.git
# Navigate into the project directory
cd portfolio-v1
# Install dependencies using npm or yarn
npm install
# or
yarn installThe project requires the following environment variables to be configured. Create a .env.local file in the root directory and populate it with your specific values.
# AWS S3 Configuration for file uploads
MY_AWS_ACCESS_KEY=your_aws_access_key_id_here
AWS_SECRET_ACCESS_KEY=your_aws_secret_access_key_here
AWS_S3_BUCKET_NAME=your_s3_bucket_name_here
AWS_REGION=your_aws_region_here (e.g., eu-north-1)
# Resend API Key for sending emails
RESEND_API_KEY=your_resend_api_key_here
SENDER_EMAIL="Sender Name <sender@example.com>"
CONTACT_EMAIL=your_contact_email_address_here
# MongoDB Connection
MONGODB_URL=mongodb+srv://user:password@cluster.mongodb.net/database
MONGODB_DB=portfolio
# GitHub Integration
GITHUB_USERNAME=your_github_username_here
# Next-Auth (Auth.js v5) Secret
AUTH_SECRET="a_long_random_string_for_nextauth_jwt_signing"
# Admin Setup PIN (for initial admin user creation)
ADMIN_SETUP_PIN=Number
The API base URL is derived from the deployed application's root (e.g., https://your-portfolio.com/api).
Description: Handles secure uploading of image files to an AWS S3 bucket.
Request:
Content-Type: multipart/form-data
| Field | Type | Description | Required | Example |
|---|---|---|---|---|
file |
File |
The image file to be uploaded. | Yes | (binary file data) |
Response (200 OK):
{
"success": true,
"fileUrl": "https://legend4tech-portfolio.s3.eu-north-1.amazonaws.com/unique-image-id.jpg"
}Errors:
400 Bad Request: "No file provided", "Upload failed"500 Internal Server Error: "S3 upload failed: [error message]", "Failed to upload file: [error message]"
Description: Updates the profile information of the authenticated admin user.
Authentication: Requires an active admin session.
Request:
Content-Type: application/json
{
"name": "string",
"username": "string",
"email": "string",
"avatar": "string (URL, optional)",
"currentPassword": "string (required if newPassword is provided)",
"newPassword": "string (min 6 characters, optional)"
}Response (200 OK):
{
"success": true,
"message": "Profile updated successfully"
}Errors:
400 Bad Request: "Name is required", "Username is required", "Invalid email address", "Current password is required to set a new password", "Password must be at least 6 characters", "Current password is incorrect"401 Unauthorized: "Unauthorized"404 Not Found: "User not found"500 Internal Server Error: "Failed to update profile"
Description: Creates the first admin user account. This endpoint is only accessible if no admin user currently exists in the database.
Authentication: None (public for initial setup).
Request:
Content-Type: application/json
{
"name": "string",
"username": "string",
"email": "string",
"password": "string (min 6 characters)",
"avatar": "string (URL, optional)",
"secretPin": "string"
}Response (201 Created):
{
"success": true,
"userId": "string (ObjectId of the newly created admin user)"
}- Note: This endpoint also clears the
no_admin_existscookie upon successful setup.
Errors:
400 Bad Request: "Name is required", "Username is required", "Invalid email address", "Password must be at least 6 characters", "Secret PIN is required", "Admin already exists"403 Forbidden: "Invalid secret PIN"500 Internal Server Error: "Admin setup is not configured. Please set ADMIN_SETUP_PIN environment variable.", "Failed to create admin account"
Description: Retrieves a list of merged GitHub pull requests for the configured GITHUB_USERNAME.
Authentication: None (public endpoint).
Request: No request body.
Response (200 OK):
{
"success": true,
"data": [
{
"id": 12345,
"title": "string",
"url": "string (URL)",
"mergedAt": "string (ISO Date)",
"repository": "string",
"repositoryUrl": "string (URL)",
"labels": [
{
"name": "string",
"color": "string (hex color code without #)"
}
],
"closedIssues": [
{
"number": "string",
"url": "string (URL)"
}
],
"description": "string | null"
}
],
"count": "number"
}Errors:
500 Internal Server Error: "GitHub username not configured", "Failed to fetch pull requests"
The Legend4Tech Portfolio project leverages a modern and robust stack to deliver a seamless user experience and efficient content management.
| Category | Technology | Description |
|---|---|---|
| Frontend | Next.js | React framework for production, server-side rendering, and API routes. |
| React | JavaScript library for building user interfaces. | |
| TypeScript | Superset of JavaScript that adds static typing. | |
| Tailwind CSS | Utility-first CSS framework for rapid UI development. | |
| Shadcn/ui | Re-usable components built with Radix UI and Tailwind CSS. | |
| Framer Motion | Production-ready motion library for React. | |
| React Query | Powerful asynchronous state management for React. | |
| DotLottie React | React component for playing Lottie animations. | |
| Backend | Node.js | JavaScript runtime for server-side logic. |
| Next.js API Routes | API endpoints within the Next.js framework. | |
| Next-Auth (Auth.js) | Flexible authentication for Next.js applications. | |
| MongoDB | NoSQL document database for data storage. | |
| AWS S3 | Cloud object storage service for image uploads. | |
| Resend | Email API for developers. | |
| Development | ESLint | Pluggable JavaScript linter. |
| Prettier | Opinionated code formatter. | |
| Vercel Analytics | Real-time analytics for website performance. |
To run the application in development mode:
npm run dev
# or
yarn devOpen http://localhost:3000 in your browser to see the result. The application supports an admin dashboard for content management, accessible at /admin.
The first time you access /admin, you will be redirected to /admin/setup to create your initial admin account using the ADMIN_SETUP_PIN from your environment variables.
Contributions are welcome! If you have suggestions or find issues, please open an issue or submit a pull request.
- β Fork the repository.
- π‘ Create a new branch for your feature or bug fix.
- π οΈ Make your changes and ensure your code follows the project's coding standards.
- β Write clear commit messages.
- π Submit a pull request.
This project is licensed under the MIT License.
Developed with passion by Ajulu Dennis.
- π Website
- πΌ LinkedIn
- π¦ X (Twitter)
- π§ Email