RepoWidget
Display live GitHub repository cards on any website. No build tools, no framework, no manual updates. One script tag and one function call.
The Problem
Developers and organizations frequently want to showcase their GitHub repositories on portfolios, documentation, or marketing pages. The usual approaches all have painful trade-offs:
Manual HTML
Copy-pasted repo details go stale the moment you push a new commit or earn another star.
Custom API code
Re-implementing GitHub API integration, caching, and card rendering from scratch for every project.
Heavy frameworks
Pulling in a full component library just to display repository metadata is significant overhead.
RepoWidget eliminates all three. Drop in the script, call one function. Repositories appear live, always current, with zero maintenance.
<!-- Before: static, stale, hand-maintained -->
<div class="repo-card">
<h3>my-cool-project</h3>
<p>A tool I made: ★ 42 forks 7</p> <!-- already wrong -->
</div>
<!-- After: live data, always correct -->
<div id="repos"></div>
<script src="https://cdn.jsdelivr.net/npm/repowidget/dist/repoWidget.min.js"></script>
<script>
createRepoWidget({ username: 'your-username', containerId: 'repos' });
</script>
Features
Always Live
Fetches directly from the GitHub API. Stars, forks, descriptions, and language badges are always current. No manual updates needed.
Intelligent Caching
24-hour localStorage cache with ETag support prevents redundant API calls and keeps you well within GitHub's 60 req/hr rate limit.
Full Customization
Override card styles, text colors, grid columns, sort order, filter criteria, and hover animations to match any design system.
Responsive Grid
Mobile-first CSS Grid with configurable column counts per breakpoint. Cards adapt consistently across phone, tablet, and desktop.
How It Works
RepoWidget is a thin layer over the GitHub REST API v3. On each page load it checks localStorage
for
a valid cache; on a miss (or after 24 hours) it fires a conditional request with an ETag header
so
unchanged data costs zero bytes. The resulting JSON is filtered, sorted, and rendered in a
single
innerHTML write.
- 1 Cache check. LocalStorage is queried for an unexpired entry. If one exists, rendering skips straight to step 4.
-
2
API fetch. A
Fetchrequest is sent toapi.github.com/users/{'{'}username{'}'}/repos, optionally with a stored ETag to receive a 304 instead of redundant data. -
3
Filter & sort. Forks, excluded slugs, and
archived repos are dropped. The remainder is sorted by
stars,forks,name,size, orupdatedand capped atmaxRepos. - 4 Render. Repository cards are generated and injected into the container in a single DOM write. Language badges receive automatic color coding.
Configuration
Pass an options object to createRepoWidget().
Only
username and containerId are required.
Core
| Option | Type | Default | Description |
|---|---|---|---|
username |
string | — | GitHub username or organization name |
containerId |
string | — | ID of the element to render cards into |
maxRepos |
number | 6 |
Maximum number of repositories to display |
sortBy |
string | 'stars' |
stars, forks, name, size, or
updated
|
forked |
boolean | false |
Include forked repositories |
exclude |
string[] | [] |
Repository slugs to hide |
Layout
| Option | Type | Default | Description |
|---|---|---|---|
columns.mobile |
number | 1 |
Grid columns on small screens |
columns.tablet |
number | 2 |
Grid columns on medium screens |
columns.desktop |
number | 3 |
Grid columns on large screens |
Styling
| Option | Description |
|---|---|
cardStyles |
Object of CSS properties applied to each card element |
textStyles.titleColor |
CSS color for the repository name |
textStyles.descriptionColor |
CSS color for the description text |
Callbacks
| Option | Signature | Description |
|---|---|---|
onLoad |
(repos) => void |
Called after cards are rendered; receives the array of displayed repos |
onError |
(err) => void |
Called when the API request or rendering fails |
Code Examples
Vanilla HTML. CDN
<div id="repos"></div>
<script src="https://cdn.jsdelivr.net/npm/repowidget/dist/repoWidget.min.js"></script>
<script>
createRepoWidget({
username: 'your-username',
containerId: 'repos',
maxRepos: 6,
sortBy: 'stars',
exclude: ['your-username.github.io'],
columns: { mobile: 1, tablet: 2, desktop: 3 }
});
</script>
React
import { useEffect } from 'react';
import { createRepoWidget } from 'repowidget';
function RepoDisplay() {
useEffect(() => {
createRepoWidget({ username: 'your-username', containerId: 'repos', maxRepos: 6 });
}, []);
return <div id="repos"></div>;
}
Custom style override
createRepoWidget({
username: 'your-org',
containerId: 'oss-repos',
sortBy: 'updated',
forked: false,
cardStyles: {
backgroundColor: '#0f1117',
borderRadius: '12px',
border: '1px solid #30363d',
boxShadow: '0 4px 12px rgba(0,0,0,0.4)'
},
textStyles: {
titleColor: '#58a6ff',
descriptionColor: '#8b949e'
},
onLoad: (repos) => console.log(`Rendered ${repos.length} repos`)
});
Who It's For
- ▸ Individual developers building portfolios to showcase open-source contributions and side projects.
- ▸ Organizations maintaining open-source landing pages, DevRel pages, or documentation hubs.
- ▸ Technical writers & educators linking course repos or listing example code repositories.
- ▸ Any site where static repo listings would go stale. WordPress, Webflow, or plain HTML pages.
Security Notes
Public repos only
RepoWidget only accesses public repository data via unauthenticated requests. No private data is ever readable.
No tokens in client code
If you supply an optional auth token for higher rate limits, route requests through your own backend rather than including tokens in page source.
CSP headers
Add connect-src https://api.github.com; to your Content-Security-Policy
if
your site uses CSP.
How It Compares
RepoWidget specializes. It doesn't try to be a charting library or a full design system.
| RepoWidget | GitHub Readme Stats | Manual HTML | |
|---|---|---|---|
| Live data | Yes | Yes (SVG) | No |
| Interactive / clickable | Yes | No | Yes |
| Full CSS control | Yes | Limited params | Yes |
| Setup time | <5 min | <5 min | Hours–days |
| Ongoing maintenance | None | None | Manual |
| Works in plain HTML file | Yes | Via <img> | Yes |
| Built-in caching | Yes (24 hr) | No | No |
Get Started in Minutes
Install via npm or drop the CDN link directly into your HTML. No bundler, no config file, no component architecture to learn.
# npm
npm install repowidget
# or via CDN
https://cdn.jsdelivr.net/npm/repowidget/dist/repoWidget.min.js
https://unpkg.com/repowidget/dist/repoWidget.min.js