π A modern GitHub portfolio gallery with live repositories, GitHub-style README previews, automatic repo categories, matching SVG preview covers, and online-only PWA install support.
Tharindu Work Gallery is a clean React + Vite portfolio project that loads public GitHub repositories and presents them in a beautiful command-center style UI.
It is built for:
- π§βπ» Developer portfolios with real GitHub repos
- π¦ Project galleries with repo details and README previews
- π§ Automatic categories and icons from repo name, language, topics, and description
- πΌοΈ Automatic SVG project preview covers when screenshots are missing
- π± Installable PWA that stays fully online and avoids stale cache problems
- π GitHub Pages deployment with a ready workflow
| Feature | Status | Details |
|---|---|---|
| π§ Modern portfolio UI | β Ready | Sticky top navigation, hero, timeline projects, smooth mobile layout |
| π΄ Live GitHub repo loading | β Ready | Loads selected repos or all public repos from your GitHub profile |
| π§ Auto category detection | β Ready | Finance, Android, Web, Automation, Media, Tools |
| π― Auto icon detection | β Ready | Wallet, piggy, film, terminal, React, Android, pen, book, and more |
| π GitHub-style README preview | β Ready | GitHub-like fonts, headings, code blocks, tables, links, and dark mode |
| πΌοΈ Automatic repo preview SVG | β Ready | Matching preview cover for every repo details page |
| π± Online-only PWA | β Ready | Installable app, network-only service worker, no stale app cache |
| π Theme toggle | β Ready | Day/dark theme with matching UI colors |
| π² Mobile-first layout | β Ready | Works cleanly on phone screens and desktop screens |
| π GitHub Pages workflow | β Ready | .github/workflows/pages.yml deploys the built site |
corepack enable
corepack prepare pnpm@9.15.4 --activate
pnpm install
pnpm devOpen the local URL from Vite, then edit the config files below.
| File | Purpose |
|---|---|
π§βπΌ src/config/site.config.js |
Profile info, contact links, GitHub username, category list, UI options |
π¦ src/config/projects.config.js |
Selected repo links, manual overrides, custom photos, tags, notes, status |
π public/manifest.webmanifest |
PWA name, icons, theme color, shortcuts |
π‘ public/sw.js |
Online-only service worker with no precache |
πΌοΈ src/utils/repoPreview.js |
Automatic matching SVG preview generator |
π src/components/ReadmeViewer.jsx |
GitHub-like README preview renderer |
Edit src/config/site.config.js:
githubUsername: 'tharindu899'A full profile link also works:
githubUsername: 'https://github.com/tharindu899'Edit src/config/projects.config.js:
export const repositoryLinks = [
'https://github.com/tharindu899/CashNest_X',
'tharindu899/Inkwell',
{
url: 'https://github.com/tharindu899/MyRepo',
featured: true,
photo: 'images/projects/my-repo.png'
}
];When repositoryLinks has items, the app loads only those exact repos. When it is empty, the app loads all public repos from githubUsername.
β Latest: pinned badges now show on both Home and Projects page, but Home is still limited to 3 pinned items.
The home page now shows only pinned project items, capped to 3, and only 3 focus/method cards.
The Projects page is not limited. It keeps the normal full repo list, and pinned repos show a Pinned badge there too.
Edit src/config/site.config.js when you want to change the Home limit:
ui: {
pinnedProjectLimit: 3,
workItemLimit: 3
}Project page still shows all repos. Repos with featured: true also show the Pinned badge on the Projects page.
GitHub repo names use the real repo slug, not only the display title. For CashNest X, use CashNest_X in projectOverrides:
export const projectOverrides = {
CashNest_X: {
title: 'CashNest X',
aliases: ['CashNest', 'CashNest X', 'cashnest-x'],
featured: true,
category: 'finance',
icon: 'piggy'
}
};The app now also matches override title and aliases, so CashNest X, CashNest_X, and cashnest-x can all point to the same repo.
The app checks repo name, owner, description, topics, language, and homepage to choose the best category and icon.
| Category | Emoji | Detected from |
|---|---|---|
| Finance | π° | cash, money, budget, salary, expense, loan, bank, wallet |
| Media | π¬ | movie, film, cinema, stream, video, TMDb, Telegram, anime |
| Android | π€ | Android, APK, AAB, Kotlin, Java, Capacitor, Cordova, Compose |
| Web | π | React, Vite, website, portfolio, dashboard, PWA, HTML, CSS |
| Automation | β‘ | GitHub Actions, workflow, script, deploy, Termux, Docker, bot |
| Tools | π§° | Default fallback when nothing else matches |
Need a custom result? Use projectOverrides.
export const projectOverrides = {
CashNest_X: {
title: 'CashNest X',
category: 'finance',
featured: true,
icon: 'piggy',
photo: 'images/projects/cashnest-x.png',
shortNote: 'Mobile-first personal finance tracker.',
tags: ['React', 'Capacitor', 'Finance'],
status: 'Active'
}
};Every project details page gets a generated SVG preview when no screenshot is set.
The SVG preview includes:
- π·οΈ Repo title
- π€ Owner/repo name
- π§ Category
- π» Main language
- β Stars
- π΄ Forks
- π¦ Status
- π§© Tags
Put images here:
public/images/projects/my-project.png
public/images/projects/gallery/my-project-screen-1.pngThen set:
MyRepoName: {
photo: 'images/projects/my-project.png',
photos: [
'images/projects/my-project.png',
'images/projects/gallery/my-project-screen-1.png'
]
}This app is installable as a PWA, but it intentionally does not keep old cached app files.
- β
Install support through
manifest.webmanifest - β
Service worker registration through
src/pwa/registerOnlineOnlyPwa.js - β
Network-only fetch in
public/sw.js - β Same-origin app files handled by the service worker
- β External GitHub API, raw README files, avatars, and badges bypass the service worker
- β No precache list
- β No stale UI after updates
- β Offline message instead of old cached pages
This is useful for GitHub Pages projects where you want every visit to load the latest deployed build while live GitHub repo data still loads correctly.
π Click to show every file with emoji labels
π¦ github-work-gallery-pwa/
βββ 𧬠.github/
β βββ βοΈ workflows/
β βββ π pages.yml
βββ π docs/
β βββ π CHANGELOG.md
β βββ π CONFIGURATION.md
β βββ π DEPLOY_GITHUB_PAGES.md
β βββ π FULL_GUIDE.md
β βββ π PROJECT_STRUCTURE.md
β βββ π PWA_ONLINE_ONLY.md
β βββ π REPO_PREVIEWS.md
βββ π public/
β βββ π¨ icons/
β β βββ πΌοΈ app-icon.svg
β β βββ πΌοΈ apple-touch-icon.png
β β βββ πΌοΈ favicon-48.png
β β βββ πΌοΈ pwa-icon-192.png
β β βββ πΌοΈ pwa-icon-512.png
β β βββ πΌοΈ pwa-maskable-192.png
β β βββ πΌοΈ pwa-maskable-512.png
β βββ πΌοΈ images/
β β βββ π§βπΌ profile/
β β β βββ πΌοΈ profile.svg
β β βββ π¦ projects/
β β β βββ π gallery/
β β β βββ πΌοΈ project-placeholder.svg
β β βββ π readme/
β β βββ πΌοΈ top-banner.svg
β βββ π± manifest.webmanifest
β βββ π¨ sw.js
βββ π§ src/
β βββ π§© components/
β β βββ π¨ icons/
β β β βββ βοΈ Icon.jsx
β β βββ βοΈ CategoryFilter.jsx
β β βββ βοΈ Header.jsx
β β βββ βοΈ Hero.jsx
β β βββ βοΈ IconButton.jsx
β β βββ βοΈ Layout.jsx
β β βββ βοΈ ProfileSidebar.jsx
β β βββ βοΈ ProjectModal.jsx
β β βββ βοΈ ProjectTimeline.jsx
β β βββ βοΈ PwaInstallButton.jsx
β β βββ βοΈ ReadmeViewer.jsx
β β βββ βοΈ SearchBox.jsx
β β βββ βοΈ SectionHeader.jsx
β β βββ βοΈ StatStrip.jsx
β β βββ βοΈ ThemeToggle.jsx
β β βββ βοΈ WorkTiles.jsx
β βββ βοΈ config/
β β βββ π¨ projects.config.js
β β βββ π¨ site.config.js
β βββ πͺ hooks/
β β βββ π¨ useGithubRepos.js
β β βββ π¨ useHashRoute.js
β βββ π pages/
β β βββ βοΈ Contact.jsx
β β βββ βοΈ Home.jsx
β β βββ βοΈ Projects.jsx
β βββ π± pwa/
β β βββ π¨ registerOnlineOnlyPwa.js
β β βββ π¨ usePwaInstallPrompt.js
β βββ π¨ styles/
β β βββ π¨ index.css
β βββ π§° utils/
β β βββ π¨ format.js
β β βββ π¨ github.js
β β βββ π¨ repoPreview.js
β βββ βοΈ App.jsx
β βββ βοΈ main.jsx
βββ π¦ .npmrc
βββ π index.html
βββ π§ package.json
βββ π README.md
βββ π¨ vite.config.js| Guide | What it explains |
|---|---|
π docs/FULL_GUIDE.md |
Complete A-Z setup, edit, run, build, deploy, and customize guide |
ποΈ docs/PROJECT_STRUCTURE.md |
Full emoji file tree and explanation for every important folder |
βοΈ docs/CONFIGURATION.md |
Profile, links, categories, repo links, overrides, screenshots |
π± docs/PWA_ONLINE_ONLY.md |
Online-only PWA method, icons, no-cache behavior, install notes |
πΌοΈ docs/REPO_PREVIEWS.md |
Automatic SVG previews and custom screenshot method |
π docs/DEPLOY_GITHUB_PAGES.md |
GitHub Pages deployment with Actions workflow |
π docs/CHANGELOG.md |
Project update notes and release history |
# π§© Install dependencies
pnpm install
# π₯ Start local development
pnpm dev
# ποΈ Build production files
pnpm build
# π Preview production build
pnpm preview- π€ Push this project to a public GitHub repo.
- βοΈ Go to Settings β Pages.
- π§ͺ Set Build and deployment to GitHub Actions.
- πΏ Push to
mainormaster. - β The workflow builds and deploys the website.
Tharindu Prabath
π Sri Lanka
π GitHub: tharindu899
π§ Email: prabath99t@gmail.com
- π οΈ Fixed live GitHub repo loading in the online-only PWA
- π‘ Service worker now bypasses external GitHub API/README/avatar/badge requests
- π Added safer GitHub fetch handling with
no-storelive requests - π§© If the full GitHub profile list is blocked, configured/override repos are checked one by one first
- π Pinned project logic stays the same: Home shows pinned max 3, Projects shows all repos with badges
./push.sh "fix live github repo loading; update online pwa api bypass; improve configured repo fallback"This app now uses a stronger online loader:
- π GitHub user repos API
- π GitHub search API fallback
- πͺ mirror metadata fallback
- π configured repo links / project overrides as the final safe fallback
If your browser was already using an old installed PWA cache, open the site once and hard refresh. On Android Chrome, use Site settings β Storage β Clear & reset if the old page still appears. The new service worker is online-only and clears old caches automatically after it loads.