Nuxt Guide

State Management

How reactive state is managed without an external state library.

There is no external state management library (no Pinia, no Vuex). State is managed using Vue's built-in reactivity APIs and Nuxt's useState.

Global State — useState

Use useState when state needs to be shared across multiple components or pages without prop drilling. The key string is the unique identifier — the same key anywhere in the app returns the same reactive ref.

// Set / initialize (typically in a composable or middleware)
const currentUser = useState<TUser | null>('currentUser', () => null)

// Read anywhere — same key returns the same reactive ref
const currentUser = useState<TUser | null>('currentUser')

Establish a clear set of global state keys per project:

KeyTypeDescription
'currentUser'TUser | nullLogged-in user object
'currentOrganization'any | nullOrg loaded by middleware
'tenant'{ slug: string } | nullSubdomain slug (multi-tenant only)
'tenantNotFound'booleanWhether tenant org exists

Local State — ref and reactive

Use ref for primitives and single values; reactive for objects:

// Primitives
const isLoading   = ref(false)
const searchQuery = ref('')
const selectedId  = ref<string | null>(null)

// Form objects — reactive so properties are individually bindable
const form = reactive({
  firstName: '',
  lastName: '',
  email: '',
})

const errors = reactive({
  firstName: '',
  email: '',
})

Authentication tokens are stored in cookies managed by useCookie. Cookie config (expiry, secure, sameSite) comes from runtimeConfig.public.cookieConfig:

const token = useCookie<string | null>('accessToken', cookieConfig)

// Set
token.value = response.accessToken

// Clear
token.value = null

Dialog / Modal State

Modal visibility is kept as a reactive object per page — one object, multiple boolean flags:

const dialogs = reactive({
  view:   false,
  edit:   false,
  delete: false,
})

// Open
dialogs.view = true

// Close (from child emit)
function onClose() {
  dialogs.view  = false
  selected.value = null
}

Do's and Don'ts

✅ Do❌ Don't
Use useState('key') for cross-component stateCreate a separate store file
Use reactive for form objectsUse ref for objects you need to destructure
Use useCookie for tokensStore tokens in localStorage
Clear state on logout (null assignments)Leave stale state after session end
Co-locate state with the composable that manages itScatter useState calls across random components