Generate a retro terminal-style stats card for your GitHub profile README — just like Neofetch, but for GitHub!
- ASCII Avatar — Your GitHub profile picture converted to ASCII art
- Real-time Stats — Repos, stars, commits, followers, and lines of code
- Dark/Light Themes — Automatically matches the viewer's GitHub theme
- Fully Customizable — Add your own sections via JSON config
- No Setup Required — Just add the URL to your README
- Quick Start
- Add to Your GitHub Profile
- Dark/Light Mode Support
- Parameters
- Custom Configuration
- Deploy Your Own
- Local Development
Add this to your GitHub profile README:
Replace YOUR_USERNAME with your GitHub username. That's it!
If you don't have one yet, create a repository with the same name as your GitHub username (e.g., username/username). This is a special repository — its README.md appears on your GitHub profile page.
Edit your profile README.md and add:
Commit the changes and visit your GitHub profile. Your neofetch card will appear!
GitHub users can choose dark or light themes. Use the <picture> element to automatically show the right theme:
<a href="https://github.com/jeantimex/neofetch-profile">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://neofetch-profile.vercel.app/api?username=[YOUR_USERNAME]&theme=github-dark">
<img alt="Neofetch Profile" src="https://neofetch-profile.vercel.app/api?username=[YOUR_USERNAME]&theme=github-light">
</picture>
</a><p align="center">
<a href="https://github.com/jeantimex/neofetch-profile">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://neofetch-profile.vercel.app/api?username=[YOUR_USERNAME]&theme=github-dark">
<img alt="Neofetch Profile" src="https://neofetch-profile.vercel.app/api?username=[YOUR_USERNAME]&theme=github-light">
</picture>
</a>
</p>When using a config URL, URL-encode the config parameter:
<p align="center">
<a href="https://github.com/jeantimex/neofetch-profile">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://neofetch-profile.vercel.app/api?username=[YOUR_USERNAME]&theme=github-dark&config=[YOUR_CONFIG_JSON_FILE_URL]">
<img alt="Neofetch Profile" src="https://neofetch-profile.vercel.app/api?username=[YOUR_USERNAME]&theme=github-light&config=[YOUR_CONFIG_JSON_FILE_URL]">
</picture>
</a>
</p>| Parameter | Description | Default |
|---|---|---|
username |
Your GitHub username (required) | — |
theme |
github-dark or github-light |
github-dark |
config |
URL to a JSON config file | — |
# Basic
https://neofetch-profile.vercel.app/api?username=jeantimex
# Light theme
https://neofetch-profile.vercel.app/api?username=jeantimex&theme=github-light
# With custom config (URL-encoded for GitHub README)
https://neofetch-profile.vercel.app/api?username=jeantimex&theme=github-dark&config=https%3A%2F%2Fraw.githubusercontent.com%2Fjeantimex%2Fneofetch-profile%2Fmain%2Fpublic%2Fconfig.json
Tip: Use urlencoder.org to encode your config URL.
Want to customize the info displayed? Host a JSON config file and pass its URL.
Create neofetch.json in your profile repository:
{
"sections": [
{
"title": "{{username}}@github",
"fields": [
{ "key": "Name", "value": "{{name}}" },
{ "key": "Location", "value": "{{location}}" },
{ "key": "Created", "value": "{{created}}" },
{ "key": "Uptime", "value": "{{uptime}}" },
{ "key": "Company", "value": "{{company}}" }
]
},
{
"fields": [
{ "key": "Languages", "value": "{{languages}}" },
{ "key": "IDE", "value": "Cursor, VSCode, Neovim" }
]
},
{
"fields": [
{ "key": "Hobbies.Software", "value": "WebGL, WebGPU, AI/ML" },
{ "key": "Hobbies.Hardware", "value": "Mechanical Keyboards" }
]
},
{
"title": "- Contact",
"fields": [
{ "key": "Email", "value": "{{email}}" },
{ "key": "Website", "value": "https://github.com/{{username}}" },
{ "key": "Twitter", "value": "{{twitter}}" }
]
}
],
"stats": {
"title": "- GitHub Stats",
"rows": [
{ "left": { "key": "Repos", "value": "{{repos}}" }, "right": { "key": "Stars", "value": "{{stars}}" } },
{ "left": { "key": "Following", "value": "{{following}}" }, "right": { "key": "Followers", "value": "{{followers}}" } },
{ "left": { "key": "Commits", "value": "{{commits}}" }, "right": { "key": "Forks", "value": "{{forks}}" } },
{ "left": { "key": "Issues", "value": "{{issues}}" }, "right": { "key": "PRs", "value": "{{prs}}" } },
"loc"
]
}
}After committing, get the raw URL:
https://raw.githubusercontent.com/YOUR_USERNAME/YOUR_USERNAME/main/neofetch.json
Important: URL-encode the config URL for GitHub README compatibility.
Use these variables in your config to pull data from GitHub automatically:
| Variable | Description | Example Output |
|---|---|---|
{{username}} |
GitHub username | jeantimex |
{{name}} |
Display name | Yong Su |
{{company}} |
Company (auto-capitalized) | Apple Inc |
{{location}} |
Location | San Francisco, CA |
{{bio}} |
Bio (first 40 chars) | Software Engineer |
{{uptime}} |
Account age | 10 years, 3 months, 5 days |
{{created}} |
Account creation date | 2015-03-21 |
{{languages}} |
Top 4 programming languages | TypeScript, Python, Go, Rust |
{{repos}} |
Number of repositories | 42 |
{{stars}} |
Total stars received | 128 |
{{forks}} |
Total forks across repos | 64 |
{{gists}} |
Number of public gists | 12 |
{{issues}} |
Total issues created | 85 |
{{prs}} |
Total pull requests created | 142 |
{{commits}} |
Estimated total commits | 5,000 |
{{followers}} |
Follower count | 256 |
{{following}} |
Following count | 128 |
{{email}} |
Public email | you@example.com |
{{blog}} |
Website/blog URL | yoursite.com |
{{twitter}} |
Twitter/X username | yourhandle |
| Field | Description |
|---|---|
image |
Custom image URL for ASCII art (optional). Supports PNG, WebP, AVIF, GIF, SVG. |
coloredImage |
true to render ASCII with original image colors |
imageScale |
Scale factor: 0 = no image, 0.5 = half size, 1 = full size (default), 2 = 2x zoom |
imageOffsetX |
Horizontal offset: number, "50px", or "25%" |
imageOffsetY |
Vertical offset: number, "50px", or "25%" |
imageColor |
Override image color: "lightColor, darkColor" |
removeBackground |
true to auto-detect and remove background color |
backgroundColor |
Custom card background: "lightColor, darkColor" |
separatorColor |
Custom dots/separator color: "lightColor, darkColor" |
sections |
Array of sections to display |
sections[].title |
Section header (optional). Use "{{username}}@github" for the first section, "- Section Name" for others |
sections[].titleColor |
Custom title colors: { "text": "light, dark", "line": "light, dark" } |
sections[].fields |
Array of field objects (see Field Options below) |
stats |
GitHub Stats section configuration (optional) |
stats.title |
Stats section title (default: "- GitHub Stats") |
stats.titleColor |
Custom stats title colors: { "text": "light, dark", "line": "light, dark" } |
stats.enabled |
Set to false to hide stats section |
stats.rows |
Array of row types to display |
Each field in sections[].fields supports:
| Field | Description |
|---|---|
key |
Label text (required) |
value |
Value text or template variable (required) |
keyColor |
Custom key color: "lightColor, darkColor" |
valueColor |
Custom value color: "lightColor, darkColor" |
Use a custom image instead of your GitHub avatar:
{
"image": "https://example.com/my-logo.png",
"sections": [...]
}Supported formats: PNG, WebP, AVIF, GIF, SVG
Transparency is automatically preserved — transparent pixels render as spaces.
Render the image with its original colors:
{
"image": "https://example.com/pikachu.png",
"coloredImage": true
}Control the image size with imageScale:
{
"imageScale": 0.5
}| Value | Effect |
|---|---|
0 |
No image (empty space) |
0.5 |
Half size, centered |
1 |
Full size (default) |
2 |
2x zoom (crops to center) |
Auto-detect and remove solid background colors:
{
"image": "https://example.com/logo.png",
"removeBackground": true
}Shift the image crop position with imageOffsetX and imageOffsetY:
{
"imageScale": 2,
"imageOffsetX": "20%",
"imageOffsetY": -50
}| Value | Description |
|---|---|
50 |
Shift 50 pixels |
"50px" |
Shift 50 pixels |
"25%" |
Shift 25% of crop dimensions |
-50 |
Shift in opposite direction |
Offsets are relative to the grid size. Positive X shifts right, positive Y shifts down.
Understanding how images are processed helps you get the best results:
┌─────────────────────────────────────────────────────────────────┐
│ 1. LOAD Load image (PNG, WebP, AVIF, GIF, SVG) │
├─────────────────────────────────────────────────────────────────┤
│ 2. REMOVE BG If removeBackground: true, detect and remove │
│ solid background color (keeps original size) │
├─────────────────────────────────────────────────────────────────┤
│ 3. CROP For transparent images: crop to bounding box │
│ of opaque pixels (removes transparent padding) │
├─────────────────────────────────────────────────────────────────┤
│ 4. CONTAIN Fit image in 38x25 character grid, maintain │
│ aspect ratio, center both horizontally and │
│ vertically (no cropping, image fits entirely) │
├─────────────────────────────────────────────────────────────────┤
│ 5. SCALE Apply imageScale multiplier from center │
│ (>1 = zoom in, <1 = zoom out) │
├─────────────────────────────────────────────────────────────────┤
│ 6. OFFSET Shift image position by imageOffsetX/Y │
├─────────────────────────────────────────────────────────────────┤
│ 7. ASCII Convert each pixel to ASCII character with │
│ color (if coloredImage: true) │
├─────────────────────────────────────────────────────────────────┤
│ 8. FINAL CROP Crop to final 38x25 character grid │
└─────────────────────────────────────────────────────────────────┘
Key behaviors:
- Transparent PNGs: Transparent padding is automatically cropped so your content fills the grid
- removeBackground: Only removes background color, does NOT crop the image
- Scale + Offset: Use
imageScale > 1to zoom in, thenimageOffsetX/Yto pan around
Override colors with light/dark mode support. Format: "lightModeColor, darkModeColor"
Card Background:
{
"backgroundColor": "#ffffff, #1a1a2e"
}Separator/Dots Color:
{
"separatorColor": "#cccccc, #555555"
}Image Color Override:
{
"imageColor": "#333333, #00ff00"
}Section Title Colors:
{
"sections": [
{
"title": "{{username}}@github",
"titleColor": {
"text": "#1A73E8, #4285F4",
"line": "#5F6368, #9AA0A6"
},
"fields": [...]
}
]
}Field Colors:
{
"fields": [
{
"key": "Name",
"value": "{{name}}",
"keyColor": "#EA4335, #EA4335",
"valueColor": "#202124, #E8EAED"
}
]
}Color format:
- Use
"lightColor, darkColor"for different light/dark mode colors - Use
"color"(no comma) for the same color in both modes
Supported color values:
- Hex:
#FF0000,#f00 - Named:
red,blue,green - RGB/RGBA:
rgb(255,0,0),rgba(0,0,0,0.5) - HSL/HSLA:
hsl(0,100%,50%),hsla(0,100%,50%,0.5)
Examples:
{
"backgroundColor": "red",
"keyColor": "#4285F4",
"valueColor": "#333, #fff"
}Pikachu Theme (yellow/red/brown):
{
"image": "https://example.com/pikachu.png",
"coloredImage": true,
"sections": [
{
"title": "{{username}}@github",
"titleColor": { "text": "#CC9900, #FFD700", "line": "#8B4513, #D4A574" },
"fields": [
{ "key": "Name", "value": "{{name}}", "keyColor": "#CC9900, #FFC107", "valueColor": "#5D4037, #FFEB3B" }
]
}
]
}Google Theme (blue/red/yellow/green):
{
"image": "https://example.com/marker.svg",
"coloredImage": true,
"sections": [
{
"title": "{{username}}@github",
"titleColor": { "text": "#1A73E8, #4285F4", "line": "#5F6368, #9AA0A6" },
"fields": [
{ "key": "Name", "value": "{{name}}", "keyColor": "#1A73E8, #4285F4", "valueColor": "#202124, #E8EAED" },
{ "key": "Location", "value": "{{location}}", "keyColor": "#EA4335, #EA4335", "valueColor": "#202124, #E8EAED" },
{ "key": "Created", "value": "{{created}}", "keyColor": "#FBBC04, #FBBC04", "valueColor": "#202124, #E8EAED" },
{ "key": "Uptime", "value": "{{uptime}}", "keyColor": "#34A853, #34A853", "valueColor": "#202124, #E8EAED" }
]
}
]
}| Row Type | Description |
|---|---|
{ "left": {...}, "right": {...} } |
Split row with | separator. Each side has key and value |
"loc" |
Special row: Lines of Code: X ( Y++, Z-- ) |
{
"stats": {
"title": "- GitHub Stats",
"rows": [
{ "left": { "key": "Repos", "value": "{{repos}}" }, "right": { "key": "Stars", "value": "{{stars}}" } },
{ "left": { "key": "Commits", "value": "{{commits}}" }, "right": { "key": "Followers", "value": "{{followers}}" } },
{ "left": { "key": "Forks", "value": "{{forks}}" }, "right": { "key": "Gists", "value": "{{gists}}" } },
"loc"
]
}
}To hide the stats section entirely:
{
"stats": {
"enabled": false
}
}For private repo stats or higher rate limits, deploy your own instance:
For private repos or to avoid rate limits:
- Go to GitHub Settings → Developer settings → Personal access tokens → Tokens (classic)
- Click Generate new token (classic)
- Select the
reposcope - Copy the token
- In your Vercel project, go to Settings → Environment Variables
- Add
GITHUB_TOKENwith your token value
# Clone the repo
git clone https://github.com/jeantimex/neofetch-profile.git
cd neofetch-profile
# Install dependencies
npm install
# Create .env file with your GitHub token
echo "GITHUB_TOKEN=your_token_here" > .env
# Run locally (requires Vercel CLI)
vercel devBasic usage:
http://localhost:3000/api?username=YOUR_USERNAME
With theme:
http://localhost:3000/api?username=YOUR_USERNAME&theme=github-light
With local config file (edit public/config.json to customize):
http://localhost:3000/api?username=YOUR_USERNAME&config=http://localhost:3000/config.json
- Fetches your GitHub profile and repository data via the GitHub API
- Converts your avatar to ASCII art using image processing
- Calculates stats: repos, stars, total commits, followers, lines of code
- Generates an SVG with neofetch-style terminal aesthetics
- Caches the result for 4 hours for performance
This project is inspired by Andrew Grant's GitHub Profile — the original neofetch-style GitHub profile that started it all. Check out his amazing work!
Also inspired by:
- neofetch — The original CLI system info tool
- github-readme-stats — GitHub stats cards
MIT





