React setup
Use when initializing a new React frontend with Vite to connect to a Django backend over HTTPS. Sets up routing, CSRF protection, Axios config, and validates the build. Not for existing React projects.From its SKILL.md
npx -y skills add otoshek/Claude-Code-Toolkit --skill react-setupAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 2 stars2 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
6.7 KB, as published. Nobody here has run it
Overview
Sets up a production-ready React + Vite frontend configured for Django backend integration with:
- HTTPS local development (using mkcert certificates)
- CSRF token handling for Django session auth
- Axios interceptors for automatic CSRF injection
- React Router with layout structure
- Production build validation
When to use: New React projects that need Django backend connectivity When NOT to use: Existing React projects, non-Django backends, or projects not using session auth
Prerequisites
- Django backend configured with HTTPS
- mkcert certificates in
/certs/directory (usemkcert-https-setupskill) - Node.js 18+ installed
Copy this checklist and track your progress:
- 1. Initialize React + Vite Project
- 2. Configure vite.config.js:
- 3. Create API Configuration
- 4. Create CSRF Service
- 5. Create Axios Configuration
- 6. Create Navbar and Footer Components
- 7. Create
src/layouts/Root.jsx: - 8. Create Page Components
- 9. Create
src/router/AppRoutes.jsx - 10. Create Router Wrapper
- 11. Update App.jsx
- 12. Verify Setup
- Initialize React + Vite Project
npm create vite@latest frontend -- --template react --yesnpm --prefix ./frontend install react-router-dom axios
-
Configure vite.config.js:
-
List cert files in
certs/to find actual filenames -
Read existing
frontend/vite.config.js(created by Vite) -
Add imports:
fs,path -
Add server config:
- server.https: Load key/cert from
certs/using found filenames - server.port: 5173
- server.proxy:
/api→https://localhost:8000(changeOrigin: true, secure: false)
- server.https: Load key/cert from
- Create API Configuration
src/config/api.js:
export const API_BASE_URL = ''; // Empty string uses Vite proxy
export const ENDPOINTS = {
CSRF: '/api/csrf/',
// Add your API endpoints here as you build features
// Example: PRODUCTS: '/api/products/',
};
- Create CSRF Service
src/services/csrf.js:
import { ENDPOINTS } from '../config/api';
let csrfToken = null;
/**
* Fetches and caches the CSRF token from Django backend
* The token is stored in a cookie by Django after the first request
*/
export async function getCsrfToken() {
// Return cached token if available
if (csrfToken) {
return csrfToken;
}
try {
const response = await fetch(ENDPOINTS.CSRF, {
credentials: 'include',
headers: {
'Accept': 'application/json',
}
});
if (!response.ok) {
throw new Error(`Failed to fetch CSRF token: ${response.status}`);
}
// Django sets the token in a cookie after this request
const cookies = document.cookie.split(';');
const csrfCookie = cookies.find(cookie => cookie.trim().startsWith('csrftoken='));
if (!csrfCookie) {
throw new Error('CSRF token not found in cookies');
}
csrfToken = csrfCookie.split('=')[1].trim();
return csrfToken;
} catch (error) {
console.error('CSRF token fetch error:', error);
throw error;
}
}
/**
* Clears the cached CSRF token (useful for logout or token refresh)
*/
export function clearCsrfToken() {
csrfToken = null;
}
- Create Axios Configuration
src/services/api.js:
import axios from 'axios';
import { API_BASE_URL } from '../config/api';
import { getCsrfToken } from './csrf'; // ADD THIS
const axiosInstance = axios.create({
baseURL: API_BASE_URL,
withCredentials: true,
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
}
});
// REQUEST INTERCEPTOR
axiosInstance.interceptors.request.use(
async (config) => {
if (['post', 'put', 'patch', 'delete'].includes(config.method.toLowerCase())) {
const csrfToken = await getCsrfToken();
config.headers['X-CSRFToken'] = csrfToken;
}
return config;
}
);
// Response interceptor
axiosInstance.interceptors.response.use(
response => response,
error => {
console.error('API request failed:', error);
return Promise.reject(error);
}
);
export default axiosInstance;
- Create Navbar and Footer Components
Create src/components/Navbar.jsx:
export default function Navbar() {
return (
<nav>
<h1>My App</h1>
</nav>
);
}
Create src/components/Footer.jsx:
export default function Footer() {
return (
<footer>
<p>© {new Date().getFullYear()} My App. All rights reserved.</p>
</footer>
);
}
- Create
src/layouts/Root.jsx:
import { Outlet } from 'react-router-dom';
import Navbar from '../components/Navbar';
import Footer from '../components/Footer';
export default function Root() {
return (
<div>
<Navbar />
<main>
<Outlet />
</main>
<Footer />
</div>
);
}
- Create Page Components
Create src/components/BackendStatus.jsx:
- Import axios from
../services/api, useState, useEffect - Initialize state:
status = "checking...",error = null - useEffect hook (runs on mount):
- First:
axios.get('/api/csrf/')to initialize cookies - Second:
axios.get('/api/health/')using same axios instance - Success path: update status with backend message
- Error path: set error state, display "Backend unreachable"
- First:
- Component is presentational only (no routing/layout logic)
Create src/pages/Home.jsx:
- Render
<BackendStatus /> - Add heading + text explaining the backend connectivity check
-
Create
src/router/AppRoutes.jsx: -
Export
createAppRouter()function -
Returns route config array: Root layout at "/" with Home page as nested "/" child route
-
Imports:
Rootfrom../layouts/Root,Homefrom../pages/Home
-
Create
src/router/index.jsx: -
Export default
AppRoutercomponent -
Create browser router from
createAppRouter()config -
Return
<RouterProvider router={router} /> -
Imports:
createBrowserRouter,RouterProviderfrom react-router-dom,createAppRouterfrom./AppRoutes
- Update
src/App.jsx:
- Remove: All useState, demo imports (reactLogo, viteLogo, App.css), counter UI
- Add imports:
Routerfrom./router - Render:
<Router />
- Verify Setup
Run npm --prefix ./frontend run build to validate imports, dependencies, and syntax
Common issues:
- Missing certs: Check
/certs/directory exists with .pem files - Module not found: Verify all imports use correct paths
- CSRF errors: Ensure Django backend is running at
https://localhost:8000