Frontend Fetch Patterns
Sending the token with every request
Section titled “Sending the token with every request”After the spartan-login event fires, the JWT is in localStorage['spartan-token']. Wrap your fetch calls to include it automatically:
async function apiFetch(path: string, options: RequestInit = {}): Promise<Response> { const token = localStorage.getItem('spartan-token'); return fetch(path, { ...options, headers: { 'Content-Type': 'application/json', ...options.headers, ...(token ? { Authorization: `Bearer ${token}` } : {}), }, });}Use it like regular fetch:
const response = await apiFetch('/api/profile');const profile = await response.json();Global 401 handling (fully-authenticated apps)
Section titled “Global 401 handling (fully-authenticated apps)”For applications where every page requires authentication, you can intercept all 401 responses globally by overriding window.fetch:
// Place in your app's entry point (e.g., main.ts or App.vue)const { fetch: originalFetch } = window;
window.fetch = async (...args) => { const response = await originalFetch(...args); if (!response.ok && response.status === 401) { localStorage.removeItem('spartan-token'); if (!window.location.pathname.startsWith('/login')) { window.location.href = '/login'; } } return response;};Per-request 401 handling (partially-public apps)
Section titled “Per-request 401 handling (partially-public apps)”For apps with both public and protected content, handle authentication failures at the call site:
async function fetchProtected(path: string) { const response = await apiFetch(path); if (response.status === 401) { // Token expired or invalid — redirect to login localStorage.removeItem('spartan-token'); window.location.href = '/login'; return null; } return response.json();}Axios interceptor
Section titled “Axios interceptor”If you’re using Axios instead of fetch:
import axios from 'axios';
// Request interceptor: attach tokenaxios.interceptors.request.use((config) => { const token = localStorage.getItem('spartan-token'); if (token) { config.headers.Authorization = `Bearer ${token}`; } return config;});
// Response interceptor: handle 401axios.interceptors.response.use( (response) => response, (error) => { if (error.response?.status === 401) { localStorage.removeItem('spartan-token'); window.location.href = '/login'; } return Promise.reject(error); });Checking authentication status
Section titled “Checking authentication status”To check whether the user is currently authenticated (e.g., to conditionally render UI):
function isAuthenticated(): boolean { return localStorage.getItem('spartan-token') !== null;}