Skip to main content

Overview

GitFolio gives you complete control over your portfolio content. While your initial data comes from GitHub, you can customize everything through the dashboard to create a portfolio that truly represents you.

Dashboard overview

The dashboard is organized into focused tabs for different content types:

Overview

Dashboard home with content summary and quick actions

Personal Info

Edit your profile details and bio

Projects

Manage which repositories appear in your portfolio

Experience

Add and edit work experience

Education

Showcase your educational background

Social Links

Connect your social media profiles

Skills

Highlight your technical skills

Templates

Choose and preview templates

Preview

See your live portfolio

Personal information

Customize your profile through the Personal Info tab:

Editable fields

interface PersonalInformation {
  full_name: string;      // Your display name
  tagline: string;        // Professional headline
  bio: string;            // About you section
  location: string;       // Your location
  profileImg: string;     // Profile picture URL
}
These fields are displayed prominently in your portfolio’s hero section.

Uploading profile images

You can upload a custom profile picture:
1

Click 'Edit Profile'

Open the Personal Info tab and click the Edit Profile button
2

Choose image

Click “Change Image” and select a file from your device (JPG, PNG, etc.)
3

Upload to S3

GitFolio uploads your image to AWS S3 for fast, reliable hosting:
// From dashboard/page.tsx
const uploadImage = async (params) => {
  // Get presigned URL from server
  const res = await fetch(config.server_endpoints.GET_PRESIGNED_URL, {
    method: "POST",
    body: JSON.stringify({
      type: "Personal Information",
      filename: "profile.jpg"
    })
  });
  const { url, link } = await res.json();
  
  // Upload directly to S3
  await fetch(url, { method: "PUT", body: imageFile });
  
  return link; // CDN URL for your image
};
4

Save changes

Click “Save Changes” to update your profile with the new image
Profile images are stored in S3 with the naming pattern: {userId}/Personal Information/profile.jpg

Project customization

Manage your portfolio projects in the Projects tab:

Project fields

Each project includes these customizable fields:
interface Projects {
  id: string;
  name: string;              // Project name
  description: string;       // Project description
  thumbnail: string;         // Project image/screenshot
  repoLink: string;          // GitHub repository URL
  liveLink: string;          // Live demo URL (optional)
  topics: string[];          // Tags/topics
  languages: object;         // Programming languages
  stars: number;             // GitHub stars (auto-synced)
  forks: number;             // GitHub forks (auto-synced)
  isIncluded: boolean;       // Show in portfolio?
}

Adding projects

Add custom projects not hosted on GitHub:
1

Click 'Add Project'

Navigate to the Projects tab and click the Add Project button
2

Fill in details

Required fields:
  • Project name
  • Description
  • Repository link
  • Thumbnail image
Optional fields:
  • Live demo URL
  • Topics/tags
3

Upload thumbnail

Choose an image file or paste an image URL:
<Input
  type="file"
  accept="image/*"
  onChange={handleFileChange}
/>
// OR
<Input
  placeholder="Or paste image URL"
  value={project.thumbnail}
/>
4

Add topics

Add relevant tags to help visitors understand the project:
const addTopic = () => {
  if (newTopic && !project.topics.includes(newTopic)) {
    setProject({
      ...project,
      topics: [...project.topics, newTopic.toLowerCase()]
    });
  }
};
5

Save project

Click “Save Changes” to add the project to your portfolio

Show/hide projects

Control project visibility with the toggle switch:
const toggleProject = (project: Projects) => {
  onSave({
    type: "Projects",
    data: { ...project, isIncluded: !project.isIncluded }
  });
};
Projects with isIncluded: false are hidden from your portfolio but remain in your dashboard.

Editing projects

Click any project card to edit:
  • Update project descriptions
  • Change thumbnails
  • Add or remove topics
  • Update live demo URLs
  • Modify repository links
GitFolio validates project data before saving:
const handleSaveProject = () => {
  if (!editingProject.thumbnail) {
    toast.warning("Please upload a thumbnail.");
    return;
  }
  if (!editingProject.description) {
    toast.warning("Please add a description.");
    return;
  }
  if (!editingProject.name) {
    toast.warning("Please add a Name.");
    return;
  }
  if (!editingProject.repoLink) {
    toast.warning("Please add Repo Link.");
    return;
  }
  // Save project...
};

Work experience

Add your professional experience in the Experience tab:

Experience fields

interface Experience {
  id: string;
  company: string;          // Company name
  role: string;             // Job title
  logo: string;             // Company logo URL
  description: string;      // Role description (min 10 chars)
  start_date: string;       // Format: "Month Year" (e.g., "June 2023")
  end_date: string;         // "Month Year" or "Present"
  onGoing: boolean;         // Currently working here?
}

Adding experience

1

Click 'Add Experience'

Open the Experience tab and click Add Experience
2

Enter details

Fill in:
  • Job role/title
  • Company name
  • Start date (month + year)
  • End date or check “Currently working here”
