Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/danielitoCode/compose_svelted/llms.txt

Use this file to discover all available pages before exploring further.

NavController is the single source of truth for navigation state in a Compose Svelted application. It holds an array of NavBackStackEntry objects inside a Svelte writable store. Every call to navigate() or popBackStack() updates that store, which causes the NavHost subscribed to it to re-render the appropriate screen automatically. You will almost never instantiate NavController directly. The rememberNavController factory function is the recommended way to create one and is what all examples in this documentation use.

Types

Route

A route is a plain object with a single path string. It carries no behavior — it exists purely as a typed identifier that connects a controller call to a host registration.
export type Route<T = unknown> = {
  path: string; // e.g. "login", "home", "details"
};
Define your application’s routes as exported constants in a dedicated file so every screen can import them without circular dependencies.
routes.ts
export const Login   = { path: 'login' };
export const Home    = { path: 'home' };
export const Details = { path: 'details' };
Each entry in the backstack is a NavBackStackEntry. It records which route is active and carries any arguments that were passed when navigating to it.
export type NavBackStackEntry<T = unknown> = {
  route: string;
  args?: T;
};
The args field is typed generically, so you can pass any serializable payload — a record with an id, a filter object, or nothing at all.

rememberNavController

The preferred way to create a NavController. Accepts the path of the start destination and returns a fully initialised controller.
import { rememberNavController } from '@danielito1996/compose-svelted';

function rememberNavController(startDestination: string): NavController
Because the controller is plain JavaScript, you can create it at module scope inside a <script> block, store it in Svelte context, or pass it as a prop — it is just an object.
<script lang="ts">
  import { rememberNavController } from '@danielito1996/compose-svelted';
  import { Home } from './routes';

  const navController = rememberNavController(Home.path);
</script>

Constructor

new NavController(startDestination: string)
Initialises the backstack with a single entry { route: startDestination }. The underlying writable store is created once and never replaced, so all subscribers always reference the same store identity.
navigate<T = unknown>(route: string, args?: T): void
Pushes a new NavBackStackEntry onto the top of the backstack. NavHost reacts immediately and renders the component registered for route.
// Navigate without arguments
navController.navigate(Home.path);

// Navigate with a typed payload
navController.navigate(Details.path, { id: 42 });
Pass route paths via the path property of your route constants (e.g. Details.path) rather than bare string literals. This keeps navigation calls refactor-safe and removes the risk of typos.

popBackStack()

popBackStack(): void
Removes the top entry from the backstack, exposing the previous screen. If the backstack contains only one entry, this call is a no-op — the last screen can never be popped.
navController.popBackStack();

_getStackStore()

_getStackStore(): Writable<NavBackStackEntry[]>
Returns the internal Svelte writable store. This method is used internally by NavHost and is prefixed with an underscore to signal that it is not part of the public API. Avoid calling it in application code.

Reading arguments in a screen

When you navigate with arguments, the navBackStackEntry prop received by the target screen contains them under the args key. Destructure with a nullish fallback to handle the case where the screen is the start destination and no args were provided.
DetailsScreen.svelte
<script lang="ts">
  import { Column, Button, Text, Modifier, Arrangement, Alignment } from '@danielito1996/compose-svelted';

  export let navController;
  export let navBackStackEntry;

  const { id } = navBackStackEntry?.args ?? {};
</script>

<Column
  modifier={Modifier.fillMaxSize().padding(32)}
  verticalArrangement={Arrangement.Center}
  horizontalAlignment={Alignment.CenterVertically}
>
  <Text>Details Screen</Text>
  <Text>ID: {id}</Text>

  <Button onClick={() => navController.popBackStack()}>
    Back
  </Button>
</Column>

Complete example

The snippet below shows a self-contained navigation wrapper: routes are imported, a controller is created, and screens are wired up through NavHost.
MainNavigationWrapper.svelte
<script lang="ts">
  import {
    NavHost,
    composable,
    rememberNavController,
    Modifier
  } from '@danielito1996/compose-svelted';
  import { Login, Home, Details } from './routes';
  import LoginScreen   from './LoginScreen.svelte';
  import HomeScreen    from './HomeScreen.svelte';
  import DetailsScreen from './DetailsScreen.svelte';

  const navController = rememberNavController(Home.path);
</script>

<NavHost
  navController={navController}
  modifier={Modifier.fillMaxSize()}
  routes={[
    composable(Login,   () => LoginScreen),
    composable(Home,    () => HomeScreen),
    composable(Details, () => DetailsScreen)
  ]}
/>
Keep your NavController instance as close to the root of the screen tree as possible. Passing it down as a prop (or via Svelte context) to child screens is the intended pattern — every screen that needs to navigate simply calls methods on the controller it receives.

Build docs developers (and LLMs) love