8.4 KiB
Ikar
Ikar is a working Telegram-like messenger MVP built in this folder with an ASP.NET Core backend, an Android MAUI client, and a dedicated WinUI 3 desktop client for Windows.
Stack
src/Ikar.Server: ASP.NET Core 10 Web API + SignalR + SQLite.src/Ikar.Shared: shared DTO/contracts used by server and client.src/Ikar.Client: .NET MAUI client targetingnet10.0-android.src/Ikar.WinUI: WinUI 3 desktop client targetingnet10.0-windows10.0.19041.0.
Implemented
- phone-based sign-in with one-time test codes
- JWT access tokens with rotating refresh tokens
- secure client-side session persistence
- seeded demo accounts and sample chats
- Android contact-book lookup against registered phone numbers
- direct chats
- group chats
- channels with owner-only publishing
- message history persisted in SQLite
- file attachments with metadata persisted in SQLite
- voice notes as audio-classified attachments
- inline voice note playback in Android chat
- message edit/delete with realtime updates
- authenticated attachment download
- real-time message delivery with SignalR
- Android direct-chat audio/video calls with SignalR-based signaling and WebRTC media transport
- dedicated Android call screen for incoming and outgoing audio calls
- Android call ring/ringback tones and proximity-based screen blanking during active calls
- Android push registration API and FCM-based push delivery pipeline
- web admin panel for users, chats, attachments, and system status
- public landing page at
/with latest Android APK download - publishable Windows
exe - publishable Android
apk
Not Implemented
This is not full Telegram parity. The following are not implemented in this MVP:
- microphone recording UI for voice notes
- stickers and inline media previews
- end-to-end encryption
- advanced channel admin roles, granular moderation policies, multi-device sync edge cases
- Windows cloud push notifications
Demo Accounts
alice, phone+10000000001bob, phone+10000000002carol, phone+10000000003
These are created automatically on first server start in src/Ikar.Server/Data/ikar.db.
Run
- Start the backend:
./scripts/run-server.ps1
- Run the Windows client from Visual Studio or CLI:
dotnet build .\src\Ikar.WinUI\Ikar.WinUI.csproj -f net10.0-windows10.0.19041.0 -p:Platform=x64
.\src\Ikar.WinUI\bin\x64\Debug\net10.0-windows10.0.19041.0\win-x64\Ikar.WinUI.exe
- Run the Android client from Visual Studio or install the generated APK:
dotnet build .\src\Ikar.Client\Ikar.Client.csproj -f net10.0-android
The Android client is hard-wired to the current production endpoint:
- Android client default base URL:
https://ikar.kusoft.xyz
The Android login screen no longer exposes a server URL field.
The production Docker deployment binds the backend to 127.0.0.1:5099 on the Raspberry Pi host. Public and LAN clients should use the reverse-proxied HTTPS endpoint instead of direct access to port 5099:
- public Android / browser / admin URL:
https://ikar.kusoft.xyz
Run In Docker
Docker assets for Raspberry Pi 5 are included in the repo:
Dockerfile.serverdocker-compose.rpi5.yml.env.example.env.serverdocs/raspberry-pi-5-docker.md
Quick start:
cp .env.example .env
docker compose -f docker-compose.rpi5.yml up -d --build
To place server data on an external disk, set IKAR_DATA_PATH before running Compose. The current production Pi uses /media/myDrive/ikar-data.
Health check:
curl http://127.0.0.1:5099/health
Admin panel:
/adminredirects to/admin/index.html- configure admin login through
Admin__UsernameandAdmin__Password - the admin surface uses its own cookie session and does not reuse messenger JWT tokens
/serves a public landing page with a button for the latest Android APK/api/app-updates/android/download/latestreturns the latest published Android APKscripts/publish-android-update.ps1keeps only the newest3Android APK files on the server by default; override with-KeepLatestCount <N>if needed
Publish
Windows EXE:
./scripts/publish-windows.ps1
Android APK:
./scripts/publish-android-apk.ps1
Smoke test against the running backend:
./scripts/smoke-test.ps1
Published Artifacts
- Windows EXE:
artifacts/winui-win64/Ikar.WinUI.exe - Android APK:
src/Ikar.Client/bin/Release/net10.0-android/publish/com.seven.ikar.apk - Signed Android APK:
src/Ikar.Client/bin/Release/net10.0-android/publish/com.seven.ikar-Signed.apk
Solutions
- XML solution:
Ikar.slnx - classic Visual Studio solution:
IkarClassic.sln
Auth Notes
- Android client auth is currently
phone-only. - The current verification flow returns a temporary test code from the server and shows it in the client UI.
- Real SMS delivery is not implemented yet; it can be connected later by adding an SMS provider.
- Access tokens are short-lived JWTs.
- Refresh tokens are rotated on refresh and stored as hashed server-side sessions.
- Logout revokes the active session immediately, and the revoked access token stops working because the server validates the session id (
sid) on authenticated requests. - Session
LastSeenAtwrites are throttled server-side to reduce unnecessary SQLite writes on every authenticated request. - The JWT signing key in
src/Ikar.Server/appsettings.jsonis a development default. Replace it with a strong secret via configuration before any real deployment.
Contacts Notes
- Android contact discovery requests
READ_CONTACTSand only shows people from the device phone book. - Server-side contact resolution matches users by normalized phone number through
api/users/contacts/resolve. - Users without a registered phone number do not appear in the Android contacts screen.
Attachment Notes
- Attachments are stored on the server under
src/Ikar.Server/Data/Attachments. - Metadata stored for each attachment: original file name, content type, file size, upload time, and owning message.
- Audio files are classified as
voice notesby MIME type / file extension and use the same secure attachment pipeline. - Attachment content is downloaded through an authenticated API route, not via a public static files directory.
Channel And Message Lifecycle Notes
- Channels are broadcast rooms: the creator is the owner, selected users join as subscribers, and only owners can publish.
- Message edit/delete is synchronized through SignalR
MessageUpdatedevents. - Delete is implemented as a soft-delete on the message row with attachment cleanup on the server.
Call Notes
- Calls are currently implemented only for Android and only in direct one-to-one chats.
- The current call architecture uses SignalR for call lifecycle/signaling and WebRTC for audio/video media transport.
- ICE servers are configured server-side through the
WebRtcconfiguration section. - WinUI does not support calls in the current build.
Push Setup Notes
- Android push in this repo is implemented through Firebase Cloud Messaging HTTP v1 on the server and
FirebaseMessagingServiceon the Android client. - Server-side device registrations are stored in SQLite in the
PushDevicestable and managed throughapi/push/devices. - Push dispatch is queued through a background worker so message sends do not wait on outbound Firebase network latency.
- To enable real Android delivery, set
Push:FirebaseProjectIdand eitherPush:ServiceAccountJsonPathorPush:ServiceAccountJsoninsrc/Ikar.Server/appsettings.jsonor environment-specific configuration. - Before building the Android APK, fill
src/Ikar.Client/Resources/Raw/firebase.android.jsonwith the Android Firebase values:applicationId,projectId,apiKey,senderId. - If the Firebase configuration is left empty, the app still builds and the server still accepts device registrations, but actual FCM delivery is skipped.
- The current Windows WinUI desktop target is unpackaged (
WindowsPackageType=None), so this pass does not implement Windows cloud push.
Server Runtime Notes
- Chat list loading now fetches only the latest message per chat for summary rendering instead of loading full message history.
- The server exposes
/healthfor container and deployment health checks. - The server exposes
/admin/api/*plus static admin assets under/admin/*when admin credentials are configured. - Startup enables SQLite write-ahead logging and ensures an index on
ChatMembers.UserIdfor chat list lookup.