← Files ClerkARCHIVED FILE

skills/clerk-vue-patterns/references/vue-router-guards.md

1.62 KB · Sep 30, 2026 · 23:09 UTC

↓ Download file

# Vue Router Guards

For plain Vue (without Nuxt), protect routes using navigation guards.

## Global Before Guard

```ts
// router/index.ts
import { createRouter, createWebHistory } from 'vue-router'

const router = createRouter({
  history: createWebHistory(),
  routes: [
    { path: '/', component: Home },
    { path: '/sign-in', component: SignIn },
    { path: '/dashboard', component: Dashboard, meta: { requiresAuth: true } },
  ],
})

router.beforeEach(async (to) => {
  if (!to.meta.requiresAuth) return true

  const { userId } = useAuth()

  if (!userId.value) return '/sign-in'
  return true
})
```

## Per-Route Guard with In-Component Guard

```vue
<script setup lang="ts">
import { useAuth } from '@clerk/vue'
import { useRouter } from 'vue-router'
import { watchEffect } from 'vue'

const { isSignedIn, isLoaded } = useAuth()
const router = useRouter()

watchEffect(() => {
  if (isLoaded.value && !isSignedIn.value) {
    router.replace('/sign-in')
  }
})
</script>
```

## Org-Gated Route

```ts
router.beforeEach(async (to) => {
  if (!to.meta.requiresOrg) return true

  const { userId } = useAuth()
  const { organization } = useOrganization()

  if (!userId.value) return '/sign-in'
  if (!organization.value) return '/select-org'
  return true
})
```

## CRITICAL

- Call composables outside of the guard function body if possible — `useAuth()` is reactive and works outside components in Vue 3 (when called in setup context or at module level after plugin install)
- `isLoaded` must be true before trusting `isSignedIn` — guard may fire before Clerk initializes
- For Nuxt, prefer `middleware/` instead of manual router guards

SHA-256: eefab96fcd45daf8ffa669f26c91094bfa12c35f50ec0ce7ebdccc9cb5647b8c