🚧 Glyx is pre-release software. APIs may change before v1.0. Get started →
Documentation
Guides
Routing

Routing Stable

Glyx ships with @glyx-dev/router — a named-route history-stack router built for native desktop apps. It uses the same mental model as React Navigation: a stack of { name, params } entries with no URLs.

Desktop apps have no URL bar, so file-based URL routing is not a good fit. @glyx-dev/router uses named routes — fast, simple, and works offline.

Install

npm install @glyx-dev/router

Setup

Declare routes with <Route> components inside <Router>:

import { Router, Route } from '@glyx-dev/router'
import HomeScreen from './screens/HomeScreen'
import DetailScreen from './screens/DetailScreen'
import SettingsScreen from './screens/SettingsScreen'
 
export default function App() {
  return (
    <Router initialRoute="home">
      <Route name="home"     component={HomeScreen} />
      <Route name="detail"   component={DetailScreen} />
      <Route name="settings" component={SettingsScreen} />
    </Router>
  )
}

initialRoute sets the first screen. If omitted, the first declared <Route> is used.

Navigating between screens

import { useNavigate } from '@glyx-dev/router'
 
function HomeScreen() {
  const navigate = useNavigate()
 
  return (
    <Pressable onPress={() => navigate('detail', { id: 42 })}>
      <Text>Open detail</Text>
    </Pressable>
  )
}

navigate(name, params?, opts?):

CallEffect
navigate('detail', { id: 42 })Push detail screen with params
navigate('back')Pop current screen (back)
navigate('home', {}, { replace: true })Replace current screen

Reading route params

import { useRoute } from '@glyx-dev/router'
 
function DetailScreen() {
  const { routeName, params, canGoBack } = useRoute()
 
  return (
    <View style={{ flex: 1, padding: 24 }}>
      <Text>Route: {routeName}</Text>
      <Text>ID: {params.id}</Text>
    </View>
  )
}

useRoute() returns:

FieldTypeDescription
routeNamestring | nullCurrent route name
paramsobjectParams passed to navigate()
canGoBackbooleantrue when history stack has more than one entry

Back button

import { useNavigate, useRoute } from '@glyx-dev/router'
import { Pressable, Text } from '@glyx-dev/react'
 
function BackButton() {
  const navigate = useNavigate()
  const { canGoBack } = useRoute()
 
  if (!canGoBack) return null
 
  return (
    <Pressable onPress={() => navigate('back')}>
      <Text>← Back</Text>
    </Pressable>
  )
}

Active route highlighting

import { useRoute, useNavigate } from '@glyx-dev/router'
 
function NavItem({ route, label }: { route: string; label: string }) {
  const { routeName } = useRoute()
  const navigate = useNavigate()
  const isActive = routeName === route
 
  return (
    <Pressable onPress={() => navigate(route)}>
      <Text style={{ color: isActive ? '#8B5CF6' : '#A9A9B8' }}>{label}</Text>
    </Pressable>
  )
}

Sidebar layout with router

A common pattern for desktop apps — persistent sidebar navigation alongside a routed content area:

import { Router, Route, useNavigate, useRoute } from '@glyx-dev/router'
import { View, Text, Pressable } from '@glyx-dev/react'
 
function SidebarItem({ route, label }: { route: string; label: string }) {
  const { routeName } = useRoute()
  const navigate = useNavigate()
 
  return (
    <Pressable
      onPress={() => navigate(route)}
      style={{
        paddingVertical: 10,
        paddingHorizontal: 16,
        backgroundColor: routeName === route ? '#8B5CF620' : 'transparent',
        borderRadius: 6,
      }}
    >
      <Text style={{ color: routeName === route ? '#8B5CF6' : '#A9A9B8' }}>{label}</Text>
    </Pressable>
  )
}
 
function Layout() {
  return (
    <View style={{ flex: 1, flexDirection: 'row' }}>
      {/* Sidebar */}
      <View style={{ width: 200, backgroundColor: '#1a1a24', padding: 12 }}>
        <SidebarItem route="home"     label="Home" />
        <SidebarItem route="notes"    label="Notes" />
        <SidebarItem route="settings" label="Settings" />
      </View>
 
      {/* Content — Router renders the active screen here */}
      <View style={{ flex: 1 }}>
        <Router initialRoute="home">
          <Route name="home"     component={HomeScreen} />
          <Route name="notes"    component={NotesScreen} />
          <Route name="settings" component={SettingsScreen} />
        </Router>
      </View>
    </View>
  )
}

TypeScript

Type your params with a route map:

type Routes = {
  home: {}
  detail: { id: number }
  settings: {}
}

Then narrow params in screens:

function DetailScreen() {
  const { params } = useRoute()
  const { id } = params as Routes['detail']
  // ...
}

Full API

ExportDescription
<Router initialRoute?>Router container. Renders the active screen.
<Route name component>Route declaration. Always renders null itself.
useNavigate()Returns navigate(name, params?, opts?)
useRoute()Returns { routeName, params, canGoBack }