Skip to main content
Route guards let you control who can access different parts of your application. They’re perfect for implementing role-based access control, feature flags, and authentication requirements.

What Are Guards?

Guards are functions that run before a page renders. They can:
  • Allow access with pass()
  • Block access with hidden() (shows 404)
  • Redirect with redirectTo(path)
Guards execute in order and stop at the first non-pass result.

Basic Guard Syntax

Common Guard Patterns

Authentication Guard

Redirect unauthenticated users to login:

Role-Based Access Control

Hide pages from users without proper roles:
When a guard returns hidden(), the page shows a 404 error and doesn’t appear in navigation. This prevents unauthorized users from knowing the page exists.

Feature Flag Guard

Hide features that aren’t enabled:

Setting Up Context Data

Guards access data through the context parameter. Here’s how to set it up:
1

Define Context Type

Create a type definition file:
2

Pass Context to AppShell

Provide the context data when initializing AppShell:
3

Access in Guards

Now your guards are fully type-safe:

Real-World Example: Admin-Only Page

Here’s a complete working example from the App Shell source code:
Behavior:
  • Admin users see the page in navigation and can access it
  • Non-admin users don’t see it in navigation
  • Direct URL access shows 404 for non-admins

Chaining Multiple Guards

Guards execute in order. Use this for complex access control:
Guards stop at the first non-pass result. In this example, unauthenticated users are redirected before the role check runs.

Guards on Resources

Apply guards to individual resources:

Controlling UI Elements with WithGuard

Use the WithGuard component to conditionally render UI elements based on the same guard logic:
WithGuard only supports pass() and hidden(). It does not support redirectTo(). For redirects, use route-level guards.

Async Guards

Guards can be asynchronous for checking permissions from an API:
App Shell automatically shows a loading state while async guards execute.

Default Redirects

Redirect module landing pages to a default resource:

Testing Guards

Test guards by simulating different context values:

Best Practices

Security

  • Never trust client-side guards alone - Always verify permissions on your backend
  • Guards only hide UI elements; backend validation is essential
  • Use hidden() for sensitive features to avoid information disclosure

Organization

  • Keep guards in a separate guards.ts file
  • Create reusable guard factories for common patterns
  • Document what each guard protects and why

Performance

  • Keep guards fast - they run on every navigation
  • Cache permission checks when possible
  • Use async guards sparingly (they add loading time)