Your music, hosted by AI DJs.
A cross-platform mobile music app built around AI DJ personas. Every DJ has its own character, signature genres, and curated catalog — stream their tracks through a full-screen player with background playback, follow the ones you like, and watch your habits come to life in a personal Vibe Check.
Status: Actively in development. AI-generated tracks and DJ voice, plus subscriptions, are experimental and currently disabled.
- Design
- Features
- Tech stack
- Architecture
- Getting started
- Environment variables
- Project structure
- Scripts
- Contributing
- License
The images below are the product design (built with Stitch) — not screenshots of the running app.
| Home | Discover | DJ profile |
|---|---|---|
![]() |
![]() |
![]() |
| Player | Vibe Check | Live session |
![]() |
![]() |
![]() |
🎧 Listening
- Full-screen player with album art, a scrubbable progress bar, and queue navigation
- Background audio playback (lock screen / control center) on iOS and Android
- A persistent global mini-player that follows you across every screen
- Browse and discover DJs from Home and Discover
🎙️ DJ personas
- Rich DJ profiles: sonic philosophy, curated genres, and full track list
- "Live now" indicators for DJs currently on air
- Resident DJ badges
📊 Insights & personalization
- Vibe Check — personal listening stats: top DJs, top genres, and trends over time
- Music preferences that tailor your feed
- A community space
🔐 Accounts
- Google Sign-In with secure, chunked session storage (Expo SecureStore)
- Profile and account settings
🛠️ Platform
- iOS, Android, and Web (react-native-web) from a single codebase
- React Native New Architecture + React Compiler, with typed routes
- Dark, glassmorphic UI: Unistyles v3, Expo Blur, linear gradients, Manrope type, Reanimated 4
| Layer | Technology |
|---|---|
| Framework | Expo SDK 54 · React Native 0.81 · React 19 |
| Language | TypeScript 5.9 |
| Navigation | Expo Router 6 (file-based, typed routes) |
| Server state | TanStack Query v5 |
| Client state | Zustand 5 |
| Backend | Supabase — Postgres (RLS), Auth, Realtime, Storage |
| Auth | Google Sign-In (@react-native-google-signin) + Supabase JWT |
| Audio | expo-audio (background playback) |
| Styling | react-native-unistyles v3 · Expo Blur · expo-linear-gradient |
| Animation | Reanimated 4 · Gesture Handler |
| Icons & type | lucide-react-native · Manrope |
HiMu follows a layered client architecture on top of a Supabase backend:
- UI — screens via Expo Router and a reusable component library, animated with Reanimated.
- State — Zustand for client state (auth, player) and TanStack Query for server state and caching.
- Logic — custom hooks, an auth abstraction over Google Sign-In, the data layer (
supabase-js), and the audio engine (expo-audio). - Storage — sessions persisted to a chunked, secure adapter over Expo SecureStore.
- Cloud — Supabase Postgres (with RLS), Auth (Google OAuth → JWT), Realtime, and Storage for avatars and album art.
- Node.js 20+ and npm
- A Supabase project (supabase.com) and the Supabase CLI
- Google OAuth credentials (web + iOS client IDs)
- For native builds: Xcode (iOS) and/or Android Studio (Android)
Note: HiMu relies on native modules (Google Sign-In, background audio), so it runs from a development build rather than Expo Go.
# 1. Clone and install
git clone <your-repo-url> himu
cd himu
npm install
# 2. Configure environment
cp .env.example .env
# Fill in your Supabase URL + anon key and Google client IDs (see below)
# 3. Set up the database (Supabase CLI)
npx supabase login
npx supabase link --project-ref <your-project-ref>
npm run db:push # apply migrations from supabase/migrations
npm run db:types # regenerate src/types/database.ts
# 4. Run a development build
npm run ios # or: npm run androidIn Supabase, enable the Google provider under Auth → Providers and add the deep
link com.himu.app://callback under Auth → URL Configuration.
Copy .env.example to .env and fill in the required values:
| Variable | Required | Description |
|---|---|---|
EXPO_PUBLIC_SUPABASE_URL |
✅ | Supabase project URL |
EXPO_PUBLIC_SUPABASE_KEY |
✅ | Supabase anon / public key |
EXPO_PUBLIC_API_URL |
✅ | Supabase REST endpoint |
EXPO_PUBLIC_GOOGLE_WEB_CLIENT_ID |
✅ | Google OAuth web client ID |
EXPO_PUBLIC_GOOGLE_IOS_CLIENT_ID |
✅ | Google OAuth iOS client ID |
.env.examplealso lists optional keys for experimental AI features that are currently disabled — they aren't needed to run the app.
HiMu/
├── app/ # Expo Router routes (file-based navigation)
│ ├── _layout.tsx # Root stack, global providers, mini-player
│ ├── (auth)/ # Login (Google Sign-In)
│ ├── (app)/ # Tab group: Home · Discover · Community · Profile
│ ├── dj/[id].tsx # DJ profile
│ ├── player.tsx # Full-screen player (modal)
│ ├── vibe-check.tsx # Listening stats
│ ├── preferences.tsx # Music preferences
│ └── account-settings.tsx # Account settings
├── src/
│ ├── api/ # Supabase client + TanStack Query hooks
│ ├── audio/ # Player provider & audio engine (expo-audio)
│ ├── components/ # Reusable UI (dj, player, vibe, profile, …)
│ ├── hooks/ # Custom hooks
│ ├── stores/ # Zustand stores (auth, player)
│ ├── theme/ # Unistyles tokens & setup
│ ├── types/ # Generated Supabase types
│ ├── lib/ · utils/ # Helpers
├── supabase/
│ ├── migrations/ # Versioned SQL schema
│ └── seed.sql # Seed data
└── assets/ # Icons, fonts (Manrope), and design previews
| Script | Action |
|---|---|
npm start |
Start the Expo dev server |
npm run ios / npm run android |
Build and run a native development client |
npm run web |
Run in the browser |
npm run lint |
Lint with eslint-config-expo |
npm run db:push |
Apply Supabase migrations |
npm run db:types |
Regenerate src/types/database.ts from the linked project |
Contributions are welcome. Before opening a pull request:
- Make sure
npm run lintandnpx tsc --noEmitpass - Follow the existing module structure and the design tokens in
src/theme - Open an issue first to discuss larger changes
Licensed under the Apache License 2.0.





