A modern, feature-rich GitHub mobile client — a beautiful alternative to the official GitHub app. Built with Expo 55, React 19, and Uniwind.
- GitHub activity feed (Push, Watch, Fork, PR, Issue, Release events)
- Infinite scroll with pull-to-refresh
- Per-event-type cards with icons and relative timestamps
- Global search — repos, users, issues/PRs with debounced instant results
- Trending Repositories (powered by GitHub Search API):
- Filter by period: Today · This Week · This Month
- Filter by language: 25+ languages
- Sort by stars, forks, recently pushed
- Trending Developers — filter by language
- Topics Browser — 8 category groups, 40+ curated topics
- Segments: All · Participating · Assigned · Mentioned
- Grouped by type, mark individual or all as read
- Unread badge count
- List your repos with filter (Owner / All / Public / Private / Forks)
- Search, infinite scroll, last-updated timestamps
- Per-repo cards with language dot, stars, forks
- Detail view — About (description, topics, stats), Issues, PRs, Actions, Branches tabs
- Settings — rename, description, website, topics/keywords (chip UI with autocomplete), visibility toggle (public ↔ private), archive
- GitHub Pages — live status, source branch, custom domain, HTTPS toggle
- Actions / Workflows — per-workflow run history, trigger manual dispatch, cancel runs, auto-refresh every 30s
- Contribution heat-map (GitHub GraphQL
contributionCalendar) - Stats: repos · followers · following
- Bio, company, location, blog
- Theme: Light · Dark · System
- Sign out
| Layer | Library |
|---|---|
| Framework | Expo 55 (CNG) · Expo Router |
| UI / Styling | React Native + Uniwind (Tailwind CSS) |
| Icons | expo-vector-icons (Ionicons) |
| Images | expo-image |
| GitHub API | @octokit/rest + @octokit/graphql |
| Server state | TanStack Query v5 |
| Auth | expo-auth-session + expo-web-browser |
| Secure storage | expo-secure-store |
| Animations | react-native-reanimated 4 + react-native-worklets |
| Dates | date-fns |
git clone https://github.com/involvex/awesome-github-app
cd awesome-github-app
bun installbun run test— run Jest (jest-expo preset) in watch mode.bun run test:ci— run the suite with coverage in CI-friendly mode.- Tests use
__tests__/test-utils/render.tsxfor provider-wrapped renders andjest.setup.jsfor Expo/React Native mocks.
Two separate GitHub OAuth Apps are required — one for native (Android/iOS) and one for web.
- Go to GitHub → Settings → Developer settings → OAuth Apps → New OAuth App
- Set Authorization callback URL to:
awesomegithubapp://oauth/callback - Copy the Client ID and Client Secret
- Create a second OAuth App
- Set Authorization callback URL to:
http://localhost:8081/oauth/callback - Copy the Client ID and Client Secret
Set a .env file at the project root (loaded via app.config.js):
GITHUB_CLIENT_ID=<native-client-id>
GITHUB_CLIENT_ID_WEB=<web-client-id>The client secrets are never stored in the app. They live only in the Cloudflare Worker. Never commit
.env.
All token exchanges (both native and web) go through the Cloudflare Worker, which holds the client secrets server-side.
-
Navigate to the worker directory:
cd workers/oauth-token-exchange -
Create environment file:
cp .env.example .env
-
Add credentials to
.env:GITHUB_CLIENT_ID=<native-client-id> GITHUB_CLIENT_SECRET=<native-client-secret> GITHUB_CLIENT_ID_WEB=<web-client-id> GITHUB_CLIENT_SECRET_WEB=<web-client-secret>
-
Deploy the worker:
bun install bun run deploy
-
The worker will be deployed at:
https://awesomegithubapp-api.involvex.workers.dev
For production, use Cloudflare secrets instead of .env:
wrangler secret put GITHUB_CLIENT_ID
wrangler secret put GITHUB_CLIENT_SECRET
wrangler secret put GITHUB_CLIENT_ID_WEB
wrangler secret put GITHUB_CLIENT_SECRET_WEB
bun run deploy:prodbun run android # Build + run on Android device/emulator
bun run ios # Build + run on iOS simulator
bun run web # Web preview in browser
bun run start # Expo dev server (requires a dev client build)Native OAuth requires a development build (
bun run android/bun run ios). Expo Go is not supported.
| Script | Description |
|---|---|
bun run start |
Start Expo dev server |
bun run android |
Prebuild → run Android |
bun run ios |
Prebuild → run iOS |
bun run web |
Web preview |
bun run native:sync |
Regenerate native folders from app.json |
bun run build |
Export for production |
bun run doctor |
Run expo-doctor health checks |
bun run typecheck |
TypeScript check |
bun run lint |
ESLint |
bun run format |
Prettier |
src/
├── app/
│ ├── (auth)/ # Login + OAuth callback
│ ├── (tabs)/ # Bottom tabs: feed, explore, notifications, repos, profile
│ ├── repo/[owner]/[repo]/ # Repo detail, settings, pages, workflows
│ └── user/[login].tsx # Public user profile
├── components/
│ └── ui/ # Avatar, Badge, Skeleton, ChipFilter, LanguageDot,
│ # StatBar, Section, SettingsRow, EmptyState, + primitives
├── contexts/ # AuthContext, ThemeContext, ToastContext
└── lib/
├── api/ # Octokit, GraphQL client, TanStack QueryClient
│ └── hooks/ # useActivity, useTrending, useRepo, useNotifications,
│ # useSearch, useMyRepos, useWorkflows, useContributions
└── theme.ts # Light/dark theme tokens
- This project uses CNG (Continuous Native Generation) —
android/andios/folders are generated byexpo prebuildand are not committed to git. - App icon source file:
assets/icon.png. Usemagick icon-source.png -resize 1024x1024 assets/icon.pngto regenerate icons with ImageMagick. - Sponsor: github.com/sponsors/involvex