3

Upload logo

Add a company logo:
<Avatar className="h-20 w-20">
  <AvatarImage src={experience.logo} alt={experience.company} />
  <AvatarFallback>
    {experience.company.split(" ").map(n => n[0]).join("")}
  </AvatarFallback>
</Avatar>
<Button onClick={() => fileInput.click()}>Change Image</Button>
4

Write description

Describe your role and achievements (minimum 10 characters):
<Textarea
  placeholder="Describe your role and achievements..."
  rows={4}
  minLength={10}
/>
5

Save experience

Click “Add Experience” to save to your portfolio

Date selection

Experience dates use month + year dropdowns:
const handleDateChange = (type: "start" | "end", field: "month" | "year", value: string) => {
  const { month, year } = getDateParts(currentDate);
  const newMonth = field === "month" ? value : month;
  const newYear = field === "year" ? value : year;
  const newDate = [newMonth, newYear].filter(Boolean).join(" ");
  
  setExperience({
    ...experience,
    [type === "start" ? "start_date" : "end_date"]: newDate
  });
};

Current positions

Check “Currently working here” to set end_date: "Present":
<Checkbox
  id="ongoing"
  checked={experience.onGoing}
  onCheckedChange={(checked) => {
    setExperience({
      ...experience,
      onGoing: checked,
      end_date: checked ? "Present" : ""
    });
  }}
/>

Education

Showcase your educational background in the Education tab:

Education fields

interface Education {
  id: string;
  title: string;            // Degree/certificate name
  institution: string;      // School/university name
  logo: string;            // Institution logo
  description: string;     // Optional details (min 10 chars if provided)
  start_date: string;      // Year (e.g., "2019")
  end_date: string;        // Year or "Present"
  onGoing: boolean;        // Currently studying?
}

Adding education

Similar to experience, but uses years instead of month+year:
<Select value={education.start_date} onValueChange={(value) => setEducation({ ...education, start_date: value })}>
  <SelectTrigger><SelectValue placeholder="Start Year" /></SelectTrigger>
  <SelectContent>
    {YEARS.map(year => (
      <SelectItem key={year} value={year.toString()}>{year}</SelectItem>
    ))}
  </SelectContent>
</Select>
Education descriptions are optional, but if provided must be at least 10 characters.
Connect your social media profiles in the Social Links tab:
interface SocialLinks {
  twitter?: string;
  linkedin?: string;
  github?: string;
  website?: string;
  youtube?: string;
  instagram?: string;
  // Add any other social platforms
}
All social links must start with https://:
const invalidLinks = Object.entries(socialLinks).filter(
  ([_key, value]) => value && !value.startsWith("https://")
);

if (invalidLinks.length > 0) {
  toast.error("Please make sure the following links start with https://");
  return;
}

Skills

Highlight your technical skills in the Skills tab:
// Skills are stored as a string array
interface User {
  skills: string[];
}

// Example skills
const skills = [
  "TypeScript",
  "React",
  "Node.js",
  "PostgreSQL",
  "AWS"
];
You can add, remove, and reorder skills to match your expertise.

Data persistence

All customizations are saved to the database:
// From dashboard/page.tsx
const onSave = async ({ type, data }: SavePayload) => {
  const token = await getToken();
  
  // Upload images if needed
  if (hasImage) {
    const imageUrl = await uploadImage({ token, type, data });
    data = { ...data, [imageField]: imageUrl };
  }
  
  // Save to database
  const res = await fetch(endpoint, {
    method: "POST",
    headers: {
      authorization: `Bearer ${token}`,
      "Content-Type": "application/json"
    },
    body: JSON.stringify(data)
  });
  
  toast.success(`${type} saved successfully`);
};
Changes are reflected in your portfolio immediately after saving.

Deleting content

You can delete experience and education entries:
const onDelete = async (type: DeleteType, id: string) => {
  const token = await getToken();
  
  switch (type) {
    case DeleteType.PROJECT:
      await fetch(`${config.server_endpoints.DELETE_REPO}/${id}`, {
        method: "DELETE",
        headers: { authorization: `Bearer ${token}` }
      });
      break;
    
    case DeleteType.EXPERIENCE:
      await fetch(`${config.server_endpoints.DELETE_EXPERIENCE}/${id}`, {
        method: "DELETE",
        headers: { authorization: `Bearer ${token}` }
      });
      break;
    
    case DeleteType.EDUCATION:
      await fetch(`${config.server_endpoints.DELETE_EDUCATION}/${id}`, {
        method: "DELETE",
        headers: { authorization: `Bearer ${token}` }
      });
      break;
  }
  
  toast.success("Deleted successfully");
};
Deleting content is permanent. Associated images are also removed from S3 storage.

Next steps

Choose a template

Select a template to showcase your customized content

Theme customization

Customize colors and enable dark mode

Build docs developers (and LLMs) love