CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-nuxt

Nuxt is a free and open-source framework with an intuitive and extendable way to create type-safe, performant and production-grade full-stack web applications and websites with Vue.js.

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

state.mddocs/

State Management

Reactive state management with server-side hydration, cookie management, and error handling. Nuxt provides powerful composables for managing application state that works seamlessly between server and client.

Capabilities

Reactive State

Create reactive shared state across components with automatic SSR hydration.

/**
 * Create reactive shared state across components
 * @param key - Optional key for the state (auto-generated if not provided)
 * @param init - Optional initial value factory function
 * @returns Reactive reference to the state
 */
function useState<T>(key?: string, init?: () => T): Ref<T>;

/**
 * Clear stored state by key(s) or filter function
 * @param keys - Keys to clear or filter function
 */
function clearNuxtState(keys?: string | string[] | ((key: string) => boolean)): void;

Usage Examples:

// Basic state
const counter = useState("counter", () => 0);

function increment() {
  counter.value++;
}

// Typed state
interface User {
  id: number;
  name: string;
  email: string;
}

const user = useState<User>("user", () => ({
  id: 0,
  name: "",
  email: ""
}));

// Auto-generated key
const theme = useState(() => "light");

// Computed state
const doubleCounter = computed(() => counter.value * 2);

// Complex state management
const todos = useState<Todo[]>("todos", () => []);

function addTodo(todo: Omit<Todo, "id">) {
  todos.value.push({
    ...todo,
    id: Date.now()
  });
}

function removeTodo(id: number) {
  const index = todos.value.findIndex(todo => todo.id === id);
  if (index > -1) {
    todos.value.splice(index, 1);
  }
}

// Clear state
function clearTodos() {
  clearNuxtState("todos");
}

// Clear multiple states
clearNuxtState(["counter", "user"]);

// Clear with filter
clearNuxtState((key) => key.startsWith("temp-"));

Cookie Management

Manage cookies with reactive updates and SSR support.

/**
 * Manage cookies with reactive updates and SSR support
 * @param name - Cookie name
 * @param opts - Cookie configuration options
 * @returns Reactive reference to cookie value
 */
function useCookie<T = string>(name: string, opts?: CookieOptions<T>): CookieRef<T>;

/**
 * Refresh a cookie value from the latest request
 * @param name - Cookie name to refresh
 */
function refreshCookie(name: string): void;

interface CookieOptions<T = string> {
  /** Default value factory */
  default?: () => T | Ref<T>;
  /** Deserialize cookie value */
  decode?: (value: string) => T;
  /** Serialize cookie value */
  encode?: (value: T) => string;
  /** Cookie domain */
  domain?: string;
  /** Cookie expiration date */
  expires?: Date;
  /** HTTP only flag */
  httpOnly?: boolean;
  /** Maximum age in seconds */
  maxAge?: number;
  /** Cookie path */
  path?: string;
  /** SameSite attribute */
  sameSite?: boolean | "lax" | "strict" | "none";
  /** Secure flag */
  secure?: boolean;
  /** Read-only cookie */
  readonly?: boolean;
  /** Watch for changes */
  watch?: boolean;
}

interface CookieRef<T> extends Ref<T> {
  /** Cookie value */
  value: T;
}

Usage Examples:

// Basic cookie
const token = useCookie("token");

// Set cookie value
token.value = "abc123";

// Typed cookie with default
const theme = useCookie<"light" | "dark">("theme", {
  default: () => "light"
});

// Object cookie with serialization
const userPrefs = useCookie<UserPrefs>("user-prefs", {
  default: () => ({ lang: "en", notifications: true }),
  encode: (value) => JSON.stringify(value),
  decode: (value) => JSON.parse(value)
});

// Secure cookie configuration  
const sessionId = useCookie("session-id", {
  httpOnly: true,
  secure: true,
  sameSite: "strict",
  maxAge: 60 * 60 * 24 * 7 // 7 days
});

// Read-only cookie
const csrfToken = useCookie("csrf-token", {
  readonly: true
});

