Samtalsvän is a very simple video calling tool for elderly people.
No apps. No login. No complexity.
Start a call → share a link or QR code → talk instantly.
I wanted to give something back to the country that welcomed me. Sweden has a growing elderly population, and many seniors feel isolated – especially when technology becomes a barrier. Existing video tools often require accounts, downloads, or confusing steps.
Samtalsvän (Swedish for "Conversation Friend") is my small contribution: a tool that turns a video call into a one-click experience. A family member or volunteer creates a call, prints a QR code, and the elderly person simply scans it – that's it. No login, no password, no frustration.
If this tool helps even one person connect with a loved one, it was worth building.
- Create a contact card for your elderly relative
- Print it out and give it to them
- Keep your browser open
- Scan the QR code with their phone camera
- That's it – the video call starts immediately
No apps to install. No accounts to create. No passwords to remember.
Just a printed card and a phone camera.
- Open the app in your browser
- Click "Starta videosamtal" (Start video call)
- Share the link or QR code with the other person
- They scan/click and the call begins!
- Click "Skapa kontaktkort" (Create contact card)
- Enter a name (optional)
- Click "Skapa kontaktkort" to generate
- Print the card and give it to your elderly relative
- Keep your browser open on the "Wait for calls" page
- When they scan the QR code, you'll receive an incoming call!
- Click "Mina kontakter" (My contacts) on the start screen
- View all saved contact cards
- Print any contact card again
- Delete contacts you no longer need
- Mute/Unmute: Click the microphone icon
- Camera on/off: Click the camera icon
- Switch camera: Click the switch icon (mobile only)
- Fullscreen: Click the fullscreen icon
- Chat: Click the chat icon to open the chat panel
- 🔓 No login required – Just start a call and share the link
- 📱 QR code sharing – Easy sharing for mobile users
- 📤 Share button – Share call link via Web Share API
- 💬 SMS sharing – Send call link via SMS
- 👴 Elderly-initiated calls – Create contact cards for seniors to call you
- 🎴 Printable contact cards – Large, clear print with high contrast
- 📋 Multiple contacts – Manage and save multiple contact cards
- 🎨 Swedish design – Yellow and blue color scheme for accessibility
- 📞 Ringtone – Audio notification for incoming calls
- 🔒 Privacy-focused – No data collection, all video peer-to-peer
- 🎤 Mute/Unmute – Toggle microphone on/off
- 📷 Camera on/off – Toggle camera with black screen when off
- 🔄 Camera switch – Switch between front/back cameras (mobile)
- ⏱️ Call timer – Shows elapsed call time
- 📶 Network indicator – Shows connection quality (Excellent/Good/Weak)
- 🔊 Speaker toggle – Switch between earpiece and speaker
- 🖥️ Fullscreen mode – Expand video to full screen
- 💬 Text chat – Send text messages during calls
- 📸 Photo sharing – Share photos during calls (up to 5MB)
- 🎙️ Voice messages – Record and send voice messages (up to 1 minute)
- 📅 Call scheduling – Schedule future calls with contacts
- 🔄 Auto-reconnect – Automatically reconnects if connection drops
- 📋 Contact management – View, print, and delete saved contacts
- ⏰ Date/Time widget – Displays current time and date (Swedish & English)
- 💾 Local storage – Contacts and schedules saved in browser
- 🔓 Ingen inloggning krävs – Starta bara ett samtal och dela länken
- 📱 QR-kodsdelning – Enkel delning för mobilanvändare
- 📤 Dela-knapp – Dela samtalslänk via Web Share API
- 💬 SMS-delning – Skicka samtalslänk via SMS
- 👴 Äldre kan ringa – Skapa kontaktkort för äldre att ringa dig
- 🎴 Utskrivbara kontaktkort – Stor, tydlig print med hög kontrast
- 📋 Flera kontakter – Hantera och spara flera kontaktkort
- 🎨 Svensk design – Gul och blå färgschema för tillgänglighet
- 📞 Ringsignal – Ljudnotis vid inkommande samtal
- 🔒 Integritetsfokus – Ingen datainsamling, all video peer-to-peer
- Node.js 18+
- npm or yarn
# Clone the repository
git clone https://github.com/AbdirahmanNomad/samtalsvan.git
cd samtalsvan
# Install dependencies
npm install
# Copy environment variables (optional for development)
cp .env.example .env
# Start the server
npm startThe app will be available at http://localhost:3000
| Variable | Description | Default |
|---|---|---|
PORT |
Server port | 3000 |
NODE_ENV |
Environment (development/production) | development |
BASE_URL |
Public URL for QR codes | http://localhost:3000 |
CORS_ORIGIN |
Allowed origins (comma-separated) | * |
For production, you need TURN servers for calls to work behind firewalls/NAT:
| Variable | Description |
|---|---|
OPENRELAY_ENABLED |
Set to true to enable OpenRelay TURN |
OPENRELAY_API_KEY |
Your OpenRelay API key (free at metered.ca/openrelay) |
TURN_SERVERS |
Custom TURN servers (format: turn:server:port|username|credential) |
TURN_USERNAME |
Default TURN username |
TURN_CREDENTIAL |
Default TURN credential |
┌─────────────────────────────────────────────────────────────┐
│ Frontend │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ index.html │ │ call.js │ │ style.css │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
└─────────────────────────────────────────────────────────────┘
│
│ Socket.io
▼
┌─────────────────────────────────────────────────────────────┐
│ Backend │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ server.js │ │ Socket.io │ │ QRCode │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
└─────────────────────────────────────────────────────────────┘
│
│ WebRTC
▼
┌─────────────────────────────────────────────────────────────┐
│ Peer-to-Peer │
│ Direct video/audio between browsers │
└─────────────────────────────────────────────────────────────┘
samtalsvan/
├── server.js # Express + Socket.io server
├── config.js # Configuration module
├── package.json # Dependencies
├── Dockerfile # Docker configuration
├── docker-compose.yml # Docker Compose (development)
├── docker-compose.prod.yml # Docker Compose (production with Caddy)
├── .env.example # Environment variables template
├── README.md # This file
├── CONTRIBUTING.md # Contribution guidelines
├── PRIVACY.md # Privacy policy
├── LICENSE # MIT License
├── deploy/ # Deployment configs
│ ├── Caddyfile # Caddy reverse proxy config
│ └── nginx.conf # Nginx reverse proxy config
├── scripts/ # Utility scripts
│ ├── backup.sh # Database backup script
│ └── restore.sh # Database restore script
├── .github/ # GitHub Actions
│ └── workflows/
│ └── ci.yml # CI/CD pipeline
└── public/
├── index.html # Main HTML
├── call.js # WebRTC logic
├── style.css # Styles
├── adapter.js # WebRTC adapter (local)
├── favicon.ico # App icon
└── fonts/ # Sweden Sans fonts
| Method | Endpoint | Description |
|---|---|---|
POST |
/create-call |
Create a new video call room |
POST |
/create-contact |
Create a contact card for elderly |
GET |
/contact/:code |
Get contact info by code |
DELETE |
/contact/:code |
Delete a contact (requires X-Owner-Token) |
GET |
/contacts |
Get multiple contacts (query: codes) |
GET |
/health |
Health check endpoint |
GET |
/health/ready |
Readiness check |
GET |
/health/live |
Liveness check |
GET |
/ice-servers |
Get ICE server configuration |
GET |
/api/user/data |
Export user data (GDPR, requires X-Owner-Token) |
DELETE |
/api/user/data |
Delete user data (GDPR, requires X-Owner-Token) |
- HTTPS - Required for WebRTC camera/mic access
- TURN Server - Required for NAT traversal (calls behind firewalls)
- Domain name - For SSL certificate
# Clone and configure
git clone https://github.com/AbdirahmanNomad/samtalsvan.git
cd samtalsvan
# Create .env file
cp .env.example .env
# Edit .env with your settings:
# - BASE_URL=https://your-domain.com
# - DOMAIN=your-domain.com
# - OPENRELAY_API_KEY=your-key (get free at metered.ca/openrelay)
# Start production stack
docker-compose -f docker-compose.prod.yml up -d# Install PM2
npm install -g pm2
# Start server
pm2 start server.js --name samtalsvan
# Setup nginx reverse proxy with Let's Encrypt
sudo apt install nginx certbot python3-certbot-nginx
sudo nano /etc/nginx/sites-available/samtalsvan
# Configure reverse proxy to localhost:3000
# Get SSL certificate
sudo certbot --nginx -d your-domain.com- Joi schemas for all user inputs
- XSS protection with output escaping
- Rate limiting on all endpoints
- Token-based authorization for contact deletion
- Socket.io room isolation
- Content Security Policy (CSP)
- HTTP Strict Transport Security (HSTS)
- X-Content-Type-Options: nosniff
- X-Frame-Options: DENY
- 10 requests/minute for call creation
- 20 requests/minute for contact operations
- 5 requests/minute for GDPR endpoints
GET /api/user/data- Export all user dataDELETE /api/user/data- Delete all user data
We welcome contributions! See CONTRIBUTING.md for details.
MIT – free to use, modify, and share. See LICENSE.
We don't collect any personal data. Video calls are peer-to-peer and never touch our servers. See PRIVACY.md for details.
Abdirahman Ahmed 📧 hello@abdirahman.net
Built with ❤️ for Sweden, and for every generation that deserves to stay connected.
Byggt med ❤️ för Sverige, och för varje generation som förtjän att hålla kontakten.