The maker's introduction consists of the line above. Read the repository README for more details. Repository README ↗
Loading the full README.
Read the full README ↗A scalable, high-throughput Discord clone built with Next.js 16 (React 19), Express 5, Mediasoup v3 SFU, Redis Streams, and PostgreSQL (Drizzle ORM).
docker run -d --name discord-redis -p 6379:6379 redis:alpine
cd backend
npm install
npx drizzle-kit push
npm run dev
To persist messages and reactions into PostgreSQL:
# In separate terminals:
npm run streamWorker # Chat message persistence
npm run reactionWorker # Message reaction persistence
cd frontend
npm install
npm run dev
Visit http://localhost:3000 in your browser.
The phone apps are the same Next.js frontend wrapped with Capacitor 8, plus native Bluetooth mesh plugins (frontend/android/, frontend/ios/). The normal web build (npm run dev / npm run build) is not affected by any of this.
cd frontend
npm install
cp .env.capacitor.example .env.capacitor
Edit frontend/.env.capacitor and set the backend address the phone should use. On a phone, localhost is the phone itself, so use:
http://<your PC's Wi-Fi IP>:4000 (find it with ipconfig)http://10.0.2.2:4000https:// server, with CAP_ALLOW_HTTP=falseThe backend URL is baked into the app at build time. If you change
.env.capacitor, rebuild the app.
Requirements: Android Studio (with the Android SDK) and JDK 21 exactly. JDK 17 is too old and the JDK 25 bundled with Android Studio is too new for Gradle 8.14. In Android Studio: Settings → Build Tools → Gradle → Gradle JDK → Download JDK → 21. For command-line builds, point JAVA_HOME at a JDK 21.
Build the web app and copy it into the Android project:
npm run build:app
Compile the APK — either:
npm run app:open, then Build → Build App Bundle(s) / APK(s) → Build APK(s), orfrontend/android):
./gradlew assembleDebug
(PowerShell / cmd: .\gradlew.bat assembleDebug)The APK is written to frontend/android/app/build/outputs/apk/debug/app-debug.apk.
Install it on a phone (USB debugging on, phone plugged in):
adb install -r app/build/outputs/apk/debug/app-debug.apk
Or copy the APK to the phone and open it (allow "install unknown apps"). Shortcut for steps 2–3: npm run app:run builds and launches on a connected phone.
Release APK: Android Studio → Build → Generate Signed App Bundle / APK, create or pick a keystore, choose APK → release. Use an https backend for release builds.
Requirements: a Mac with Xcode and Node 22. Swift can't be compiled on Windows.
npm run build:ios
npm run ios:open
| Way | Cost | Who can install | How long it lasts |
|---|---|---|---|
| Xcode → Run (above) | Free | Phones plugged into your Mac | 7 days, then Run again |
| AltStore (below) | Free | Anyone with an Apple ID and a PC or Mac | 7 days, refreshed automatically over Wi-Fi |
| TestFlight / Ad Hoc | $99/year Apple Developer account | Up to 10,000 testers by link (TestFlight) | 90 days (TestFlight), 1 year (Ad Hoc) |
The website works in Safari for chat and voice, but not for the Bluetooth mesh: Safari can't use Bluetooth, so mesh on iPhone needs the app.
.ipa with AltStoreWith a free Apple ID you can't send someone an .ipa that installs by tapping it. With AltStore, each person installs it with their own Apple ID, and AltStore signs it on their phone.
Step 1 — Make the .ipa (you, on the Mac). Build it unsigned; AltStore signs it later. From frontend/:
npm run build:ios
cd ios/App
xcodebuild -project App.xcodeproj -scheme App -configuration Release -sdk iphoneos -derivedDataPath build CODE_SIGNING_ALLOWED=NO
mkdir -p Payload
cp -R build/Build/Products/Release-iphoneos/App.app Payload/
zip -r DemoDiscord.ipa Payload
rm -rf Payload
This gives you frontend/ios/App/DemoDiscord.ipa. Send it to testers by AirDrop, Google Drive, WhatsApp or similar. An .ipa is just a zip file with a Payload/App.app folder inside.
Set the backend in
.env.capacitorto a server the testers can reach (your deployedhttpsserver) before building. Your home Wi-Fi IP only works on your Wi-Fi.
Step 2 — Install AltStore (each tester, once). They need a Windows PC or Mac and a USB cable.
This is the beginning of the README. Read the rest at the original. Read the full README ↗