Best Practices
To get the most out of BoltFetch in a production application, follow these architectural best practices.
1. Singleton Configuration for APIs
If you are interacting with a specific API service, you shouldn't use the raw boltfetch object everywhere, as you would need to repeat the base URL and authentication headers continuously.
Instead, create a configured instance in a dedicated file and export it.
typescript// src/lib/api.ts import { configureBoltFetchClient } from "boltfetch"; export const apiClient = configureBoltFetchClient({ baseUrl: process.env.NEXT_PUBLIC_API_URL || "https://api.myapp.com/v1", globalConfig: { timeout: 10000, headers: { "Accept": "application/json", } }, requestInterceptor: (config) => { const token = localStorage.getItem('token'); if (token) { config.headers = { ...config.headers, Authorization: `Bearer ${token}` }; } return config; } });
2. The Repository Pattern
To keep your UI components clean, avoid calling your apiClient directly inside them. Instead, abstract your network requests into dedicated service/repository files.
textsrc/ ├── lib/ │ └── api.ts # BoltFetch configuration ├── services/ │ ├── UserService.ts # All user-related API calls │ └── ProductService.ts # All product-related API calls └── components/ └── UserProfile.tsx # Imports UserService
Example UserService.ts
typescriptimport { apiClient } from "@/lib/api"; import type { User } from "@/types/user"; export const UserService = { getUser: async (id: string) => { return apiClient.get<User>(`/users/${id}`); }, updateProfile: async (id: string, payload: Partial<User>) => { return apiClient.patch<User>(`/users/${id}`, payload); } };
3. Handle Errors Early
Take advantage of BoltFetch's linear control flow. Check !response.success immediately after making a call.
typescriptconst response = await UserService.getUser("123"); if (!response.success) { // Handle the error (show toast, log to sentry, etc.) showErrorToast(response.message); return; } // Proceed with business logic updateUI(response.data);