A simple real-time messaging app built with Flutter & Firebase - designed for a single purpose: let people reach you directly from your personal website.
No need to share social media links. No need for third-party contact forms.
Just embed Talkest on your website, and anyone with a Google account can start a conversation with you instantly.
Why does this exist?
I built Talkest because I wanted a simple "get in touch" solution for my portfolio website. Instead of redirecting visitors to social media, they can just chat with me right there, powered by a Flutter Web widget embedded directly into the page.
- Real-time messaging — Powered by Cloud Firestore with live message streaming
- Google Sign-In — One-tap authentication, no extra account needed
- Light & Dark theme — With system theme detection and manual toggle
- QR Code profile — Each user gets a personal QR code for quick contact sharing
- QR Scanner — Scan someone's QR code to start a chat instantly
- Start chat by email — Find and message any registered user by their email address
- Editable display name — Customize how your name appears to others
- Embeddable chat widget — Deploy the Flutter Web build and embed it on any website via iframe
- Native mobile app — Install the Android app to monitor and reply to incoming messages on the go
| Platform | Status | Link |
|---|---|---|
| Android | ✅ Available | Github release |
| Web | ✅ Available | khip01.github.io/talkest |
| Embedded mode | ✅ Available | Used on my portfolio |
| iOS | ❌ Not yet | No Mac device available for development |
Note
Push notifications are currently not implemented.
A complete push notification flow requires Firebase Cloud Functions to trigger Firebase Cloud Messaging (FCM), which depends on the Blaze (pay-as-you-go) plan.
| Login | Chat List | Messaging |
![]() |
![]() |
![]() |
| Embed mode — Landing page on portfolio website |
|---|
![]() |
| Embed mode — Chat view on portfolio website |
|---|
![]() |
| Category | Technology |
|---|---|
| Framework | Flutter (Dart) |
| Backend | Firebase (Auth, Cloud Firestore) |
| Authentication | Google Sign-In |
| State Management | BLoC + Provider |
| Routing | GoRouter |
| Deployment | GitHub Pages (Web), APK (Android) |
- Flutter SDK
- Firebase project with Authentication and Cloud Firestore enabled
- Google OAuth 2.0 Client ID (for Flutter Web only)
Collections and documents are created automatically when the app runs for the first time — no manual setup needed. Below is the database structure for reference:
├── app_users (collection)
│ └── {uid} (document)
│ ├── name: string
│ ├── displayName: string
│ ├── email: string
│ ├── photoUrl: string
│ ├── provider: string
│ ├── createdAt: timestamp
│ ├── updatedAt: timestamp
│ └── lastLoginAt: timestamp
│
└── chats (collection)
└── {chatId} (document)
├── type: string ("direct")
├── participants: array [uid1, uid2]
├── createdAt: timestamp
├── updatedAt: timestamp
├── unreadCount: map { uid1: number, uid2: number }
├── lastMessage: map
│ ├── id: string
│ ├── senderId: string
│ ├── text: string
│ ├── type: string
│ ├── createdAt: timestamp
│ └── isDeleted: boolean
│
└── 📁 messages (subcollection)
└── {messageId} (document)
├── id: string
├── chatId: string
├── senderId: string
├── type: string
├── text: string
├── createdAt: timestamp
├── editedAt: timestamp (optional)
├── isDeleted: boolean
├── replyToId: string (optional)
├── replyToSenderId: string (optional)
├── replyToSenderName: string (optional)
└── replyToText: string (optional)
Security rules are defined in firestore.rules.
Important
The included rules are stricter than the default test-mode rules. They enforce that:
- Users can only write to their own profile
- Only chat participants can read/write chats and messages
- Messages can only be created (no editing or deleting from client)
Review and adjust the rules in firestore.rules to fit your needs before deploying.
This project requires a composite index for querying chats. The index configuration is defined in firestore.indexes.json.
| Collection | Fields | Query Scope |
|---|---|---|
chats |
participants (Array) + updatedAt (Descending) |
Collection |
Tip
If you skip deploying indexes, Firestore will show an error with a direct link to create the required index when the app first runs a query that needs it.
Deploy both rules and indexes at once:
firebase deploy --only firestore --project YOUR_PROJECT_IDOr deploy them individually if needed:
firebase deploy --only firestore:rules --project YOUR_PROJECT_ID
firebase deploy --only firestore:indexes --project YOUR_PROJECT_IDTip
If you skip this step, Firestore will show an error with a direct link to create the required index when the app first runs a query that needs it.
-
Via Firebase Console (Recommended):
- Open Firebase Console
- Select your project → Project Settings
- Add a Web app (if not already added)
- The Client ID will be auto-generated in Google Cloud Console
-
Manual Setup:
- Go to Google Cloud Console
- Navigate to APIs & Services → Credentials
- Create OAuth client ID → Select Web application
- Configure:
- Authorized JavaScript origins:
http://localhosthttp://localhost:5000https://your-domain.firebaseapp.com(production)
- Authorized redirect URIs:
https://your-domain.firebaseapp.com/__/auth/handler
- Authorized JavaScript origins:
- Copy the generated Client ID
Web (Development):
flutter run -d <web-device> --dart-define=GOOGLE_WEB_CLIENT_ID=YOUR_CLIENT_ID.apps.googleusercontent.comMobile (Android/iOS):
flutter run -d <device-id>Web (Release)
flutter build web --elease --dart-define=GOOGLE_WEB_CLIENT_ID=YOUR_CLIENT_ID.apps.googleusercontent.comImportant
Web builds require the Google Web Client ID for authentication.
Mobile (Release)
flutter build --releaseMobile builds do not require additional parameters and can be built normally in release mode.
Talkest supports an embedded chat widget mode, designed to be loaded inside an <iframe> on any website. This allows visitors to chat with a specific user directly from your page.
URL format:
https://your-talkest-deployment.com/?embed=1&targetUid=FIREBASE_USER_UID
Example iframe usage:
<iframe
src="https://khip01.github.io/talkest/?embed=1&targetUid=YOUR_FIREBASE_UID"
width="400"
height="600"
style="border: none; border-radius: 12px;"
allow="clipboard-read; clipboard-write"
></iframe>Parameters:
| Parameter | Required | Description |
|---|---|---|
embed |
Yes | Set to 1 to activate embedded mode |
targetUid |
Yes | The Firebase UID of the user to chat with |
Tip
You can find your Firebase UID in the Firebase Console → Authentication → Users tab.
In embed mode, the app will:
- Show a landing page with a sign-in prompt for unauthenticated visitors
- Automatically open a direct chat with the target user after sign-in
- Hide navigation elements like the FAB and profile access for a clean widget experience
Made with 🤍 by Khip01




