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.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
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.
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-"));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);
});// 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
};
};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");
}
}
});// 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
};
};// 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
};
}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