Overview
GitFolio automatically syncs your GitHub data to keep your portfolio up-to-date. When you sign in with GitHub, GitFolio fetches your profile information, repositories, and contribution history through the GitHub API.
How GitHub sync works
Authentication
You authenticate with GitHub OAuth, granting GitFolio read access to your public profile and repositories.
Initial sync
During onboarding, GitFolio fetches your complete GitHub profile and repository data.
Data storage
Your data is stored in GitFolio’s database for fast portfolio rendering.
Ongoing updates
You can manually refresh your data anytime from the dashboard.
Profile data sync
GitFolio syncs these profile fields from your GitHub account:
Repository sync
GitFolio fetches all your public repositories with detailed information:
Repository fields
Field Source Description namerepo.nameRepository name descriptionrepo.descriptionProject description topicsrepo.topicsGitHub topics/tags languagesLanguages API Programming languages with byte counts starsrepo.stargazers_countNumber of stars forksrepo.forks_countNumber of forks deploymentsDeployments API Active deployment count repoLinkrepo.html_urlGitHub repository URL liveLinkrepo.homepageLive demo URL (if set)
Language detection
GitFolio fetches programming language data for each repository:
// From github.service.ts
const getLanguages = async ({ token , url }) => {
const res = await fetch ( url , {
headers: { Authorization: `Bearer ${ token } ` }
});
const languages = await res . json ();
return languages ; // { "TypeScript": 45032, "JavaScript": 12843, ... }
};
Languages are displayed as badges on project cards in your portfolio.
Language data is calculated by GitHub based on the number of bytes of code in each language.
Contribution graph sync
GitFolio syncs your entire GitHub contribution history using the GitHub GraphQL API:
// From github.service.ts
export const getUserContributionsGraph = async (
token : string ,
username : string ,
createdAt : string
) => {
const firstContributionYear = getYear ( parseISO ( createdAt ));
const currentYear = getYear ( new Date ());
const allContributions = [];
// Fetch contributions year by year
for ( let year = firstContributionYear ; year <= currentYear ; year ++ ) {
const yearStart = startOfYear ( new Date ( year , 0 , 1 ));
const yearEnd = endOfYear ( new Date ( year , 0 , 1 ));
const contributionsQuery = `
query UserContributions($username: String!, $from: DateTime, $to: DateTime) {
user(login: $username) {
contributionsCollection(from: $from, to: $to) {
contributionCalendar {
totalContributions
weeks {
contributionDays {
color
contributionCount
date
weekday
}
firstDay
}
}
}
}
}
` ;
const yearData = await makeGraphQLQuery ( token , contributionsQuery , {
username ,
from: format ( yearStart , "yyyy-MM-dd'T'HH:mm:ssXXX" ),
to: format ( yearEnd , "yyyy-MM-dd'T'HH:mm:ssXXX" )
});
allContributions . push ({ year , data: yearData });
}
return allContributions ;
};
This powers the contribution calendar visualization in templates like Pixel Perfect.
Data persistence
Synced data is stored in the PostgreSQL database:
model User {
id String @id
username String ? @unique
firstname String
lastname String
email String @unique
profileImg String
bio String ?
tagline String ?
location String ?
website String ?
githubLink String ?
followers Int @default ( 0 )
following Int @default ( 0 )
skills String []
repos Repo []
experiences Experience []
educations Education []
}
model Repo {
id String @id @default ( uuid ())
name String
description String ?
topics String []
languages Json
stars Int @default ( 0 )
forks Int @default ( 0 )
deployments Int @default ( 0 )
thumbnail String ?
repoLink String
liveLink String ?
isPinned Boolean @default ( false )
isIncluded Boolean @default ( true )
userId String
owner User @relation ( fields : [ userId ], references : [ id ] )
}
Repository management
After syncing, you have full control over which repositories appear in your portfolio:
Include/exclude repositories
Each repository has an isIncluded flag:
// From dashboard.service.ts
export const createOrUpdateRepo = async ( userId : string , data : Repo ) => {
await prisma . repo . upsert ({
where: { id: data . id },
update: { ... data },
create: { ... data , userId , isIncluded: true } // Default to included
});
};
Toggle this in the Projects tab to show/hide repositories from your portfolio.
Pin repositories
Mark important repositories as pinned to feature them prominently:
model Repo {
isPinned Boolean @default ( false )
isIncluded Boolean @default ( true )
}
Manual data refresh
Refreshing your GitHub data
While GitFolio doesn’t automatically poll GitHub for updates, you can manually refresh your data:
Navigate to the dashboard
GitFolio fetches the latest data on each dashboard load
New repositories are automatically added
Updated repository data (stars, forks, etc.) is refreshed
The dashboard fetches data using: // From dashboard/page.tsx
useEffect (() => {
const fetchData = async () => {
const token = await getToken ();
const res = await fetch ( config . server_endpoints . GET_USER_DATA , {
headers: { authorization: `Bearer ${ token } ` },
credentials: "include"
});
const result = await res . json ();
// Update state with fresh data
};
fetchData ();
}, []);
Authentication flow
GitFolio uses Clerk for authentication with GitHub OAuth:
OAuth redirect
User clicks “Sign in with GitHub” and is redirected to GitHub’s OAuth page
Authorization grant
User authorizes GitFolio to read their public profile and repositories
User creation
Clerk receives the OAuth token and creates a user account
Data sync
GitFolio’s user sync service runs daily to sync new users: // From UserSync.service.ts
corn . schedule ( "0 0 * * *" , syncUsers ); // Daily at midnight
Onboarding
New users are directed to onboarding to complete their profile setup
API rate limits
GitFolio respects GitHub’s API rate limits:
Authenticated requests: 5,000 requests per hourGraphQL API: 5,000 points per hourGitFolio uses authenticated requests with your OAuth token to maximize available quota.
Privacy and security
Read-only access GitFolio only requests read access to your public repositories and profile. It cannot modify your GitHub account.
Token security OAuth tokens are securely stored and never exposed in your portfolio or client-side code.
Data control You control which repositories and information appear on your portfolio through the dashboard.
Account deletion Deleting your GitFolio account removes all synced data from our database.
Next steps
Customize your portfolio Learn how to customize the data displayed in your portfolio
Choose a template Select a template to showcase your GitHub data