Skip to main content

Routing

This service provides helpers for routing and handling document.title.

buildRoute​

buildRoute provides type-safe path building for pages in the app. It includes auto-complete for path names and will require path parameters to be included if they are present in the URL.

import { buildRoute } from '@rhapsody/routing'

buildRoute('/analytics')
buildRoute('/coaching/:id/calls', { id: '12345' })

history​

history is a global singleton created using createBrowserHistory from v4 of the history library.

DocumentTitle​

We can use DocumentTitle to update the current page's document title in the browser. The text provided as children to DocumentTitle will be prepended to the string | Salesloft, e.g. <DocumentTitle>Home</DocumentTitle> results in the document title Home | Salesloft. If no text is provided, the fallback title Salesloft will be used, e.g. <DocumentTitle /> results in the document title Salesloft.

import React from 'react'
import { DocumentTitle } from '@rhapsody/routing'

function PageComponent() {
return (
<>
<DocumentTitle>Page XYZ</DocumentTitle>
<div>{/* Additional page content here */}</div>
</>
)
}

How Routing Works in Rhapsody​

Local Development Environment​

The routing system in Rhapsody works in multiple layers:

1. Nginx Layer (First Contact)​

The first routing happens through the infrastructure/server/src/nginx/default.conf file. At this level:

  • All server requests are initially directed to https://$host/app
  • Several security headers are added to protect the application
  • Specific legacy routes are handled (like /live_calls and /leaving)

2. Express Server Layer​

The next layer is an Express server (infrastructure/server/src/serverDev.ts) which:

  • Redirects all requests from https://$host to /app
  • Handles static file serving
  • Sets up development middleware
  • Configures CORS and other security measures
  • Proxies requests to the Melody service when needed

3. Frontend Application Layer​

Finally, routing reaches the frontend application (platform/internal/navigation/src/Content/Content.tsx). Here, routes are constructed based on registrations made through the @rhapsody/app-registry package. Routes are processed in this order:

  1. Standard redirects (from getAllRegisteredRedirects)
  2. Settings section redirects
  3. Main application routes
  4. Settings routes
  5. Root path (/) handling
  6. 404 handling for unmatched routes

The root path (/) has special handling through LicenseRedirectTracker which:

  • Checks if the collaboration license platform is enabled
  • Redirects users without 'cadence' feature to /conversation-intelligence
  • Otherwise redirects to /dashboard

If no route matches the user's request, the Handle404Redirect component:

  • Logs the error with additional context
  • Redirects the user to /dashboard

Development Container Environment​

When running in a development container:

  • The system works similarly to the local environment
  • A Docker image is created using .devcontainer/Dockerfile
  • The container connects to networks created by the local environment setup
  • Development dependencies and tools are included in the container

QA and Production Environment​

For QA and production:

  • A production Docker image is built using the root Dockerfile
  • The build process happens in two stages:
    1. Build Stage: Compiles and bundles the application
    2. Deploy Stage: Creates a lightweight Nginx-based image
  • The image is exported to SalesLoft's registry for use with Kubernetes

Route Registration System​

Routes can be registered in two main ways:

  1. Through registerRoutes for general application routes
  2. Through registerSettingsSection for settings-related routes

The system validates all routes to ensure:

  • They start with a forward slash
  • They contain only valid characters
  • There are no duplicate routes
  • Settings sections have all required properties
caution

After creating new routes, you must run pnpm generate-routes to ensure type definitions are properly generated. Failing to do this will cause TypeScript errors and prevent proper type checking for route paths.