React + Vite
Create a Vite SPA, configure routing, and integrate with the API.
Use Vite for client-rendered React applications — internal tools, embeddable widgets, and lightweight SPAs that do not require SSR.
Create the project
pnpm create vite web-app --template react-ts
cd web-app
pnpm install
pnpm add react-router-dom zustand @aws-amplify/auth
pnpm devProject structure
src/
├── components/ # Shared UI components
├── features/ # Feature-specific modules
├── lib/ # API client, auth, utilities
├── stores/ # Zustand stores
├── routes/ # Route definitions
└── main.tsxEnvironment variables
VITE_API_URL=http://localhost:4000/api
VITE_COGNITO_USER_POOL_ID=us-east-1_xxxxx
VITE_COGNITO_CLIENT_ID=xxxxxxxx
VITE_COGNITO_DOMAIN=auth.company.comAPI client
// src/lib/api.ts
const BASE = import.meta.env.VITE_API_URL;
export async function apiFetch(path: string, options: RequestInit = {}) {
const token = await getAccessToken();
const res = await fetch(`${BASE}${path}`, {
...options,
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${token}`,
...options.headers,
},
});
if (!res.ok) throw new ApiError(res.status, await res.text());
return res.json();
}Routing with auth guards
// src/routes/index.tsx
import { createBrowserRouter } from 'react-router-dom';
import { ProtectedRoute } from './ProtectedRoute';
export const router = createBrowserRouter([
{ path: '/login', element: <LoginPage /> },
{
path: '/',
element: <ProtectedRoute><AppLayout /></ProtectedRoute>,
children: [
{ index: true, element: <Dashboard /> },
{ path: 'settings', element: <Settings /> },
],
},
]);Verify setup
pnpm lint && pnpm typecheck && pnpm test && pnpm build
pnpm devConfirm login, API calls, and route guards before opening a PR.