# nextjs-component > const axiosInstance = axios.create({ baseURL: process.env.NEXT_PUBLIC_API_BASE_URL || 'http://localhost:8000/api', }); - Author: irajfatima001 - Repository: irajfatima001/phase-03 - Version: 20260208223900 - Stars: 0 - Forks: 0 - Last Updated: 2026-02-08 - Source: https://github.com/irajfatima001/phase-03 - Web: https://mule.run/skillshub/@@irajfatima001/phase-03~nextjs-component:20260208223900 --- # Skill: nextjs-component **Name**: nextjs-component **Description**: Generates reusable Next.js TypeScript components with Tailwind, shadcn/ui, forms, and axios Bearer token API calls ## Purpose This skill generates reusable Next.js components using TypeScript, Tailwind CSS, shadcn/ui components, and axios for API calls with Bearer token authentication. The components follow modern best practices for state management, error handling, and responsive design. ## Allowed Tools - code_write - file_edit ## Implementation Instructions ### 1. Component Structure Create components in the `src/components` directory with the following structure: ``` components/ ├── ui/ │ ├── button.tsx │ ├── card.tsx │ ├── input.tsx │ └── ... ├── TaskCard.tsx ├── TaskForm.tsx ├── AuthButton.tsx └── ... ``` ### 2. Axios Instance with Interceptors ```typescript // src/lib/axios-instance.ts import axios from 'axios'; const axiosInstance = axios.create({ baseURL: process.env.NEXT_PUBLIC_API_BASE_URL || 'http://localhost:8000/api', }); // Add Bearer token to requests axiosInstance.interceptors.request.use( (config) => { const token = localStorage.getItem('better-auth-token'); // Or however you store the token if (token) { config.headers.Authorization = `Bearer ${token}`; } return config; }, (error) => { return Promise.reject(error); } ); // Handle token expiration axiosInstance.interceptors.response.use( (response) => response, (error) => { if (error.response?.status === 401) { // Handle token expiration (e.g., redirect to login) localStorage.removeItem('better-auth-token'); window.location.href = '/login'; } return Promise.reject(error); } ); export default axiosInstance; ``` ### 3. Example Component: TaskCard ```tsx // src/components/TaskCard.tsx import { Card, CardContent, CardFooter } from '@/components/ui/card'; import { Badge } from '@/components/ui/badge'; import { Button } from '@/components/ui/button'; import { Checkbox } from '@/components/ui/checkbox'; import { Task } from '@/types/task'; import { Trash2, Edit } from 'lucide-react'; import { useState } from 'react'; interface TaskCardProps { task: Task; onEdit: (task: Task) => void; onDelete: (taskId: number) => void; onToggleComplete: (taskId: number) => void; } export function TaskCard({ task, onEdit, onDelete, onToggleComplete }: TaskCardProps) { const [isLoading, setIsLoading] = useState(false); const handleDelete = async () => { setIsLoading(true); try { await onDelete(task.id); } finally { setIsLoading(false); } }; const handleToggleComplete = async () => { setIsLoading(true); try { await onToggleComplete(task.id); } finally { setIsLoading(false); } }; return (

{task.title}

{task.description && (

{task.description}

)}
{task.priority} {task.status}
); } ``` ### 4. Example Component: TaskForm ```tsx // src/components/TaskForm.tsx import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Input } from '@/components/ui/input'; import { Textarea } from '@/components/ui/textarea'; import { Button } from '@/components/ui/button'; import { Label } from '@/components/ui/label'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; import { Task } from '@/types/task'; import { useForm } from 'react-hook-form'; import { zodResolver } from '@hookform/resolvers/zod'; import { z } from 'zod'; const taskSchema = z.object({ title: z.string().min(1, 'Title is required'), description: z.string().optional(), priority: z.enum(['low', 'medium', 'high']), }); type TaskFormData = z.infer; interface TaskFormProps { task?: Task; onSubmit: (data: TaskFormData) => void; onCancel: () => void; isLoading?: boolean; } export function TaskForm({ task, onSubmit, onCancel, isLoading = false }: TaskFormProps) { const { register, handleSubmit, formState: { errors }, setValue, reset } = useForm({ resolver: zodResolver(taskSchema), defaultValues: { title: task?.title || '', description: task?.description || '', priority: task?.priority || 'medium', } }); const handleFormSubmit = (data: TaskFormData) => { onSubmit(data); reset(); // Reset form after submission }; return ( {task ? 'Edit Task' : 'Create Task'}
{errors.title && (

{errors.title.message}

)}