Skip to main content

Route Definition

Routes define the navigable destinations in your application that can be accessed via voice commands.
type NavaiRoute = {
  name: string;
  path: string;
  description: string;
  synonyms?: string[];
};

Route Fields

name
string
required
Primary name for the route. Used for matching voice input.
name: 'profile'
path
string
required
URL path to navigate to when route is resolved.
path: '/user/profile'
description
string
required
Human-readable description. Included in the agent’s prompt to help understand the route’s purpose.
description: 'User profile page with account settings'
synonyms
string[]
Alternative names or translations. Useful for multilingual apps.
synonyms: ['perfil', 'account', 'mi cuenta']

Defining Routes

Static Route Array

import { NavaiRoute } from '@navai/voice-frontend';

const APP_ROUTES: NavaiRoute[] = [
  {
    name: 'home',
    path: '/',
    description: 'Main landing page'
  },
  {
    name: 'dashboard',
    path: '/dashboard',
    description: 'Analytics and metrics dashboard'
  },
  {
    name: 'profile',
    path: '/profile',
    description: 'User profile and settings',
    synonyms: ['account', 'settings', 'preferences']
  },
  {
    name: 'reports',
    path: '/reports',
    description: 'Financial reports and documents',
    synonyms: ['documents', 'files']
  }
];

Routes Module

Create a dedicated routes file:
// src/ai/routes.ts
import { NavaiRoute } from '@navai/voice-frontend';

export const NAVAI_ROUTE_ITEMS: NavaiRoute[] = [
  {
    name: 'home',
    path: '/',
    description: 'Home page'
  },
  {
    name: 'products',
    path: '/products',
    description: 'Product catalog',
    synonyms: ['catalog', 'items', 'shop']
  },
  {
    name: 'cart',
    path: '/cart',
    description: 'Shopping cart',
    synonyms: ['basket', 'checkout']
  },
  {
    name: 'orders',
    path: '/orders',
    description: 'Order history',
    synonyms: ['purchases', 'history']
  }
];

// Alternative export names also work:
// export const NAVAI_ROUTES = [...];
// export const APP_ROUTES = [...];
// export const routes = [...];
// export default [...];

Using Routes with Hook

import { useWebVoiceAgent } from '@navai/voice-frontend';
import { APP_ROUTES } from './ai/routes';

function VoiceNav() {
  const navigate = useNavigate();
  
  const { start } = useWebVoiceAgent({
    navigate,
    defaultRoutes: APP_ROUTES,
    moduleLoaders: {}
  });
  
  return <button onClick={start}>Start Voice</button>;
}

Route Resolution

resolveNavaiRoute

Resolves voice input to a route path using fuzzy matching.
import { resolveNavaiRoute } from '@navai/voice-frontend';

const routes = [
  { name: 'profile', path: '/profile', description: 'Profile page', synonyms: ['account'] },
  { name: 'settings', path: '/settings', description: 'Settings' }
];

// Exact path match
resolveNavaiRoute('/profile', routes); // '/profile'

// Exact name match
resolveNavaiRoute('profile', routes); // '/profile'

// Synonym match
resolveNavaiRoute('account', routes); // '/profile'

// Partial match
resolveNavaiRoute('prof', routes); // '/profile'

// Case-insensitive, accent-insensitive
resolveNavaiRoute('PROFILE', routes); // '/profile'
resolveNavaiRoute('perfil', routes); // null (no match)

// Unknown route
resolveNavaiRoute('unknown', routes); // null

Type Signature

function resolveNavaiRoute(
  input: string,
  routes: NavaiRoute[]
): string | null;

Resolution Strategy

1

Exact Path Match

Checks if input matches any route’s path exactly (normalized).
resolveNavaiRoute('/settings', routes); // matches path
2

Exact Name Match

Checks if input matches any route’s name exactly (normalized).
resolveNavaiRoute('settings', routes); // matches name
3

Synonym Match

Checks if input matches any route’s synonym exactly (normalized).
resolveNavaiRoute('preferences', routes); // matches synonym
4

Partial Name Match

Checks if any route’s name contains the input (normalized).
resolveNavaiRoute('sett', routes); // matches partial 'settings'
5

Partial Synonym Match

Checks if any route’s synonym contains the input (normalized).
resolveNavaiRoute('pref', routes); // matches partial 'preferences'
6

No Match

Returns null if no route matches.
resolveNavaiRoute('nonexistent', routes); // null

Normalization

Route resolution normalizes input by:
  1. Converting to lowercase
  2. Removing accents (NFD normalization)
  3. Trimming whitespace
// All resolve to the same route
resolveNavaiRoute('Profile', routes);
resolveNavaiRoute('PROFILE', routes);
resolveNavaiRoute(' profile ', routes);

Prompt Generation

getNavaiRoutePromptLines

Generates human-readable route descriptions for the agent’s system prompt.
import { getNavaiRoutePromptLines } from '@navai/voice-frontend';

const routes = [
  {
    name: 'home',
    path: '/',
    description: 'Home page'
  },
  {
    name: 'profile',
    path: '/profile',
    description: 'User profile',
    synonyms: ['account', 'settings']
  }
];