// Cookie with custom domain and path
const subdomain = useCookie("subdomain-pref", {
  domain: ".example.com",
  path: "/app"
});

// Refresh cookie from server
refreshCookie("session-id");

// Watch cookie changes
watch(theme, (newTheme) => {
  document.documentElement.setAttribute("data-theme", newTheme);
});

Authentication State Example

// composables/useAuth.ts
interface User {
  id: number;
  name: string;
  email: string;
  role: string;
}

export const useAuth = () => {
  const user = useState<User | null>("auth.user", () => null);
  const token = useCookie("auth-token", {
    httpOnly: false, // Allow client access
    secure: true,
    sameSite: "strict",
    maxAge: 60 * 60 * 24 * 30 // 30 days
  });

  const isLoggedIn = computed(() => !!user.value);
  
  const login = async (credentials: LoginCredentials) => {
    try {
      const response = await $fetch("/api/auth/login", {
        method: "POST",
        body: credentials
      });
      
      user.value = response.user;
      token.value = response.token;
      
      await navigateTo("/dashboard");
    } catch (error) {
      throw createError({
        statusCode: 401,
        statusMessage: "Invalid credentials"
      });
    }
  };

  const logout = async () => {
    user.value = null;
    token.value = null;
    
    await $fetch("/api/auth/logout", {
      method: "POST"
    });
    
    await navigateTo("/login");
  };

  const refresh = async () => {
    if (!token.value) return;
    
    try {
      const response = await $fetch("/api/auth/me", {
        headers: {
          Authorization: `Bearer ${token.value}`
        }
      });
      
      user.value = response.user;
    } catch (error) {
      // Token invalid, clear auth state
      user.value = null;
      token.value = null;
    }
  };

  return {
    user: readonly(user),
    token: readonly(token),
    isLoggedIn,
    login,
    logout,
    refresh
  };
};

Error Handling

Comprehensive error handling with user-friendly error states.

/**
 * Get the current error state
 * @returns Reactive reference to current error
 */
function useError(): Ref<NuxtError | null>;

/**
 * Create a new Nuxt error object
 * @param err - Error message or partial error object
 * @returns Formatted Nuxt error
 */
function createError<DataT = any>(err: string | Partial<NuxtError<DataT>>): NuxtError<DataT>;

/**
 * Show an error and trigger error handling
 * @param error - Error to display
 * @returns The error object
 */
function showError<DataT = any>(error: string | Partial<NuxtError<DataT>>): NuxtError<DataT>;

/**
 * Clear the current error state
 * @param options - Optional redirect options
 * @returns Promise resolving when error is cleared
 */
function clearError(options?: { redirect?: string }): Promise<void>;

/**
 * Check if an error is a Nuxt error
 * @param error - Error to check
 * @returns Type predicate
 */
function isNuxtError<DataT = any>(error: unknown): error is NuxtError<DataT>;

interface NuxtError<DataT = any> {
  /** HTTP status code */
  statusCode: number;
  /** HTTP status message */
  statusMessage?: string;
  /** Error message */
  message: string;
  /** Stack trace */
  stack?: string;
  /** Additional error data */
  data?: DataT;
  /** Error cause */
  cause?: unknown;
}

Usage Examples:

// Get current error
const error = useError();

// Create and show errors
function handleApiError(response: Response) {
  if (response.status === 404) {
    throw createError({
      statusCode: 404,
      statusMessage: "Not Found",
      message: "The requested resource was not found"
    });
  }
  
  if (response.status >= 500) {
    throw createError({
      statusCode: 500,
      statusMessage: "Server Error",
      message: "An internal server error occurred"
    });
  }
}

// Show error manually
function showNotFoundError() {
  showError({
    statusCode: 404,
    statusMessage: "Page Not Found"
  });
}

// Clear error and redirect
async function goHome() {
  await clearError({ redirect: "/" });
}

// Error checking
try {
  await someAsyncOperation();
} catch (err) {
  if (isNuxtError(err)) {
    console.log("Nuxt error:", err.statusCode, err.message);
  } else {
    console.log("Unknown error:", err);
  }
}

