Skip to main content
COSMOS RSC provides client-side navigation through the Navigation API, allowing instant page transitions without full page reloads. The simplest way to navigate is using standard HTML <a> tags. COSMOS RSC automatically intercepts clicks and performs client-side navigation:
export default function Navigation() {
  return (
    <nav>
      <a href='/' className='text-blue-600 hover:underline'>
        Home
      </a>
      <a href='/about' className='text-blue-600 hover:underline'>
        About
      </a>
      <a href='/features/forms' className='text-blue-600 hover:underline'>
        Forms Demo
      </a>
    </nav>
  );
}
No special Link component is needed - regular anchors work out of the box.

Programmatic navigation with useRouter

For client components that need to navigate programmatically, use the useRouter hook:
'use client';

import { useRouter } from '#cosmos-rsc/client';

export function NavigateButton() {
  const router = useRouter();

  const handleClick = () => {
    router.navigate('/dashboard');
  };

  return <button onClick={handleClick}>Go to Dashboard</button>;
}

Router API

The router object provides:
interface Router {
  // Navigate to a new URL
  navigate(url: string): void;

  // Go back in history
  back(): void;

  // Go forward in history
  forward(): void;

  // Reload the current page
  reload(): void;
}
Example usage:
'use client';

import { useRouter } from '#cosmos-rsc/client';

export function NavigationControls() {
  const router = useRouter();

  return (
    <div className='flex gap-2'>
      <button onClick={() => router.back()}>Back</button>
      <button onClick={() => router.forward()}>Forward</button>
      <button onClick={() => router.reload()}>Reload</button>
      <button onClick={() => router.navigate('/home')}>Home</button>
    </div>
  );
}

Adding view transitions

COSMOS RSC supports React’s ViewTransition component for smooth animations during navigation. The demo includes a NavigationTransition component that wraps content for animated transitions:
app/components/navigation-transition.js
import { ViewTransition } from 'react';

export function NavigationTransition({ children }) {
  return (
    <ViewTransition
      default={{
        'navigation-back': 'navigation-back',
        'navigation-forward': 'navigation-forward',
      }}
    >
      {children}
    </ViewTransition>
  );
}

Using NavigationTransition in pages

Wrap page headings or sections with NavigationTransition for smooth transitions:
app/pages/features/forms.js
import { NavigationTransition } from '../../components/navigation-transition';

export default function FormsPage() {
  return (
    <div className='mx-auto max-w-4xl px-4 py-12'>
      <NavigationTransition>
        <h1 className='mb-8 text-3xl font-bold'>Server Actions Form Demo</h1>
      </NavigationTransition>

      <a href='/' className='text-blue-500 hover:underline'>
        Back to Home
      </a>

      {/* Rest of page content */}
    </div>
  );
}

Defining transition animations

Define custom animations in your globals.css:
app/globals.css
@import 'tailwindcss';

@keyframes enter-slide-right {
  0% {
    opacity: 0;
    translate: -200px 0;
  }
  100% {
    opacity: 1;
    translate: 0 0;
  }
}

@keyframes exit-slide-left {
  0% {
    opacity: 1;
    translate: 0 0;
  }
  100% {
    opacity: 0;
    translate: -200px 0;
  }
}

::view-transition-new(.navigation-back) {
  animation: enter-slide-right ease-in 0.25s;
}

::view-transition-old(.navigation-back) {
  animation: exit-slide-left ease-in 0.25s;
}
This creates a sliding animation when navigating backward. The direction is determined by the browser’s Navigation API.

How it works

COSMOS RSC’s client navigation:
  1. Intercepts link clicks - The framework listens for clicks on <a> tags
  2. Updates the URL - Uses the Navigation API to change the browser URL
  3. Fetches RSC payload - Requests the new page as an RSC stream from the server
  4. Updates the UI - React renders the new page components
  5. Maintains state - Client components preserve their state during navigation
The Navigation API triggers view transitions automatically. COSMOS RSC leverages this to provide smooth animations without additional JavaScript.

Best practices

Always use <a> tags for navigation, not <button> or <div> with click handlers. This ensures:
  • Proper accessibility
  • Right-click to open in new tab works
  • Search engines can crawl your links
Use short durations (200-300ms) for navigation transitions. Long animations can feel sluggish.
Apply NavigationTransition to main headings or hero sections for maximum impact. Wrapping too much content can make animations overwhelming.
COSMOS RSC pages work with JavaScript disabled - navigation falls back to full page loads. Test this to ensure your app remains accessible.

Example: Full navigation pattern

Here’s a complete example combining links, transitions, and the router:
app/pages/index.js
import { NavigationTransition } from '../components/navigation-transition';

export default function HomePage() {
  return (
    <div className='mx-auto max-w-4xl px-4 py-12'>
      <NavigationTransition>
        <h1 className='mb-8 text-4xl font-bold'>COSMOS RSC Features</h1>
      </NavigationTransition>

      <div className='space-y-6'>
        <section>
          <h2 className='mb-4 text-2xl font-semibold'>
            Feature Demonstrations
          </h2>
          <ul className='space-y-3'>
            <li>
              <a
                href='/features/server-components'
                className='text-blue-600 hover:underline'
              >
                Server Components Demo
              </a>
              <p className='mt-1 text-gray-600'>
                Showcase of React Server Components with async data fetching
              </p>
            </li>
            <li>
              <a
                href='/features/streaming'
                className='text-blue-600 hover:underline'
              >
                Streaming SSR Demo
              </a>
              <p className='mt-1 text-gray-600'>
                Server-side streaming rendering with Suspense
              </p>
            </li>
          </ul>
        </section>
      </div>
    </div>
  );
}

Build docs developers (and LLMs) love