> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mentraglass.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Local Development

> Test your MentraOS app locally using ngrok tunneling

When developing your MentraOS app, you'll want to test it locally before deploying to production. This guide explains how local development works and how to set it up.

## How MentraOS Apps Work

Understanding the architecture helps explain why we need tunneling for local development:

```
User's Glasses ←→ MentraOS Relay Server←→ Your App Server
```

**The flow:**

1. User interacts with glasses (voice, buttons, camera)
2. MentraOS Relay Server processes the interaction
3. Relay Server sends events to **your app server** via webhook
4. Your app responds (display text, play audio, etc.)
5. Response flows back through the Relay Server to the user's phone, and then to the user's glasses

**The key requirement:** MentraOS Relay Server must be able to reach your app server over the internet.

## The Local Development Problem

When you run your app locally, it's only accessible on your machine:

```
Your App: http://localhost:3000 ✅ (you can access it)
         http://localhost:3000 ❌ (MentraOS Relay Server cannot access it)
```

**Why this doesn't work:**

* `localhost` is not a public address
* MentraOS Relay Server runs on the internet
* Relay Server can't reach your local machine directly
* Firewalls and routers block incoming connections

## The Solution: Tunneling with ngrok

**ngrok** creates a secure tunnel from a public URL to your local server:

```
MentraOS Relay Server → https://abc123.ngrok.io → localhost:3000 → Your App
                        (public internet)         (your machine)
```

Now MentraOS Relay Server can send events to `https://abc123.ngrok.io`, and they'll be forwarded to your local app.

***

## Quick Start

### 1. Install ngrok

**macOS:**

```bash theme={null}
brew install ngrok
```

**Linux:**

```bash theme={null}
curl -s https://ngrok-agent.s3.amazonaws.com/ngrok.asc | \
  sudo tee /etc/apt/trusted.gpg.d/ngrok.asc >/dev/null && \
  echo "deb https://ngrok-agent.s3.amazonaws.com buster main" | \
  sudo tee /etc/apt/sources.list.d/ngrok.list && \
  sudo apt update && sudo apt install ngrok
```

**Windows / Other:**
Download from [ngrok.com/download](https://ngrok.com/download)

### 2. Start Your App

```bash theme={null}
# In your app directory
bun install
bun run dev

# Your app is now running on http://localhost:3000
```

### 3. Start ngrok Tunnel

**In a new terminal:**

```bash theme={null}
ngrok http 3000
```

You'll see output like:

```
ngrok

Session Status                online
Account                       your-email@example.com (Plan: Free)
Version                       3.x.x
Region                        United States (us)
Latency                       -
Web Interface                 http://127.0.0.1:4040
Forwarding                    https://abc123.ngrok.io -> http://localhost:3000

Connections                   ttl     opn     rt1     rt5     p50     p90
                              0       0       0.00    0.00    0.00    0.00
```

**Copy the Forwarding URL:** `https://abc123.ngrok.io`

### 4. Update Developer Console

1. Go to [console.mentra.glass/apps](https://console.mentra.glass/apps)
2. Select your app
3. Set **App Server URL** to: `https://abc123.ngrok.io`
4. Save changes

### 5. Test on Glasses

1. Open your app on MentraOS glasses
2. Interact with it (speak, press buttons, etc.)
3. Watch your terminal - you should see events coming in
4. Check ngrok's web interface at `http://localhost:4040` to see requests

***

## Development Workflow

**Typical workflow:**

```bash theme={null}
# Terminal 1: Start your app
cd my-mentra-app
bun run dev

# Terminal 2: Start ngrok
ngrok http 3000

# Copy ngrok URL and update Developer Console
# → Test on glasses
# → Make code changes
# → App auto-restarts (if using nodemon)
# → Test again
```

**When you restart ngrok:**

* Free ngrok URLs change each time
* You must update the Developer Console with the new URL
* Paid ngrok plans provide persistent URLs

***

## ngrok Web Interface

ngrok provides a web interface at **[http://localhost:4040](http://localhost:4040)** showing:

* **Request Inspector** - See all incoming requests
* **Request/Response Details** - Headers, body, timing
* **Replay Requests** - Resend requests for debugging

This is incredibly useful for debugging webhook issues.

***

## Common Issues

### Issue: "Connection Refused"

**Problem:** ngrok can't connect to your local server

**Solution:**

```bash theme={null}
# Make sure your app is running first
bun run dev

# Then start ngrok in another terminal
ngrok http 3000
```

### Issue: "No Events Coming Through"

**Problem:** You don't see any requests in your terminal

**Solution:**

1. **Check packageName** - Must match exactly in both your code and Developer Console
2. **Check API key** - Must be correct and match your app in Developer Console
3. **Check ngrok URL** - Must be correct in Developer Console (no trailing slash)
4. Check ngrok is still running (free URLs expire after 2 hours)
5. Check your app is still running
6. Look at ngrok web interface (localhost:4040) to see if requests are arriving
7. Check your app logs for errors

**Common mistakes:**

```typescript theme={null}
// ❌ Wrong - packageName doesn't match Developer Console
packageName: 'com.example.myapp'  // Console has: 'com.mycompany.myapp'

// ❌ Wrong - incorrect API key
apiKey: 'old-api-key-here'

// ✅ Correct - matches Developer Console exactly
packageName: 'com.mycompany.myapp',
apiKey: process.env.MENTRA_API_KEY,
```

### Issue: "ngrok URL Changed"

**Problem:** You restarted ngrok and URL changed

**Solution:**

* **Free plan:** Update Developer Console with new URL each time
* **Paid plan:** Use reserved domains for persistent URLs
* **Alternative:** Deploy to Railway/Ubuntu for persistent URLs

***

## ngrok Free vs Paid

### Free Plan

* ✅ Unlimited tunnels
* ✅ Web interface
* ❌ URL changes each restart
* ❌ 40 connections/minute limit
* ❌ Random subdomain

### Paid Plans (starting \$8/month)

* ✅ Everything in Free
* ✅ **Reserved domains** - URL never changes
* ✅ Custom domains
* ✅ Higher limits
* ✅ More regions

For serious development, paid ngrok or deployment to Railway/Ubuntu is recommended.

***

## Alternatives to ngrok

### CloudFlare Tunnel

```bash theme={null}
cloudflared tunnel --url http://localhost:3000
```

* Free persistent URLs
* More complex setup
* Good for long-term development

### localtunnel

```bash theme={null}
npx localtunnel --port 3000
```

* Simpler than ngrok
* Less reliable
* Good for quick tests

### VS Code Port Forwarding

If using GitHub Codespaces or VS Code Remote:

* Built-in port forwarding
* No extra tools needed
* Limited to VS Code environment

***

## Next Steps

<CardGroup cols={2}>
  <Card title="Railway Deployment" icon="train" href="/app-devs/getting-started/deployment/railway-deployment">
    Deploy to production
  </Card>

  <Card title="Ubuntu Deployment" icon="server" href="/app-devs/getting-started/deployment/ubuntu-deployment">
    Self-hosted deployment
  </Card>

  <Card title="Quickstart Guide" icon="rocket" href="/app-devs/getting-started/quickstart">
    Build your first app
  </Card>

  <Card title="Example Apps" icon="code" href="/app-devs/getting-started/example-apps">
    See working examples
  </Card>
</CardGroup>
