Git Fusion is a Next.js app that brings GitHub and GitLab activity into one authenticated dashboard. Users can sign up, connect their provider accounts through OAuth, and view consolidated contribution insights without relying on personal access tokens in the browser. More providers are planned to the future.
Try it out: https://gitfusion.thaipires.com
- Supabase authentication with sign in and sign up pages.
- Authenticated dashboard for connected GitHub and GitLab accounts.
- OAuth-based provider connection and disconnection flows.
- Consolidated contribution overview across providers.
- Dashboard metrics, contribution chart, repository highlights, and recent activity.
- Profile settings with avatar upload through Supabase Storage.
- Cached dashboard overview backed by persisted daily contribution totals.
- Server-side token handling with encrypted provider tokens.
- Next.js 15
- React 19
- Supabase for auth, database, and avatar storage
- HeroUI and Tailwind CSS for UI
- TanStack Query for client-side data fetching
- Framer Motion for animation
npm installCopy the example file and fill in the required values:
cp .env.local.example .env.localRequired variables:
NEXT_PUBLIC_SUPABASE_URL=
NEXT_PUBLIC_SUPABASE_ANON_KEY=
SUPABASE_SERVICE_ROLE_KEY=
GITHUB_OAUTH_CLIENT_ID=
GITHUB_OAUTH_CLIENT_SECRET=
GITLAB_OAUTH_CLIENT_ID=
GITLAB_OAUTH_CLIENT_SECRET=
# Recommended for production token encryption
GITFUSION_TOKEN_ENCRYPTION_KEY=Notes:
NEXT_PUBLIC_SUPABASE_URLandNEXT_PUBLIC_SUPABASE_ANON_KEYare public client-side Supabase values.SUPABASE_SERVICE_ROLE_KEYmust stay server-side only.GITFUSION_TOKEN_ENCRYPTION_KEYshould be a long, stable random string. Do not rotate it after users connect accounts unless you are prepared to invalidate/reconnect encrypted provider tokens.- Use the exact variable name
GITFUSION_TOKEN_ENCRYPTION_KEYin every environment. If production and local use different encryption keys, existing connected accounts may need to be reconnected. - If
GITFUSION_TOKEN_ENCRYPTION_KEYis not set, the app falls back toSUPABASE_SERVICE_ROLE_KEYfor token encryption, but a dedicated key is recommended.
Create a Supabase project, then link it locally:
npm run supabase:linkApply the database migrations:
npm run supabase:pushThe migrations create:
profiles- public
avatarsstorage bucket connected_accountsoauth_statesdashboard_overview_cachesync_runscontribution_daily_totals- required RLS policies, grants, indexes, and triggers
Create OAuth applications for GitHub and GitLab, then add their client IDs and secrets to .env.local.
Use these callback URLs:
http://localhost:3000/api/integrations/github/callback
http://localhost:3000/api/integrations/gitlab/callbackFor production, replace the origin with your deployed domain:
https://your-domain.com/api/integrations/github/callback
https://your-domain.com/api/integrations/gitlab/callbackProvider scopes used by the app:
- GitHub:
read:user user:email - GitLab:
read_user read_api
npm run devOpen http://localhost:3000.
npm run dev
npm run build
npm run start
npm run lint
npm run typecheck
npm run test
npm run test:run
npm run ci
npm run supabase:link
npm run supabase:pushThe project uses Vitest for focused server/API tests. The current suite covers:
/api/integrations/accountsaccount listing and disconnect behavior/api/dashboard/overviewauthorization, refresh handling, and known application errors- provider token encryption/decryption behavior, including mismatched encryption keys
Run the tests locally:
npm run test:runRun the same verification chain used by CI:
npm run ciThe CI workflow in .github/workflows/pr-checks.yml runs on pull requests targeting main and on pushes to main. It installs dependencies with npm ci, then runs lint, typecheck, tests, and the production build.
src/app Next.js routes and API handlers
src/components Shared UI components
src/lib Client/server utilities and provider helpers
src/server Server-side services, repositories, and domain modules
src/types Shared TypeScript types
supabase/migrations Database schema migrationsThe dashboard overview is loaded through /api/dashboard/overview.
The server attempts to use data in this order:
- Fresh
dashboard_overview_cache - Stored
contribution_daily_totals, when accounts have a recent sync - Provider APIs, followed by persistence of daily totals and cache refresh
Provider tokens are stored encrypted in Supabase and are never returned to the frontend.
- Configure public variables as regular config values:
NEXT_PUBLIC_SUPABASE_URLNEXT_PUBLIC_SUPABASE_ANON_KEYGITHUB_OAUTH_CLIENT_IDGITLAB_OAUTH_CLIENT_ID
- Configure sensitive values as secrets:
SUPABASE_SERVICE_ROLE_KEYGITFUSION_TOKEN_ENCRYPTION_KEYGITHUB_OAUTH_CLIENT_SECRETGITLAB_OAUTH_CLIENT_SECRET
- Apply Supabase migrations before connecting production accounts.
- Make sure production OAuth callback URLs match the deployed domain exactly.
This project is licensed under the MIT License.
