A modern, feature-rich GitHub mobile client — a beautiful alternative to the official GitHub app. Built with Expo 57, 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), Actions, Branches tabs
- Issues & PRs — coming soon
- 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
- Starred Repositories — browse starred repos with infinite scroll
- Favorites — save trending languages/topics for quick access
- Favorite trending languages and topics
- Search history for repeat queries
- Theme: Light · Dark · System
- Sign out
| Layer | Library |
|---|---|
| Framework | Expo 57 (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
│ └── settings/ # App settings screens
├── components/
│ ├── ui/ # Avatar, Badge, Skeleton, ChipFilter, LanguageDot,
│ │ # StatBar, Section, SettingsRow, EmptyState, + primitives
│ ├── explore/ # TrendingCard and explore-specific components
│ └── layout/ # Shared layout components
├── contexts/ # AuthContext, ThemeContext, ToastContext
└── lib/
├── api/ # Octokit, GraphQL client, TanStack QueryClient
│ └── hooks/ # useActivity, useTrending, useRepo, useNotifications,
│ # useSearch, useMyRepos, useWorkflows, useContributions
├── hooks/ # usePreferences, shared UI hooks
└── theme.ts # Light/dark theme tokens
See suggestions.md for the full feature backlog. Current priorities:
- Issues & PRs list screens
- Unit tests for API hooks
- Skeleton loaders across all list screens
- Optimistic updates + haptic feedback
- Notification, PR inbox, and releases home screen widgets (Android)
Three resizable widgets (Notifications, Pull requests, Recent releases).
They refresh about every 30 minutes via background fetch and on every app
open; the PR widget filter (All / Assigned / Review requested / Drafts) lives
in Profile → Settings → Home widgets. Widgets never hold your GitHub token —
the app snapshots token-free JSON to SharedPreferences, and sign-out clears
it. After changing widgets/ or plugins/, run bun run native:sync.
See CONTRIBUTING.md.