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.