# Product Description avaaz.ai

avaaz.ai is a mobile and web application featuring a motivating conversational AI tutor powered by advanced agentic capabilities. It teaches oral language skills through structured, interactive lessons that adapt to each student’s pace and performance. The core goal is to help students speak new languages confidently to pass the B2 oral proficiency exam.

## 1. Features 1. **Voice-First Conversational Engine** — Students engage in ultra-low-latency speech-to-speech interaction with the AI Tutor, enabling natural dialogue and instant corrective feedback using speech, text, and visuals. 2. **CEFR-B2 Aligned Curriculum with Real-Time AI Practice** — A full CEFR-based speaking progression up to B2, seamlessly integrated with adaptive AI conversation to bridge passive knowledge and active speaking skills. 3. **Immigrant-Focused Real-Life Scenarios** — Lessons target real-world contexts relevant to immigrants, such as workplace, healthcare, school, or daily interactions, enhancing integration and confidence in practical use. 4. **Mock Oral Exam Mode** — Simulates B2 oral exams and citizenship interviews with timed prompts, rubrics, and examiner-style feedback to build test readiness. 5. **Multilingual Scaffolding and Integrated Translation** — Learners receive UI support, bilingual explanations, and on-demand translations in their native language, helping low-confidence speakers stay engaged. 6. **Comprehensive Speaking Feedback** — Beyond pronunciation and grammar, learners get targeted insights on fluency, phrasing, coherence, and vocabulary range, aligned with B2 standards. 7. **Accent and Cultural Adaptation** — Lessons reflect local dialects and cultural etiquette relevant to the learner’s destination country, supporting realistic and socially appropriate speech. 8. **Immersive Role-Plays with Visual Cues** — Speaking simulations are enhanced with contextual images (e.g. menus, documents, locations) to deepen realism and task-based practice. 9. **Gamified Progress and Motivation** — Daily speaking challenges, streak rewards, and level badges reinforce habit formation and learning consistency. 10. **Post-Session Performance Summaries** — After each session, learners receive a concise report of strengths, errors, and suggested improvements to reinforce progress. 11. **Customizable AI Tutor Voices** — Learners can choose from various voice options with different genders or regional accents to diversify listening practice and personalize interaction. 12. **Cross-Device Learning Continuity** — Seamless synchronization ensures progress tracking and learning state remain consistent across mobile and web platforms. ## 2. Student & AI Tutor Interactions (English → Norwegian Bokmål) ### 2.1 Real-Time Conversational Flow **Scenario:** A beginner is learning everyday greetings. **AI Tutor (in Norwegian):** “Hei! Hvordan går det?” **Student:** “Uh… I think that means, ‘How are you?’” **AI Tutor:** “Exactly! You can answer: *Jeg har det bra* — that means ‘I’m doing well.’ Try it: *Jeg har det bra.*” **Student:** “Jeg har det bra.” **AI Tutor:** “Flott! Literally, it means ‘I have it good.’ Norwegians use that to say they’re fine.” **Benefit:** The AI provides instant translation and cultural context, helping English speakers grasp meaning and tone through natural conversation. ### 2.2 Adaptive Pronunciation, Fluency, and Grammar Support **Scenario:** The learner practices sentence structure and pronunciation. **AI Tutor:** “Let’s say: *Jeg bor i Oslo* — ‘I live in Oslo.’” **Student:** “Jeg bor på Oslo.” **AI Tutor:** “Almost right! We say *i Oslo*, not *på Oslo*. *I* means ‘in,’ while *på* means ‘on.’ Try again: *Jeg bor i Oslo.*” **Student:** “Jeg bor i Oslo.” **AI Tutor:** “Perfekt! Now, about pronunciation — it’s *Oslo*, not *Osh-lo.* The *s* is soft. Listen: *Oslo.*” **Student:** “Oslo.” **AI Tutor:** “Bra! That sounded natural.” **Benefit:** The AI corrects grammar and pronunciation simultaneously, giving immediate, native-level feedback tailored to English-speaking learners. ### 2.3 Scenario-Based Oral Practice **Scenario:** The learner prepares for a B2-level job interview. **AI Tutor:** “Du er på et jobbintervju. Spørsmålet er: *Hvorfor vil du jobbe her?* — ‘Why do you want to work here?’” **Student:** “Fordi jeg liker din selskap.” **AI Tutor:** “Good start! In Norwegian, we say *firmaet ditt* instead of *din selskap*. Try: *Fordi jeg liker firmaet ditt og arbeidsmiljøet her.* — ‘Because I like your company and the work environment here.’” **Student:** “Fordi jeg liker firmaet ditt og arbeidsmiljøet her.” **AI Tutor:** “Veldig bra! That sounded confident and natural.” **Benefit:** The learner rehearses authentic B2-level oral exam tasks and professional interactions with context-sensitive correction and adaptive feedback. ## 3. Pricing Plans | **Plan** | **Hours** | **NOK** | **Purpose** | | --------------------------------- | :-------: | ------------: | ------------------------------------------------------------------- | | **First Light** | 1 | **Gratis** | A taste of the experience - no pressure, no card required. | | **Spark** | 5 | **kr 999** | A short, flexible plan to get started or focus on specific skills. | | **Glow** | 15 | **kr 1 999** | Great for consistent improvement and practicing real conversations. | | **⭐ Shine** *(Recommended)* | 50 | **kr 5 999** | The sweet spot for building natural fluency and confidence. | | **Radiance** | 200 | **kr 17 999** | Designed for dedicated learners seeking transformation. | ## 4. Configuration ### 4.1 Configure the VPS #### 4.1.1 Configure the firewal at the VPS host | Public IP | | :------------: | | 217.154.51.242 | | Action | Allowed IP | Protocol | Port(s) | Description | | :-----: | :--------: | :------: | ----------: | :------------ | | Allow | Any | TCP | 80 | HTTP | | Allow | Any | TCP | 443 | HTTPS | | Allow | Any | TCP | 2222 | Git SSH | | Allow | Any | TCP | 2885 | VPS SSH | | Allow | Any | UDP | 3478 | STUN/TURN | | Allow | Any | TCP | 5349 | TURN/TLS | | Allow | Any | TCP | 7881 | LiveKit TCP | | Allow | Any | UDP | 50000-60000 | LiveKit Media | #### 4.1.2 Configure the DNS settings at domain registrar | Host (avaaz.ai) | Type | Value | | :-------------: | :---: | :------------: | | @ | A | 217.154.51.242 | | www | CNAME | avaaz.ai | | app | A | 217.154.51.242 | | api | A | 217.154.51.242 | | rtc | A | 217.154.51.242 | | git | A | 217.154.51.242 | #### 4.1.3 Change the SSH port from 22 to 2885 1. Connect to the server. ```bash ssh username@avaaz.ai ``` 2. Edit the SSH configuration file. ```bash sudo nano /etc/ssh/sshd_config ``` 3. Add port 2885 to the file and comment out port 22. ```text #Port 22 Port 2885 ``` 4. Save the file and exit the editor. - Press `Ctrl+O`, then `Enter` to save, and `Ctrl+X` to exit. 5. Restart the SSH service. ```bash sudo systemctl daemon-reload && sudo systemctl restart ssh.socket && sudo systemctl restart ssh.service ``` 6. **Before closing the current session**, open a new terminal window and connect to the server to verify the changes work correctly. ```bash ssh username@avaaz.ai # ssh: connect to host avaaz.ai port 22: Connection timed out ssh username@avaaz.ai -p 2885 ``` 7. Once the connection is successful, close the original session safely. #### 4.1.4 Build and deploy the infrastructure 1. Check with `dig git.avaaz.ai +short` wether the DNS settings have been propagated. 2. SSH into the VPS to install Docker & docker compose. ```bash ssh username@avaaz.ai -p 2885 ``` 3. Update system packages. ```bash sudo apt update && sudo apt upgrade -y ``` 4. Install dependencies for Docker’s official repo ```bash sudo apt install -y \ ca-certificates \ curl \ gnupg \ lsb-release ``` 5. Add Docker’s official APT repo. ```bash sudo install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg \ sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg echo \ "deb [arch=$(dpkg --print-architecture) \ signed-by=/etc/apt/keyrings/docker.gpg] \ https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) stable" \ sudo tee /etc/apt/sources.list.d/docker.list > /dev/null sudo apt update ``` 6. Install Docker Engine + compose plugin. ```bash sudo apt install -y \ docker-ce \ docker-ce-cli \ containerd.io \ docker-buildx-plugin \ docker-compose-plugin ``` 7. Verify the installation. ```bash sudo docker --version sudo docker compose version ``` 8. Create the `/etc/docker/daemon.json` file to avoid issues with overusing disk for log data. ```bash sudo nano /etc/docker/daemon.json ``` 9. Paste the following. ```json { "log-driver": "local", "log-opts": { "max-size": "10m", "max-file": "3" } } ``` 10. Save the file and exit the editor. - Press `Ctrl+O`, then `Enter` to save, and `Ctrl+X` to exit. 11. Restart the docker service to apply changes. ```bash sudo systemctl daemon-reload sudo systemctl restart docker ``` 12. Create directory for infra stack in `/srv/infra`. ```bash sudo mkdir -p /srv/infra sudo chown -R $USER:$USER /srv/infra cd /srv/infra ``` 13. Create directories for Gitea (repos, config, etc.) and Runner persistent data. Gitea runs as UID/GID 1000 by default. ```bash mkdir -p gitea-data gitea-runner-data ``` 14. Create the `/srv/infra/docker-compose.yml` (Caddy + Gitea + Runner) file. ```bash nano docker-compose.yml ``` 15. Paste the following. ```yaml services: caddy: # Use the latest official Caddy image image: caddy:latest # Docker Compose automatically generates container names: __ container_name: caddy # Fixed name used by Docker engine # Automatically restart unless manually stopped restart: unless-stopped ports: # Expose HTTP (ACME + redirect) - "80:80" # Expose HTTPS/WSS (frontend, backend, LiveKit) - "443:443" volumes: # Mount the Caddy config file read-only - ./Caddyfile:/etc/caddy/Caddyfile:ro # Caddy TLS certs (persistent Docker volume) - caddy_data:/data # Internal Caddy state/config - caddy_config:/config networks: # Attach to the shared "proxy" network - proxy gitea: # Official Gitea image with built-in Actions image: gitea/gitea:latest container_name: gitea # Fixed name used by Docker engine # Auto-restart service restart: unless-stopped environment: # Run Gitea as host user 1000 (prevents permission issues) - USER_UID=1000 # Same for group - USER_GID=1000 # Use SQLite (stored inside /data) - GITEA__database__DB_TYPE=sqlite3 # Location of the SQLite DB - GITEA__database__PATH=/data/gitea/gitea.db # Custom config directory - GITEA_CUSTOM=/data/gitea volumes: # Bind mount instead of Docker volume because: # - We want repos, configs, SSH keys, and SQLite DB **visible and editable** on host # - Easy backups (just copy `./gitea-data`) # - Easy migration # - Avoids losing data if Docker volumes are pruned - ./gitea-data:/data networks: - proxy ports: # SSH for Git operations mapped to host 2222 - "2222:22" gitea-runner: # Official Gitea Actions Runner image: gitea/act_runner:latest container_name: gitea-runner # Fixed name used by Docker engine restart: unless-stopped depends_on: # Runner requires Gitea to be available - gitea volumes: # Runner uses host Docker daemon to spin up job containers (Docker-out-of-Docker) - /var/run/docker.sock:/var/run/docker.sock # Bind mount instead of volume because: # - Runner identity is stored in /data/.runner # - Must persist across container recreations # - Prevents duplicated runner registrations in Gitea # - Easy to inspect/reset via `./gitea-runner-data/.runner` - ./gitea-runner-data:/data environment: # Base URL of your Gitea instance - GITEA_INSTANCE_URL=${GITEA_INSTANCE_URL} # One-time registration token - GITEA_RUNNER_REGISTRATION_TOKEN=${GITEA_RUNNER_REGISTRATION_TOKEN} # Human-readable name for the runner - GITEA_RUNNER_NAME=${GITEA_RUNNER_NAME} # Runner labels (e.g., ubuntu-latest) - GITEA_RUNNER_LABELS=${GITEA_RUNNER_LABELS} # Set container timezone to UTC for consistent logs - TZ=Etc/UTC networks: - proxy # Start runner using persisted config command: ["act_runner", "daemon", "--config", "/data/.runner"] networks: proxy: # Shared network for Caddy + Gitea (+ later app stack) name: proxy # Default Docker bridge network driver: bridge volumes: # Docker volume for Caddy TLS data (safe to keep inside Docker) caddy_data: name: caddy_data # Docker volume for internal Caddy configs/state caddy_config: name: caddy_config ``` 16. Save the file and exit the editor. - Press `Ctrl+O`, then `Enter` to save, and `Ctrl+X` to exit. 17. Create the `/srv/infra/.env` file with environment variables. ```bash nano .env ``` 18. Paste the following: ```env # Base URL of your Gitea instance (used by the runner to register itself # and to send/receive workflow job information). GITEA_INSTANCE_URL=https://git.avaaz.ai # One-time registration token generated in: # Gitea → Site Administration → Actions → Runners → "Generate Token" # This MUST be filled in once, so the runner can register. # After registration, the runner stores its identity inside ./gitea-runner-data/.runner # and this value is no longer needed (can be left blank). GITEA_RUNNER_REGISTRATION_TOKEN= # Human-readable name for this runner. # This is shown in the Gitea UI so you can distinguish multiple runners: # Example: "vps-runner", "staging-runner", "gpu-runner" GITEA_RUNNER_NAME=gitea-runner # Runner labels allow workflows to choose specific runners. # The label format is: label[:schema[:args]] # - "ubuntu-latest" is the