// Global error handling
const error = useError();

watch(error, (newError) => {
  if (newError) {
    // Log error to monitoring service
    console.error("Application error:", newError);
    
    // Show user-friendly message
    if (newError.statusCode >= 500) {
      // Server error - show generic message
      showToast("Something went wrong. Please try again later.");
    } else if (newError.statusCode === 401) {
      // Unauthorized - redirect to login
      navigateTo("/login");
    }
  }
});

Shopping Cart Example

// composables/useCart.ts
interface CartItem {
  id: number;
  name: string;
  price: number;
  quantity: number;
  image?: string;
}

export const useCart = () => {
  const items = useState<CartItem[]>("cart.items", () => []);
  
  // Persist cart in cookie
  const cartCookie = useCookie<CartItem[]>("cart", {
    default: () => [],
    encode: (value) => JSON.stringify(value),
    decode: (value) => JSON.parse(value),
    maxAge: 60 * 60 * 24 * 30 // 30 days
  });

  // Sync state with cookie
  watch(items, (newItems) => {
    cartCookie.value = newItems;
  }, { deep: true });

  // Initialize from cookie
  if (cartCookie.value.length > 0) {
    items.value = cartCookie.value;
  }

  const totalItems = computed(() => 
    items.value.reduce((sum, item) => sum + item.quantity, 0)
  );

  const totalPrice = computed(() =>
    items.value.reduce((sum, item) => sum + (item.price * item.quantity), 0)
  );

  const isEmpty = computed(() => items.value.length === 0);

  const addItem = (product: Omit<CartItem, "quantity">) => {
    const existingItem = items.value.find(item => item.id === product.id);
    
    if (existingItem) {
      existingItem.quantity++;
    } else {
      items.value.push({ ...product, quantity: 1 });
    }
  };

  const removeItem = (id: number) => {
    const index = items.value.findIndex(item => item.id === id);
    if (index > -1) {
      items.value.splice(index, 1);
    }
  };

  const updateQuantity = (id: number, quantity: number) => {
    const item = items.value.find(item => item.id === id);
    if (item) {
      if (quantity <= 0) {
        removeItem(id);
      } else {
        item.quantity = quantity;
      }
    }
  };

  const clearCart = () => {
    items.value = [];
    cartCookie.value = [];
  };

  return {
    items: readonly(items),
    totalItems,
    totalPrice,
    isEmpty,
    addItem,
    removeItem,
    updateQuantity,
    clearCart
  };
};

Advanced State Patterns

// Composable factory pattern
function createStore<T>(key: string, initialValue: T) {
  const state = useState<T>(key, () => initialValue);
  
  const reset = () => {
    state.value = initialValue;
  };
  
  const clear = () => {
    clearNuxtState(key);
  };
  
  return {
    state,
    reset,
    clear
  };
}

// Usage
const { state: userSettings, reset: resetSettings } = createStore("settings", {
  theme: "light" as const,
  language: "en",
  notifications: true
});

// Shared state with validation
function useValidatedState<T>(
  key: string, 
  initialValue: T, 
  validator: (value: T) => boolean
) {
  const state = useState<T>(key, () => initialValue);
  
  const setValue = (newValue: T) => {
    if (validator(newValue)) {
      state.value = newValue;
    } else {
      throw createError({
        statusCode: 400,
        statusMessage: "Invalid state value"
      });
    }
  };
  
  return {
    value: readonly(state),
    setValue
  };
}

Types

type MaybeRef<T> = T | Ref<T>;

interface LoginCredentials {
  email: string;
  password: string;
}

interface UserPrefs {
  lang: string;
  notifications: boolean;
  theme?: "light" | "dark";
}

interface Todo {
  id: number;
  text: string;
  completed: boolean;
  createdAt: Date;
}

Install with Tessl CLI

npx tessl i tessl/npm-nuxt

docs

app-lifecycle.md

configuration.md

core.md

data-fetching.md

head.md

index.md

module-dev.md

navigation.md

performance.md

ssr.md

state.md

tile.json