const lines = getNavaiRoutePromptLines(routes);
// [
//   '- home (/)',
//   '- profile (/profile), aliases: account, settings'
// ]

Type Signature

function getNavaiRoutePromptLines(routes: NavaiRoute[]): string[];

Usage in Agent Builder

This function is used internally by buildNavaiAgent to construct the agent’s instructions:
// Internal usage (from agent.ts)
const routeLines = getNavaiRoutePromptLines(options.routes);
const instructions = [
  'You are a voice assistant embedded in a web app.',
  'Allowed routes:',
  ...routeLines,
  'Rules:',
  '- If user asks to go/open a section, always call navigate_to.',
  '- Never invent routes that are not listed.'
].join('\n');

Real-World Examples

E-Commerce App

const STORE_ROUTES: NavaiRoute[] = [
  {
    name: 'home',
    path: '/',
    description: 'Store homepage'
  },
  {
    name: 'products',
    path: '/products',
    description: 'Browse all products',
    synonyms: ['catalog', 'shop', 'store', 'items']
  },
  {
    name: 'cart',
    path: '/cart',
    description: 'Shopping cart',
    synonyms: ['basket', 'bag']
  },
  {
    name: 'checkout',
    path: '/checkout',
    description: 'Checkout and payment',
    synonyms: ['pay', 'payment', 'purchase']
  },
  {
    name: 'orders',
    path: '/orders',
    description: 'Order history and tracking',
    synonyms: ['purchases', 'history']
  },
  {
    name: 'account',
    path: '/account',
    description: 'Account settings',
    synonyms: ['profile', 'settings', 'preferences']
  }
];

Dashboard App

const DASHBOARD_ROUTES: NavaiRoute[] = [
  {
    name: 'overview',
    path: '/dashboard',
    description: 'Main dashboard overview',
    synonyms: ['home', 'main', 'dashboard']
  },
  {
    name: 'analytics',
    path: '/dashboard/analytics',
    description: 'Analytics and metrics',
    synonyms: ['stats', 'statistics', 'metrics']
  },
  {
    name: 'reports',
    path: '/dashboard/reports',
    description: 'Generated reports',
    synonyms: ['documents', 'files']
  },
  {
    name: 'users',
    path: '/dashboard/users',
    description: 'User management',
    synonyms: ['accounts', 'people', 'team']
  },
  {
    name: 'settings',
    path: '/dashboard/settings',
    description: 'Application settings',
    synonyms: ['config', 'configuration', 'preferences']
  }
];

Multilingual App

const MULTILINGUAL_ROUTES: NavaiRoute[] = [
  {
    name: 'home',
    path: '/',
    description: 'Home page',
    synonyms: ['inicio', 'accueil', 'home'] // Spanish, French, English
  },
  {
    name: 'profile',
    path: '/profile',
    description: 'User profile',
    synonyms: [
      'perfil',      // Spanish
      'profil',      // French
      'account',     // English
      'mi cuenta',   // Spanish
      'mon compte'   // French
    ]
  },
  {
    name: 'settings',
    path: '/settings',
    description: 'Settings',
    synonyms: [
      'configuración', // Spanish
      'paramètres',    // French
      'ajustes'        // Spanish
    ]
  }
];

Best Practices

1

Use Clear, Descriptive Names

Choose route names that match how users naturally refer to pages.
// Good
{ name: 'profile', path: '/profile', description: 'User profile' }

// Avoid
{ name: 'usr_prof', path: '/profile', description: 'Profile' }
2

Include Common Synonyms

Add alternative names users might say.
{
  name: 'cart',
  synonyms: ['basket', 'bag', 'shopping cart']
}
3

Write Helpful Descriptions

Descriptions help the agent understand context.
// Good
description: 'Shopping cart with selected items and checkout options'

// Less helpful
description: 'Cart'
4

Support Multiple Languages

For international apps, include translations in synonyms.
{
  name: 'settings',
  synonyms: ['configuración', 'paramètres', 'preferences']
}
5

Test Route Resolution

Manually test common voice inputs to ensure routes resolve correctly.
console.log(resolveNavaiRoute('go to profile', routes));
console.log(resolveNavaiRoute('open settings', routes));
The voice agent uses the navigate_to tool to handle navigation commands. This tool:
  1. Receives voice input from the user (e.g., “go to profile”)
  2. Calls resolveNavaiRoute(input, routes) to find matching path
  3. If resolved, calls navigate(path) function
  4. Returns success or error message
// Internal implementation (from agent.ts)
const navigateTool = tool({
  name: 'navigate_to',
  description: 'Navigate to an allowed route in the current app.',
  parameters: z.object({
    target: z.string().min(1).describe('Route name or route path')
  }),
  execute: async ({ target }) => {
    const path = resolveNavaiRoute(target, options.routes);
    if (!path) {
      return { ok: false, error: 'Unknown or disallowed route.' };
    }
    options.navigate(path);
    return { ok: true, path };
  }
});
The agent is instructed to always use navigate_to when the user asks to go to a section. You don’t need to handle navigation manually.

Build docs developers (and LLMs) love